The Spring MVC application needs to execute an intensive computation job which takes several minutes. The client wants to run this job in asynchronous way. But after I enable the @Async annotation on the method (see code 1) and get the error (see code 2). My web.xml and web-appliaiton-context.xml are also presented below. I tried to find a workaround to fix this, but failed. Please help.
code 1:
@Service
public class AsyncServiceImpl implements AsyncServiceInt{
protected int pertArrSize = 1000;
@Autowired
protected TblvDao tblvDao1 = null;
@Override
@Async
public void startSlowProcess(Integer scenarioId) throws SecurityException, IllegalArgumentException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
batchUpdateSummaryPertSim(scenarioId);
}
public void batchUpdateSummaryPertSim(Integer scenarioId) throws SecurityException, IllegalArgumentException, IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException
{
double[] summaryArry = new double[pertArrSize];
summaryArry = summaryPertSim_env(scenarioId, summaryArry);
}
@Transactional
private double[] summaryPertSim_env(Integer scenarioId,
double[] summaryArry) throws IOException, ClassNotFoundException, SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
ScenarioTblv scenario = tblvDao1.getScenarioTblv(scenarioId);
TblvResultSaved savedResult = scenario.getTblvResultSaved();
TblvScenarioCategory4 tblvScenarioCategory4 = new TblvScenarioCategory4();
List<TblvScenarioCategory4> tblvScenarioCategory4List = scenario
.getTblvScenarioCategory4List();
Double min = 0.0, max = 0.0, ml = 0.0;
Integer conf = 4;
if (savedResult.getEnvDist() != null) {
byte[] st = (byte[]) savedResult.getEnvDist();
ByteArrayInputStream baip = new ByteArrayInputStream(st);
ObjectInputStream ois = new ObjectInputStream(baip);
summaryArry = (double[]) ois.readObject();
} else {
for (int i = 0; i < tblvScenarioCategory4List.size(); i++) {
tblvScenarioCategory4 = tblvScenarioCategory4List.get(i);
vTblvScenarioEffectChoose v = tblvDao1
.getvTblvScenarioEffectChooseById(tblvScenarioCategory4
.getId());
if (v.getC1id() == 1) {
tblvScenarioCategory4.setImpactYearlyUnitsSim(pertArrSize);
min = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.getLowValue();
max = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.getHighValue();
ml = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.getMostValue();
conf = tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue().getConf();
if ((conf == null) || (conf == 0))
conf = 4;
double[] MOPertArr;
MOPertArr = getPertArry(min, max, ml, conf, pertArrSize);
double[] benefitResult = new double[pertArrSize];
for (int j = 0; j < pertArrSize; j++) {
tblvScenarioCategory4.setSimIndex(j);
tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.setHighValue(MOPertArr[j]);
benefitResult[j] = tblvScenarioCategory4.getHighPvSum();
summaryArry[j] = summaryArry[j] + benefitResult[j];
}
tblvScenarioCategory4
.getTblvEffectScenarioImpactUnitValue()
.setHighValue(max);
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(summaryArry);
byte[] summaryArryAsBytes = baos.toByteArray();
savedResult.setEnvDist(summaryArryAsBytes);
tblvDao1.saveTblvResultSaved(savedResult);
}
return summaryArry;
}
code 2:
10:26:06,233 ERROR org.hibernate.LazyInitializationException:42 - failed to lazily initialize a collection of role: com.pb.prism.model.db.ScenarioTblv.tblvScenarioCategory4List, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.pb.prism.model.db.ScenarioTblv.tblvScenarioCategory4List, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
at com.pb.prism.util.AsyncServiceImpl.summaryPertSim_env(AsyncServiceImpl.java:446)
at com.pb.prism.util.AsyncServiceImpl.batchUpdateSummaryPertSim(AsyncServiceImpl.java:41)
at com.pb.prism.util.AsyncServiceImpl.startSlowProcess(AsyncServiceImpl.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:80)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>com.pb.prism.listener.MTAServletContextListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/web-application-context.xml</param-value>
</context-param>
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Enables Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>encoding-filter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding-filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- Handles all requests into the application -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value />
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
</web-app>
web-appliation-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.pb.prism" />
<!-- Imports the configurations of the different infrastructure systems of the application -->
<import resource="data-access-context.xml" />
<import resource="security-context.xml" />
<import resource="webmvc-context.xml" />
<bean id="applicationContextProvider" class="com.pb.prism.context.ApplicationContextProvider"></bean>
<!-- Configure the multipart resolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="2000000"/>
</bean>
<task:annotation-driven executor="myExecutor" />
<task:executor id="myExecutor" pool-size="5"/>
</beans>