Solved

ThreadPoolTaskExecutor error-Nullpointer

Posted on 2012-03-12
11
1,065 Views
Last Modified: 2012-03-28
hi guys
trying to use ThreadPoolTaskExecutor  but its failing in my java


in spring xml i defined

   <bean id="hcrExportTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
		<property name="corePoolSize" value="4" /> 
		<property name="maxPoolSize" value="5" /> 
		<!-- <property name="queueCapacity" value="25" />-->
   </bean>

Open in new window



In java, i am injecting it

public class AMDController {
private ThreadPoolTaskExecutor hcrExportTaskExecutor;
public void setHcrExportTaskExecutor(ThreadPoolTaskExecutor hcrExportTaskExecutor) { 
this.hcrExportTaskExecutor = hcrExportTaskExecutor;
	  }
...

....

public ModelAndView loadAMDBody(HttpServletRequest request, HttpServletResponse response) throws ServletException {
try {
results = amdService.loadBody();				
ArrayList<VO> bodyDataList  = (ArrayList<VO>) results.get("CUR"); 
final ArrayList<VO> dataList = bodyDataList;
hcrExportTaskExecutor.execute(new Runnable(){
public void run(){
export(dataList);    
	}
});
}	
} catch (Exception e) {
    e.printStackTrace();
	}
    }
}

Open in new window


e.printStackTrace(); prints


java.lang.NullPointerException
      at adm.controller.AMDController.loadAMDBody(AMDController.java:552)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:421)
      at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:136)
      at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:326)
      at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:313)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:875)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
      at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
      at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
      at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
      at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
      at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26)
      at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
      at com.citi.gdos.iris.app.filter.SessionTimeoutFilter.doFilter(SessionTimeoutFilter.java:153)
      at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
      at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27)
      at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:42)
      at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3496)
      at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
      at weblogic.security.service.SecurityManager.runAs(Unknown Source)
      at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
      at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
      at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
      at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
      at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)


any idea what the problem is?

thanks
0
Comment
Question by:royjayd
  • 5
  • 4
  • 2
11 Comments
 
LVL 26

Expert Comment

by:dpearson
ID: 37713094
NullPointerExceptions are a pain because they don't show in the exception exactly which object was null.

Step 1 is to look at the line number:
at adm.controller.AMDController.loadAMDBody(AMDController.java:552)

this tells you that the problem is at line 552 of AMDController.java.

Find that line (alas we can't do that from your snippet of code) and you will probably see the problem.

E.g. If it turns out the line is:
      results = amdService.loadBody();

then the exception will be because amdService is null here.

Once you figure out which object is null, then you need to figure out why it's not being initialized correctly - which means looking further up in the AMDController object to where these variables are initialized.

Doug
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37713160
Did you set the task executor as a property of your controller? eg.

<bean id="amdController" class="adm.controller.AMDController">
		<property name="amdService" ref="amdService" /> 
		<property name="hcrExportTaskExecutor" ref="hcrExportTaskExecutor" />
</bean>

Open in new window


(Make sure line 3 above is in your definition of your amdController bean. The rest of what I have put there is just my assumption of how your amdController bean is defined)
0
 

Author Comment

by:royjayd
ID: 37714590
>>>The rest of what I have put there is just my assumption of how your amdController bean is defined

I think you got up a good point.

actually we are using annotations

@Service("amdController")
public class AMDController {
..
}
Any idea how i can inject it using annotations?

thanks
0
 
LVL 35

Expert Comment

by:mccarl
ID: 37717897
Ah, ok, then you need some sort of autowiring. Which way you choose depends on which version of Spring you are using, and if you plan on having multiple different ThreadPoolTaskExecutors defined in your config.

Look at the @Autowired, @Qualifier, @Resource, @Inject and @Value annotations for the different combination of ways of doings this. I would probably suggest just using

@Resource(name="hcrExportTaskExecutor")

annotation on the setter method in your controller, though, based on some assumptions that I would make about how you would use this.

(Oh and you may need a <context:annotation-config/> in your XML if the above doesn't work as is)
0
 

Author Comment

by:royjayd
ID: 37720742
alright, thanks.

I am trying to understand what happens internally when this block of code is executed

final ArrayList<VO> dataList = bodyDataList;
hcrExportTaskExecutor.execute(new Runnable(){
public void run(){
export(dataList);    
      }
});
}

export(datalist) is the task.
corePoolSize is 4 , so 4 threads are created by JVM to process the task? How exactly are the threads created behind the scenes?      

maxPoolSize is set to 5..how is this setting useful?

thanks
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 35

Expert Comment

by:mccarl
ID: 37723314
See the doco here for full info but basically...

corePoolSize will be the minimum number of threads held open in the pool
maxPoolSize will be the maximum number of threads opened at any one time

What happens in your case, if the above task is the only thing running on this TaskExecutor, and the invocations of that task never overlap (ie. the previous call finishes before any other call to .execute() is made), then the pool will only ever have 4 threads sitting there idle, waiting for the next task to run. But if you have overlap of tasks, then 5 tasks will be allowed to run (on 5 different threads) but then the 6th "execute"d tasks will be put on the "work queue" and will wait for a free thread before it will run. And also, the number of tasks allowed to be queued can be set, and if this is exceeded then the call to execute gets rejected (again see the doc for exactly how this happens)

To answer you questions more fully...
> so 4 threads are created by JVM to process the task?

4 threads are created, but only 1 will ever process each task. This isn't some magic way of getting multithreaded processing, if that is what you were thinking :)  However, if you submit 4 separate tasks, then yes those 4 tasks will execute concurrently (as long as previous tasks have finished)

> How exactly are the threads created behind the scenes?
I'm not sure what you are asking here, the TaskExecutor creates/manages standard Java threads allowing submitted tasks to run on them when requested, within the above limits. Is there something else you are wanting to know in this regard?

> maxPoolSize is set to 5..how is this setting useful?
See above, hopefully it should be clearer now,m let us if not.
0
 

Author Comment

by:royjayd
ID: 37723370
>>>4 threads are created, but only 1 will ever process each task

Ok. This is my code (as posted above)

public ModelAndView loadAMDBody(HttpServletRequest request, HttpServletResponse response) throws ServletException {
try {
results = amdService.loadBody();                        
ArrayList<VO> bodyDataList  = (ArrayList<VO>) results.get("CUR");
final ArrayList<VO> dataList = bodyDataList;
hcrExportTaskExecutor.execute(new Runnable(){
public void run(){
export(dataList);    
      }
});
}      
} catch (Exception e) {
    e.printStackTrace();
      }
    }
}

