Spring MVC中的TaskExecutor不是异步的

时间:2015-11-02 21:17:49

标签: spring-mvc asynchronous future websphere-8 spring-4

workmanager在管理控制台中定义,池大小最小为1和5。网络应用程序具有以下配置。

Web.xml中

<web-app id="RestController" metadata-complete="true" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>rest-controller</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>rest-controller</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

应用程序的context.xml

`<!-- Empty. I moved all the servlet related entities from here -->`

休息 - 控制器-servlet.xml中

 <context:component-scan base-package="com.package.main-pack" />    
 <task:annotation-driven executor="taskExecutor"/>  
 <mvc:annotation-driven />  
 <task:executor id="taskExecutor" pool-size="5" /> 

RestController.java

@RequestMapping(value = "/reportFake", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Override
public List<String> searchFake() {
    List<String> stringArr = new ArrayList<String>();
    for (String folder : foldername) {
        Future<String> result = reportLookup.doParallelFake(folder);
        try {
            while (true) {
                if (result.isDone()) {
                    stringArr.add(result.get());
                    Logger.debug(RestController.class,
                            "Executed and Returned");
                    break;
                }
            }
        } catch (InterruptedException e) {
            Logger.error(RestController.class, e.getMessage());
        } catch (ExecutionException e) {
            Logger.error(RestController.class, e.getMessage());
        }
    }
    return stringArr;
}

ReportLookupExecutor.java

@Service("reportLookup")
public class ReportLookupExecutor implements ReportLookupIntf {

@Async("taskExecutor")
@Async("taskExecutor")
@Override
public Future<String> doParallelFake(String folder) {
    logger.debug("Execute method asynchronously - "
            + Thread.currentThread().getName());

    try {
        Thread.sleep(5000);
        return new AsyncResult<String>("Folder Name :: " + folder);
    } catch (InterruptedException e) {
        logger.error(e);
    }
    return null;
}

输出

[11/4/15 12:41:24:349 EST] 0000014d SystemOut     O [DEBUG] 04 Nov 12:41:24 PM taskExecutor-1  Execute method asynchronously - taskExecutor-1
[11/4/15 12:41:29:365 EST] 0000007b SystemOut     O [DEBUG] 04 Nov 12:41:29 PM WebContainer : 3  Executed and Returned
[11/4/15 12:41:29:366 EST] 0000014e SystemOut     O [DEBUG] 04 Nov 12:41:29 PM taskExecutor-2  Execute method asynchronously - taskExecutor-2
[11/4/15 12:41:34:365 EST] 0000007b SystemOut     O [DEBUG] 04 Nov 12:41:34 PM WebContainer : 3  Executed and Returned

现在,我试图关注this link。 我手动抛出一个异常来检查堆栈跟踪,发现它是由ibm.asynchbeans运行的,并且被Spring正式截获。这是堆栈跟踪的片段。

at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
at java.lang.reflect.Method.invoke(Method.java:611)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:97)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:314)
at java.util.concurrent.FutureTask.run(FutureTask.java:149)
at org.springframework.scheduling.commonj.DelegatingWork.run(DelegatingWork.java:61)
at com.ibm.ws.asynchbeans.J2EEContext.run(J2EEContext.java:1178)
at com.ibm.ws.asynchbeans.WorkWithExecutionContextImpl.go(WorkWithExecutionContextImpl.java:199)
at com.ibm.ws.asynchbeans.CJWorkItemImpl.run(CJWorkItemImpl.java:236)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1862)

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

OK!最后我能够让它运行起来。解决方案是在获取未来的第一个值之前,对async方法进行所有调用次数。我能够通过创建一个Future of Future对象来做到这一点。这就是最终调用类的外观。

<强> RestController.java

@RequestMapping(value = "/reportFake", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Override
public List<String> searchFake() throws InterruptedException,
        ExecutionException {
    List<Future<String>> futureArr = new ArrayList<Future<String>>();
    for (String folder : new String[] { "One", "Two", "Three", "Four" }) {
        futureArr.add(reportLookup.doParallelFake(folder));
    }
    List<String> stringArr = new ArrayList<String>();
    for (Future<String> future : futureArr) {
        stringArr.add(future.get());
    }
    return stringArr;
}