ThreadPoolTaskExecutor error-Nullpointer

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
royjaydAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

dpearsonCommented:
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
mccarlIT Business Systems Analyst / Software DeveloperCommented:
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
royjaydAuthor Commented:
>>>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
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

mccarlIT Business Systems Analyst / Software DeveloperCommented:
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
royjaydAuthor Commented:
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
mccarlIT Business Systems Analyst / Software DeveloperCommented:
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
royjaydAuthor Commented:
>>>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
mccarlIT Business Systems Analyst / Software DeveloperCommented:
> 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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dpearsonCommented:
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
royjaydAuthor Commented:
0
royjaydAuthor Commented:
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.