In the above code 'export(dataList);'   is the task which is wrapped within the run()
method. So this task is distributed among 4 threads. These 4 threads process the task
in parallel. Is my understanding correct?

>>the TaskExecutor creates/manages standard Java threads allowing submitted tasks to run on them when requested..
I wanted to know exactly what code is used internally to create/manage the java threads and submit the task (to the threads). something like thread.start() ?

thanks!

** I have opened other related questions on multithreading. Your response will be greatly appreciated.
0
 
LVL 35

Accepted Solution

by:
mccarl earned 300 total points
ID: 37723405
> So this task is distributed among 4 threads. These 4 threads process the task
in parallel. Is my understanding correct?

Your understanding MAY be correct but it is a bit hard to tell from the way to you write (or the way I am reading it! ;)

The .execute(...) call (which contains your export(dataList) call) gets called for each servlet request that loadAMDBody(...) processes. ie. I guess that there is a URL that gets mapped to this controller method, and if one person tries to access that URL, then loadAMDBody(...) gets called ONCE. Hence, the .execute() method gets called ONCE, which submits the ONE task (and the task is to call export(dataList)). That ONE task will be executed by ONE thread, no matter what setting that you have for pool sizes, etc. However, that thread will be different to the one that is running the loadAMDBody(...) method, and so the loadAMDBody method will complete straight away, and export(dataList) is left to finish executing after however long it takes.

Where the pooling part of it comes in, is if FOUR people were to invoke the URL that maps to the loadAMDBody controller method, then the controller method is invoked FOUR times (whether this is sequential or in parallel, is completely up to your servlet container), either way the .execute(...) method will be called FOUR times, with one task each, and these FOUR tasks will run in parallel on the FOUR threads maintained by the TaskExecutor's thread pool.

So in summary, in your statement that I quoted above, if by "So this task" you are talking about only ONE task instance (ie. resulting from one URL request), then NO it won't be distributed among threads, it will run on 1 thread but it is a different thread to the loadAMDBody methods thread and so that method completes immediately, and the task completes at some point after that. If by "So this task" you are talking about the task in general, and this task get instantiated multiple times, say from multiple simultaneous URL requests, then YES, each instance of the task will run on it's own thread (up to 5 of them at least), and these 5 are still separate from the loadAMDBody methods thread, so it still completes for each URL request, and then each task completes at some time later.


I'm not sure why you need to know HOW the threads are create/start threads but it would have to be something like that. The source code should be available for the libraries, so you can check if that is important to you.

> thanks!
No worries!! Hope I can help... ;)
0
 
LVL 26

Assisted Solution

by:dpearson
dpearson earned 200 total points
ID: 37723447
Each call to loadAMDBody() with run on only 1 thread.

So to get 4 threads running at once you need 4 calls to loadAMDBody().  If there's only 1 call it will only execute on one thread.

>>  wanted to know exactly what code is used internally to create/manage the java threads and submit the task (to the threads). something like thread.start() ?

If you're really interested this is how it's ultimately done:

    private void ensureQueuedTaskHandled(Runnable command) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        boolean reject = false;
        Thread t = null;
        try {
            int state = runState;
            if (state != RUNNING && workQueue.remove(command))
                reject = true;
            else if (state < STOP &&
                     poolSize < Math.max(corePoolSize, 1) &&
                     !workQueue.isEmpty())
                t = addThread(null);
        } finally {
            mainLock.unlock();
        }
        if (reject)
            reject(command);
        else if (t != null)
            t.start();
    }

That's a bunch of pretty sophisticated code but the basic idea is it creates a thread if necessary (depending on the intended pool size) and then as you guessed ends with:

            t.start();

To start it.

Doug
0
 

Author Closing Comment

by:royjayd
ID: 37763973
0
 

Author Comment

by:royjayd
ID: 37778239
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

INTRODUCTION Working with files is a moderately common task in Java.  For most projects hard coding the file names, using parameters in configuration files, or using command-line arguments is sufficient.   However, when your application has vi…
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now