Springバッチを呼び出すSpring MVCコントローラをテストするJUnitテストを実行すると、次の例外が発生します。ジョブ。ジョブには2つのタスクレットが含まれています。最初にファイル&からDBに書き込んでDBを更新します。どちらのタスクレットも同じDBを使用します。私が見る限り、例外はデータソースが閉じられていると私に伝えますが、DBでは最初のタスクレットが実行されているのに対し、2番目のタスクレットは実行されていません。Springバッチジョブを呼び出すControllerをユニットテストするときに "SQLException:データソースが閉じられています"
2番目のタスクレット(DBへの更新)中にデータソースが閉じられている(???)の理由を教えてください。
ブラウザからコントローラを呼び出すと、ジョブは両方のタスクレットを実行します。
ERROR [taskExecutor-1] (AbstractJob.java:306) - Encountered fatal error executing job
org.springframework.batch.core.JobExecutionException: Flow execution ended unexpectedly
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:141)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:281)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.batch.core.job.flow.FlowExecutionException: Ended flow=writeProductsJob at state=writeProductsJob.readWrite with exception
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:152)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:124)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
... 5 more
Caused by: org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Data source is closed
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:240)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy27.getStepExecutionCount(Unknown Source)
at org.springframework.batch.core.job.SimpleStepHandler.shouldStart(SimpleStepHandler.java:210)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:117)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:61)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:144)
... 7 more
Caused by: java.sql.SQLException: Data source is closed
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1362)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:202)
... 18 more
Exception in thread "taskExecutor-1" org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLException: Data source is closed
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:240)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy27.update(Unknown Source)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:329)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:120)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.sql.SQLException: Data source is closed
at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1362)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:202)
... 11 more
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.628 sec
UPDATE:
テストクラス:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-test.xml"})
public class UploadFileValidatorTest {
@Autowired
private ApplicationContext applicationContext;
private MockMultipartHttpServletRequest request;
private MockHttpServletResponse response;
@Autowired
private MyController controller;
private MessageSource messageSource;
@Before
public void setUp() {
request = new MockMultipartHttpServletRequest();
response = new MockHttpServletResponse();
}
@Test
@DirtiesContext
public void testDoSomething() throws Exception {
DiskFileItem fileItem = null;
final File TEST_FILE = applicationContext.getResource("classpath:csv_example.txt").getFile();
try
{
fileItem = (DiskFileItem) new DiskFileItemFactory().createItem("fileData", "text/plain", true, TEST_FILE.getName());
InputStream input = new FileInputStream(TEST_FILE);
OutputStream os = fileItem.getOutputStream();
int ret = input.read();
while (ret != -1)
{
os.write(ret);
ret = input.read();
}
os.flush();
System.out.println("diskFileItem.getString() = " + fileItem.getString());
}
catch (Exception e)
{
e.printStackTrace();
}
/////////////////////////////////////////////////////////////////////
request.addFile(multipartFile);
request.addParameter("email", "[email protected]");
request.setRequestURI("/book/upload.html");
final ModelAndView mav = new AnnotationMethodHandlerAdapter().handle(request, response, controller);
BindingResult bindException = (BindingResult) mav.getModel().get(BindingResult.MODEL_KEY_PREFIX + "uploadFile");
for (Object object : bindException.getAllErrors()) {
if(object instanceof FieldError) {
FieldError fieldError = (FieldError) object;
assertEquals(fieldError.getField(), "fileData");
System.out.println(messageSource.getMessage((FieldError) object, null));
}
}
}
}
バッチ設定:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
<property name="transactionManager" ref="transactionManager" />
</bean>
<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
<property name="jobRepository" ref="jobRepository" />
<property name="taskExecutor" ref="taskExecutor"/>
</bean>
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="5" />
</bean>
UPDATE 2:
私はtestDoSomething()
試験方法の最後に次のコードを追加しようとしました:今、全体のジョブが実行され
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
int activeCount = threadGroup.activeCount();
Thread[] list = new Thread[activeCount];
threadGroup.enumerate(list);
for (Thread thread : list) {
if (thread.getName().startsWith("taskExecutor")) {
System.out.println("WAITING FOR THREAD: " + thread.getName());
try {
thread.join();
}
catch (InterruptedException ignore) {}
}
}
が、testDoSomething()
は決して終わらない、それは死ぬことtaskExecutor
スレッドの永遠に待つように思えます。 taskExecutor
が決して死なない理由は何ですか?
:2つのランチャーを定義する 例。そのメソッドにブレークポイントを設定し、誰がそれを呼び出す責任があるのか確認できますか?私はそれが 'ApplicationContext.close()'であると確信しています...また、統合テストはどのように見えますか?あなたはSpringのコンテキストをどうやって始めますか? –
私の元の投稿の下部にある**更新**をご覧ください。 – rapt
@ Tomasz Nurkiewicz - あなたが見ることができるように、ジョブはコントローラのスレッド(およびjunitテスト)とは別のスレッドで実行するように定義されています。したがって、コントローラスレッドが終了すると、junitはすべてのオープンリソース(オープンデータソースなど)を閉じます。ジョブスレッドが終了するまで、junitにリソースのクローズを待つように指示するにはどうすればよいですか? – rapt