Spring-batch exception: org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [] was registered - spring-batch

I am seeing this exception when stopping a running job using jobOperator.stop(id) or when I want to restart it using jobOperator.restart(id).
I don't have any idea why the MapJobRegistry is empty ... Am I missing a step ?
I have reproduced the problem using the complete example from https://github.com/spring-guides/gs-batch-processing.git
#Configuration
#EnableBatchProcessing
public class BatchConfiguration {
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
// end::setup[]
#Autowired
JobRepository jobRepository;
// tag::readerwriterprocessor[]
#Bean
public FlatFileItemReader<Person> reader() {
return new FlatFileItemReaderBuilder<Person>()
.name("personItemReader")
.resource(new ClassPathResource("sample-data.csv"))
.delimited()
.names(new String[]{"firstName", "lastName"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
setTargetType(Person.class);
}})
.build();
}
#Bean
public PersonItemProcessor processor() {
return new PersonItemProcessor();
}
#Bean
public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
return new JdbcBatchItemWriterBuilder<Person>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)")
.dataSource(dataSource)
.build();
}
// end::readerwriterprocessor[]
// tag::jobstep[]
#Bean
public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
return jobBuilderFactory.get("importUserJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(step1)
.end()
.build();
}
#Bean
public Step step1(JdbcBatchItemWriter<Person> writer) {
return stepBuilderFactory.get("step1")
.<Person, Person> chunk(10)
.reader(reader())
.processor(processor())
.writer(writer)
.build();
}
// end::jobstep[]
#Bean
public JobLauncher simpleJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}
The rest controller
#RestController
public class BatchController {
Logger logger = LoggerFactory.getLogger(BatchController.class);
#Autowired
JobLauncher simpleJobLauncher;
#Autowired
Job importUserJob;
#Autowired
JobOperator jobOperator;
#RequestMapping("/startNewJob")
public String handle() {
try {
JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
.toJobParameters();
JobExecution jobExecution = simpleJobLauncher.run(importUserJob, jobParameters);
return jobExecution.toString();
} catch (Exception e) {
logger.info(e.getMessage());
return ("An error has occured, please check the logs");
}
}
#RequestMapping("/stopJob/{id}")
public Boolean stopJob(#PathVariable Long id) throws Exception {
logger.info("stopJob "+id);
return jobOperator.stop(id);
}
#RequestMapping("/restartJob/{id}")
public Long restartJob(#PathVariable Long id) throws Exception {
logger.info("restartJob "+id);
return jobOperator.restart(id);
}
}
Stacktrace while restarting the job
2020-11-12 21:47:16.452 ERROR 26252 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [importUserJob] was registered] with root cause
org.springframework.batch.core.launch.NoSuchJobException: No job configuration with the name [importUserJob] was registered
at org.springframework.batch.core.configuration.support.MapJobRegistry.getJob(MapJobRegistry.java:68) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at com.sun.proxy.$Proxy68.getJob(Unknown Source) ~[na:na]
at org.springframework.batch.core.launch.support.SimpleJobOperator.restart(SimpleJobOperator.java:275) ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobOperator$$FastClassBySpringCGLIB$$44ee6049.invoke() ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:685) ~[spring-aop-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobOperator$$EnhancerBySpringCGLIB$$853e8727.restart() ~[spring-batch-core-4.2.1.RELEASE.jar:4.2.1.RELEASE]
at com.example.batchprocessing.BatchController.restartJob(BatchController.java:60) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]

The JobOperator requires a JobLocator to locate jobs to restart, stop, etc. This JobLocator (typically a MapJobRegistry) should be populated with known jobs, and this should be done either manually or by adding a JobRegistryBeanPostProcessor to the application context.
This is explained in the reference documentation here: JobRegistry.

I simply added a JobRegistryBeanPostProcessor and set it the jobRegistry.
#Autowired
JobRegistry jobRegistry;
#Bean
public JobRegistryBeanPostProcessor jobRegistryBeanPostProcessor() {
JobRegistryBeanPostProcessor postProcessor = new JobRegistryBeanPostProcessor();
postProcessor.setJobRegistry(jobRegistry);
return postProcessor;
}

You can also trigger job using jobLauncher. Here is a blog explaining it.
In short you can refer to this code.
#Component
public class JobScheduler
{
#Autowired
JobLauncher jobLauncher;
#Qualifier("jobBeanName") // if you have multiple jobs
#Autowired
Job job;
#Scheduled(cron = "* * * * * *")
public void runJob() {
jobLauncher.run(job, new JobParameters());
}
}

Related

Spring batch - Could not commit JDBC transaction; nested exception is java.sql.SQLTransactionRollbackException

I am using spring cloud data flow 2.7.1 with mysql 5.7.24 which executes a task with job related. the architecture used is Externalizing Batch Process Execution - remote partitioning (manger,worker) each partition is read from rabbitmq and there are several consumers connected by each worker (at the moment we use 1 worker with 2 consumers), sometimes there are partitions that fail with deadlock
org.springframework.transaction.TransactionSystemException: Could not commit JDBC transaction; nested exception is java.sql.SQLTransactionRollbackException: (conn=2542684) Deadlock found when trying to get lock; try restarting transaction
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:334) ~[spring-jdbc-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744) ~[spring-tx-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:712) ~[spring-tx-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at jdk.internal.reflect.GeneratedMethodAccessor407.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) ~[spring-aop-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) ~[spring-aop-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127) ~[spring-batch-core-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at com.sun.proxy.$Proxy95.commit(Unknown Source) ~[na:na]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:152) ~[spring-tx-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258) ~[spring-batch-core-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208) ~[spring-batch-core-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at org.springframework.batch.integration.partition.StepExecutionRequestHandler.handle(StepExecutionRequestHandler.java:64) ~[spring-batch-integration-4.2.1.RELEASE.jar!/:4.2.1.RELEASE]
at jdk.internal.reflect.GeneratedMethodAccessor421.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper$HandlerMethod.invoke(MessagingMethodInvokerHelper.java:1092) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.invokeHandlerMethod(MessagingMethodInvokerHelper.java:581) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:477) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:355) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:108) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:95) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:127) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:170) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:73) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:453) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:403) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:444) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractMessageProducingHandler.doProduceOutput(AbstractMessageProducingHandler.java:318) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:266) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:229) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:133) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:170) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:73) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:453) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:403) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109) ~[spring-messaging-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:198) ~[spring-integration-core-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter.access$600(AmqpInboundChannelAdapter.java:61) ~[spring-integration-amqp-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$Listener.createAndSend(AmqpInboundChannelAdapter.java:266) ~[spring-integration-amqp-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$Listener.onMessage(AmqpInboundChannelAdapter.java:232) ~[spring-integration-amqp-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1579) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1498) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer$$Lambda$795/000000003D931C00.invokeListener(Unknown Source) ~[na:na]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1486) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1477) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1421) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:958) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:908) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:81) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1279) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1185) ~[spring-rabbit-2.2.3.RELEASE.jar!/:2.2.3.RELEASE]
at java.base/java.lang.Thread.run(Thread.java:836) ~[na:na]
Caused by: java.sql.SQLTransactionRollbackException: (conn=2542684) Deadlock found when trying to get lock; try restarting transaction
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:244) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getException(ExceptionMapper.java:171) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.MariaDbStatement.executeExceptionEpilogue(MariaDbStatement.java:248) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.MariaDbStatement.executeInternal(MariaDbStatement.java:338) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.MariaDbStatement.execute(MariaDbStatement.java:389) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.MariaDbConnection.commit(MariaDbConnection.java:755) ~[mariadb-java-client-2.4.4.jar!/:na]
at com.zaxxer.hikari.pool.ProxyConnection.commit(ProxyConnection.java:366) ~[HikariCP-3.4.2.jar!/:na]
at com.zaxxer.hikari.pool.HikariProxyConnection.commit(HikariProxyConnection.java) ~[HikariCP-3.4.2.jar!/:na]
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doCommit(DataSourceTransactionManager.java:331) ~[spring-jdbc-5.2.3.RELEASE.jar!/:5.2.3.RELEASE]
... 76 common frames omitted
Caused by: java.sql.SQLException: Deadlock found when trying to get lock; try restarting transaction
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readErrorPacket(AbstractQueryProtocol.java:1594) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readPacket(AbstractQueryProtocol.java:1453) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:1415) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.executeQuery(AbstractQueryProtocol.java:228) ~[mariadb-java-client-2.4.4.jar!/:na]
at org.mariadb.jdbc.MariaDbStatement.executeInternal(MariaDbStatement.java:332) ~[mariadb-java-client-2.4.4.jar!/:na]
... 81 common frames omitted
Here the manager that is executed as task from spring cloud dataflow
#Configuration
#EnableConfigurationProperties(ConsolidationBatchProperties.class)
public class ManagerConfiguration {
private static final String GET_MAXIMO_ADDRESS_LOCATION;
private static final String INSERT_ADDRESS_LOCATION;
static {
GET_MAXIMO_ADDRESS_LOCATION = ResourceReader.readAsString("classpath:sql/getMaximoAddressLocation.sql");
INSERT_ADDRESS_LOCATION = ResourceReader.readAsString("classpath:sql/insertAddressLocation.sql");
}
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
private final DataSource dataSource;
private final ConsolidationBatchProperties consolidationBatchProperties;
private final RemotePartitioningManagerStepBuilderFactory remotePartitioningManagerStepBuilderFactory;
#Autowired
public ManagerConfiguration(JobBuilderFactory jobBuilderFactory,
StepBuilderFactory stepBuilderFactory,
#Qualifier("appDataSource") DataSource dataSource,
ConsolidationBatchProperties consolidationBatchProperties,
RemotePartitioningManagerStepBuilderFactory remotePartitioningManagerStepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
this.dataSource = dataSource;
this.consolidationBatchProperties = consolidationBatchProperties;
this.remotePartitioningManagerStepBuilderFactory = remotePartitioningManagerStepBuilderFactory;
}
/*
* Configure outbound flow (requests going to workers)
*/
#Bean
public DirectChannel requests() {
return new DirectChannel();
}
#Bean
public IntegrationFlow outboundFlow(AmqpTemplate amqpTemplate) {
return IntegrationFlows.from(requests())
.handle(Amqp.outboundAdapter(amqpTemplate)
.routingKey(consolidationBatchProperties.getQueueName()))
.get();
}
#Bean
public JobExecutionDeltaDao jobExecutionDeltaDao(final #Qualifier("batchDataSource") DataSource batchDataSource){
JobExecutionDeltaDao jobExecutionDao = new JobExecutionDeltaDao();
jobExecutionDao.setJdbcTemplate(new JdbcTemplate(batchDataSource));
return jobExecutionDao;
}
#Bean
public StartDateConsolidation startDateConsolidation(){
return new StartDateConsolidation(this.dataSource);
}
#Bean
public JobExecutionDeltaExplorer jobExecutionDeltaExplorer(JobExecutionDeltaDao jobExecutionDeltaDao,
StartDateConsolidation startDateConsolidation){
return new JobExecutionDeltaExplorer(jobExecutionDeltaDao, startDateConsolidation);
}
#Bean
#StepScope
public ColumnRangePartitioner partitioner(final #Qualifier("batchDataSource") DataSource batchDataSource) {
ColumnRangePartitioner columnRangePartitioner = new ColumnRangePartitioner();
columnRangePartitioner.setColumn("id");
columnRangePartitioner.setDataSource(batchDataSource);
columnRangePartitioner.setTable("GEOSITES_ADDRLOC");
return columnRangePartitioner;
}
#Bean
public JdbcCursorItemReader<AddressLocation> addressLocationReader(#Value("${customers:}") String[] customers, #Value("${mode:ALL}") String mode, #Value("${locations:}") String[] locations, JobExecutionDeltaExplorer jobExecutionDeltaExplorer) {
AddressLocationSqlTransformer sqlTransformer = new AddressLocationSqlTransformer();
sqlTransformer.setSql(GET_MAXIMO_ADDRESS_LOCATION);
sqlTransformer.setCustomers(customers);
sqlTransformer.setMode(mode);
sqlTransformer.setLocations(locations);
sqlTransformer.setJobExecutionDeltaExplorer(jobExecutionDeltaExplorer);
return new JdbcCursorItemReaderBuilder<AddressLocation>()
.name("addressLocationReader")
.dataSource(this.dataSource)
.fetchSize(1000)
.sql(sqlTransformer.getTransformedSql())
.rowMapper(new BeanPropertyRowMapper<>(AddressLocation.class))
.build();
}
#Bean
public JdbcBatchItemWriter<AddressLocation> addressLocationItemWriter(final #Qualifier("batchDataSource") DataSource batchDataSource) {
return new JdbcBatchItemWriterBuilder<AddressLocation>()
.dataSource(batchDataSource)
.sql(INSERT_ADDRESS_LOCATION)
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.build();
}
#Bean
public Step createAliasAndIndexStep(CreateIndexAndAliasTasklet createIndexAndAliasTasklet){
return stepBuilderFactory.get("createAliasAndIndexStep")
.tasklet(createIndexAndAliasTasklet).build();
}
#Bean
public Step migrateAddressLocationStep(final JdbcCursorItemReader<AddressLocation> addressLocationReader,
final JdbcBatchItemWriter<AddressLocation> addressLocationItemWriter) {
return stepBuilderFactory.get(MIGRATE_ADDR_LOC_STEP_NAME)
.<AddressLocation, AddressLocation>chunk(1000)
.reader(addressLocationReader)
.writer(addressLocationItemWriter)
.build();
}
#Bean
public Step masterStep(ColumnRangePartitioner partitioner) {
return remotePartitioningManagerStepBuilderFactory.get(MASTER_STEP_NAME)
.partitioner(WORKER_STEP_NAME, partitioner)
.gridSize(consolidationBatchProperties.getGridSize())
.outputChannel(requests())
.build();
}
#Bean
public Job consolidateAddressFromMaximoJob(final Step createAliasAndIndexStep, final Step migrateAddressLocationStep, final Step masterStep) {
return jobBuilderFactory.get(JOB_NAME)
.incrementer(new RunIdIncrementer())
.start(createAliasAndIndexStep)
.next(migrateAddressLocationStep)
.next(masterStep)
.build();
}
}
Here the worker that runs outside the context of data flow, it is always listening for messages in rabbitmq
#Configuration
#EnableConfigurationProperties(ConsolidationBatchProperties.class)
public class WorkerConfiguration {
private static final Logger log = LoggerFactory.getLogger(WorkerConfiguration.class);
private static final String GET_ADDRESS_LOCATION_WITHIN_RANGE;
static {
GET_ADDRESS_LOCATION_WITHIN_RANGE = ResourceReader.readAsString("classpath:sql/getAddressLocationWithinRange.sql");
}
private final RemotePartitioningWorkerStepBuilderFactory remotePartitioningWorkerStepBuilderFactory;
private final DataSource dataSource;
private final ConsolidationBatchProperties consolidationBatchProperties;
#Autowired
public WorkerConfiguration(
RemotePartitioningWorkerStepBuilderFactory remotePartitioningWorkerStepBuilderFactory,
#Qualifier("batchDataSource") DataSource dataSource,
ConsolidationBatchProperties consolidationBatchProperties) {
this.remotePartitioningWorkerStepBuilderFactory = remotePartitioningWorkerStepBuilderFactory;
this.dataSource = dataSource;
this.consolidationBatchProperties = consolidationBatchProperties;
}
/*
* Configure inbound flow (requests coming from the master)
*/
#Bean
public DirectChannel requests() {
return new DirectChannel();
}
#Bean
public IntegrationFlow inboundFlow(SimpleMessageListenerContainer listenerContainer) {
return IntegrationFlows
.from(Amqp.inboundAdapter(listenerContainer))
.channel(requests())
.get();
}
#Bean
public SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container =
new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames(consolidationBatchProperties.getQueueName());
container.setConcurrentConsumers(consolidationBatchProperties.getConsumers());
return container;
}
/*
* Configure outbound flow (replies going to the master)
*/
#Bean
public NullChannel replies() {
return new NullChannel();
}
/*
* Configure worker components
*/
#Bean
public GeographicSiteProcessor geographicSiteProcessor(GeographicSiteApiClient GeographicSiteApiClient, GeographicAddressApiClient geographicAddressApiClient){
return new GeographicSiteProcessor(geographicAddressApiClient, GeographicSiteApiClient);
}
#Bean
public ElasticObjectItemWriter elasticObjectItemWriter(RestHighLevelClient client, ObjectMapper objectMapper, ElasticIndexProperties elasticIndexProperties){
ElasticObjectItemWriter elasticObjectItemWriter = new ElasticObjectItemWriter();
elasticObjectItemWriter.setClient(client);
elasticObjectItemWriter.setObjectMapper(objectMapper);
elasticObjectItemWriter.setIndexName(elasticIndexProperties.getWritingIndexName());
elasticObjectItemWriter.setType(elasticIndexProperties.getType());
return elasticObjectItemWriter;
}
#Bean
#StepScope
public JdbcCursorItemReader<AddressLocation> itemReader(
#Value("#{stepExecutionContext['minValue']}")Long minValue,
#Value("#{stepExecutionContext['maxValue']}")Long maxValue) {
log.info("reading " + minValue + " to " + maxValue);
RangeSetter rangeSetter = new RangeSetter();
rangeSetter.setStartValue(minValue);
rangeSetter.setEndValue(maxValue);
return new JdbcCursorItemReaderBuilder<AddressLocation>()
.name("itemReader")
.dataSource(this.dataSource)
.sql(GET_ADDRESS_LOCATION_WITHIN_RANGE)
.preparedStatementSetter(rangeSetter)
.rowMapper(new BeanPropertyRowMapper<>(AddressLocation.class))
.build();
}
#Bean
public Step workerStep(JdbcCursorItemReader<AddressLocation> itemReader,
GeographicSiteProcessor geographicSiteProcessor,
ElasticObjectItemWriter elasticObjectItemWriter) {
return remotePartitioningWorkerStepBuilderFactory.get("workerStep")
.inputChannel(requests())
.<AddressLocation, ElasticGeographicSite>chunk(consolidationBatchProperties.getChunkSize())
.reader(itemReader)
.processor(geographicSiteProcessor)
.writer(elasticObjectItemWriter)
.faultTolerant()
.retryLimit(5)
.retry(MicroserviceException.class)
.retry(TransactionSystemException.class)
.skip(NullPointerException.class)
.skipLimit(10)
.listener(new LoggingSkipListener<AddressLocation, ElasticObject>())
.build();
}
}
Do you have any way to solve this issue?
The dead-lock is happening at the worker side and I suspect the this is happening because two (or more) message consumers are competing on a resource.
Did using one consumer per worker fix the issue?
we have tested with 1 single consumer and we have not had deadlock problems, but my question is to scale so should we use several pod workers with 1 single consumer and this formula would avoid deadlock?
I'm not sure workers are expected to have more than one consumer. The idea of remote partitioning is that each partition is handled by a worker. Now how this partition is handled at the worker side is up to you. If you want to add another level of scaling on the worker side, you can try a multi-threaded step or a locally partitioned step instead of using multiple consumers.

Register Mock Bean during Integration Testing for SpEL Bean Reference

I am getting the following error while running the test from my spring-boot app. I am using version= 2.3.3.RELEASE of spring-boot-starter-data-mongodb and version=2.2.0 of de.flapdoodle.embed.mongo for integration testing.
org.springframework.expression.spel.SpelEvaluationException: EL1058E: A problem occurred when trying to resolve bean 'gameServiceImpl':'Could not resolve bean reference against BeanFactory'
at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:59)
at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:55)
at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:91)
at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:117)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:308)
at org.springframework.data.mongodb.core.mapping.BasicMongoPersistentEntity.getCollection(BasicMongoPersistentEntity.java:129)
at org.springframework.data.mongodb.repository.support.MappingMongoEntityInformation.getCollectionName(MappingMongoEntityInformation.java:97)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:88)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.springframework.data.repository.core.support.ImplementationInvocationMetadata.invoke(ImplementationInvocationMetadata.java:72)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:382)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:205)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:549)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:155)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:130)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy70.save(Unknown Source)
at eatigo.com.webscraper.service.GameServiceImplTest.testSavingSingleEntity(GameServiceImplTest.java:107)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1510)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1510)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: org.springframework.expression.AccessException: Could not resolve bean reference against BeanFactory
at org.springframework.context.expression.BeanFactoryResolver.resolve(BeanFactoryResolver.java:54)
at org.springframework.expression.spel.ast.BeanReference.getValueInternal(BeanReference.java:55)
... 89 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'gameServiceImpl' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:816)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1288)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1109)
at org.springframework.context.expression.BeanFactoryResolver.resolve(BeanFactoryResolver.java:51)
... 90 more
Below is my simple code implementations
I underdtand that the problem lies in this statement #Document(collection = "#{#gameServiceImpl.getCollectionName()}") because during testing, the SPEL can't find any bean with name='gameServiceImpl' because it has been mocked during testing.
Is there a way to inject a mock bean in the spring container registry for it to be recognized by SPEL?
Is it possible to replace and inject value in the class annotation here #Document(collection = "replace and inject value here") during the initialization of entity class e.g Game game= new Game();
Entity
#Document(collection = "#{#gameServiceImpl.getCollectionName()}")
public class Game {
#Id
private int gameId;
}
Repository
#Repository
public interface GameRepository extends MongoRepository<Game, String> {
}
Service
#Service
public class GameServiceImpl implements GameService {
private GameRepository gameRepository;
private String collectionName;
#Autowired
public GameServiceImpl(GameRepository gameRepository){
this.gameRepository = gameRepository;
}
#Override
public String getCollectionName() {
return collectionName;
}
#Override
public void setCollectionName(String collectionName) {
this.collectionName = collectionName;
}
public Game save(Game game){
return gameRepository.save(game);
}
}
Test
ExtendWith(SpringExtension.class)
#ActiveProfiles("test")
#BootstrapWith(SpringBootTestContextBootstrapper.class)
#SpringBootTest(classes = {MainApplication.class})
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
#DataMongoTest
public class GameServiceImplTest {
#Mock(name = "gameServiceImpl")
private GameServiceImpl gameServiceImpl;
#Autowired
private GameRepository gameRepository;
#Autowired
private MongoTemplate mongoTemplate;
#BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSavingGame(){
Game game= new Game();
String collectionName = "testing";
gameServiceImpl.setCollectionName(collectionName);
when(gameServiceImpl.save(game)).thenReturn(gameRepository.save(game));
when(gameServiceImpl.getCollectionName()).thenReturn(collectionName);
Game result = gameServiceImpl.save(game);
assertThat(result, is(notNullValue()));
assertThat(mongoTemplate.collectionExists(collectionName), is(true));
assertThat(mongoTemplate.findAll(Game.class, collectionName).size(), equalTo(1));
}
}
Thanks to #M. Deinum direction and some help from here, I was able to achieve results with the following modifications.
Test
#ExtendWith(SpringExtension.class)
#ActiveProfiles("test")
#BootstrapWith(SpringBootTestContextBootstrapper.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
#DataMongoTest
public class GameServiceImplTest {
#MockBean(name = "gameServiceImpl")
public GameServiceImpl gameServiceImpl;
#Autowired
private GameRepository gameRepository;
#Autowired
private MongoTemplate mongoTemplate;
#BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testSavingSingleEntity(){
Game game = new Game();
String collectionName = "testingCollection";
gameServiceImpl.setCollectionName(collectionName);
when(gameServiceImpl.getCollectionName()).thenReturn(collectionName);
Game result = gameRepository.save(game);
when(gameServiceImpl.save(game)).thenReturn(result);
assertThat(gameServiceImpl.save(game), is(notNullValue()));
assertThat(mongoTemplate.collectionExists(collectionName), is(true));
assertThat(mongoTemplate.findAll(Game.class, collectionName).size(), equalTo(1));
}
}

Spring batch with DB2 and MongoDB using Spring boot

I need to read the DB2 database and copy data to mongoDB using Spring Batch. As I am going to write the data to mongoDB, so I dont need the transaction. I would like to keep the metadata tables scripts in mongoDB only not in DB2 but I couldn't find the metadata tables scripts for mongoDB. In the server startup time, spring boot expect the batch_job_instance table in Db2 instead of mongoDB. I annotated mongoDB as primary but still it is throwing an error.
Someone can help me with this. Thanks in advance.
MongoConfig.java:
#Configuration
#EnableMongoRepositories("com.test.mongodb")
public class MongoConfig extends AbstractMongoConfiguration {
private final Logger log = LoggerFactory.getLogger(MongoConfig.class);
#Value("${spring.data.mongodb.host}")
private String host;
#Value("${spring.data.mongodb.port}")
private Integer port;
#Value("${spring.data.mongodb.username}")
private String username;
#Value("${spring.data.mongodb.database}")
private String database;
#Value("${spring.data.mongodb.password}")
private String password;
#Bean
public ValidatingMongoEventListener validatingMongoEventListener() {
return new ValidatingMongoEventListener(validator());
}
#Bean
public LocalValidatorFactoryBean validator() {
return new LocalValidatorFactoryBean();
}
#Override
public String getDatabaseName() {
return database;
}
#Override
#Bean
public Mongo mongo() throws Exception {
return new MongoClient(singletonList(new ServerAddress(host, port)),
singletonList(MongoCredential.createCredential(username, database, password.toCharArray())));
}
#Override
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.data.mongodb")
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongo(), database);
}
}
application.properties:
# DB2
spring.datasource.jndi-name=java:jboss/datasources/Db2XaDsn
# Mongo DB
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.username=admin
spring.data.mongodb.password=admin
spring.data.mongodb.database=test
Batch class:
#Configuration
#EnableBatchProcessing
public class ItemBatch {
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
EntityManagerFactory entityManagerFactory;
#Autowired
MongoTemplate mongoTemplate;
#Bean
public Job readDB2() {
return jobBuilderFactory.get("readDB2").start(step1()).build();
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1").<com.model.db2.Item, Item>chunk(200).reader(reader())
.writer(writer()).build();
}
#Bean
public ItemReader<com.model.db2.Item> reader() {
JpaPagingItemReader<com.model.db2.Item> reader = new JpaPagingItemReader<>();
reader.setQueryString("select i from Item i");
reader.setEntityManagerFactory(entityManagerFactory);
return reader;
}
#Bean
public MongoItemWriter<Item> writer() {
MongoItemWriter<Item> writer = new MongoItemWriter<>();
try {
writer.setTemplate(mongoTemplate);
} catch (Exception e) {
e.printStackTrace();
}
writer.setCollection("item");
return writer;
}
}
Error:
00:44:39,484 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 72) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./itemapi: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./itemapi: java.lang.RuntimeException: java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:85)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.lang.RuntimeException: java.lang.IllegalStateException: Failed to execute CommandLineRunner
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:231)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:100)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:82)
... 6 more
Caused by: java.lang.IllegalStateException: Failed to execute CommandLineRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:735)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:716)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:703)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:304)
at org.springframework.boot.web.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:154)
at org.springframework.boot.web.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:134)
at org.springframework.boot.web.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:87)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:169)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:184)
... 8 more
Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? order by JOB_INSTANCE_ID desc]; nested exception is com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-204, SQLSTATE=42704, SQLERRMC=TEST.BATCH_JOB_INSTANCE, DRIVER=4.18.60
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:684)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:716)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:726)
at org.springframework.batch.core.repository.dao.JdbcJobInstanceDao.getJobInstances(JdbcJobInstanceDao.java:230)
at org.springframework.batch.core.explore.support.SimpleJobExplorer.getJobInstances(SimpleJobExplorer.java:173)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$PassthruAdvice.invoke(SimpleBatchConfiguration.java:127)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy302.getJobInstances(Unknown Source)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.getNextJobParameters(JobLauncherCommandLineRunner.java:131)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:212)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123)
at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:732)
... 16 more
Caused by: com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-204, SQLSTATE=42704, SQLERRMC=TEST.BATCH_JOB_INSTANCE, DRIVER=4.18.60
at com.ibm.db2.jcc.am.kd.a(kd.java:747)
at com.ibm.db2.jcc.am.kd.a(kd.java:66)
at com.ibm.db2.jcc.am.kd.a(kd.java:135)
at com.ibm.db2.jcc.am.bp.c(bp.java:2788)
at com.ibm.db2.jcc.am.bp.d(bp.java:2776)
at com.ibm.db2.jcc.am.bp.a(bp.java:2209)
at com.ibm.db2.jcc.am.cp.a(cp.java:7886)
at com.ibm.db2.jcc.t4.bb.h(bb.java:141)
at com.ibm.db2.jcc.t4.bb.b(bb.java:41)
at com.ibm.db2.jcc.t4.p.a(p.java:32)
at com.ibm.db2.jcc.t4.vb.i(vb.java:145)
at com.ibm.db2.jcc.am.bp.kb(bp.java:2178)
at com.ibm.db2.jcc.am.cp.xc(cp.java:3686)
at com.ibm.db2.jcc.am.cp.b(cp.java:4493)
at com.ibm.db2.jcc.am.cp.kc(cp.java:767)
at com.ibm.db2.jcc.am.cp.executeQuery(cp.java:732)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:504)
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:692)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633)
... 38 more
Answering my own question. I am able use spring batch without metadata tables using the below configuration:
#Configuration
public class SpringBatchInMemoryConfiguration {
#Bean
public ResourcelessTransactionManager transactionManager() {
return new ResourcelessTransactionManager();
}
#Bean
public MapJobRepositoryFactoryBean mapJobRepositoryFactory(ResourcelessTransactionManager txManager)
throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(txManager);
factory.afterPropertiesSet();
return factory;
}
#Bean
public JobRepository jobRepository(MapJobRepositoryFactoryBean factory) throws Exception {
return factory.getObject();
}
#Bean
public JobExplorer jobExplorer(MapJobRepositoryFactoryBean factory) {
return new SimpleJobExplorer(factory.getJobInstanceDao(), factory.getJobExecutionDao(),
factory.getStepExecutionDao(), factory.getExecutionContextDao());
}
#Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) throws Exception {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
launcher.afterPropertiesSet();
return launcher;
}
}

Spring batch use JpaPagingItemReader JpaItemWriter no transaction is in progress

My project uses java config, the DataSource entityManagerFactory PlatformTransactionManager created by other java config file.
When ItemReader read data, ItemProcessor data transformed ItemWriter has some error
How can I solve this problem?
Error message
2015-01-17 16:26:30.390 ERROR AbstractStep:225 - Encountered an error executing step testStep in job validJob
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.java:1171)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1332)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
How can I enable transactions on the following Code:
#Configuration
#EnableBatchProcessing
public class JobConfiguration {
#Inject
private PlatformTransactionManager transactionManager;
#Inject
private EntityManagerFactory emf;
#Bean
public Job validJob(JobBuilderFactory jobBuilderFactory,Step step) {
return jobBuilderFactory.get("validJob").flow(step).end().build();
}
#Bean
public Step testStep(StepBuilderFactory stepBuilderFactory, ItemReader<PurchaseOrder> reader,
ItemWriter<PurchaseOrder> writer, ItemProcessor<PurchaseOrder, PurchaseOrder> processor) {
return stepBuilderFactory.get("testStep")//
.transactionManager(transactionManager)//
.<PurchaseOrder, PurchaseOrder>chunk(100)//
.reader(reader)//
.processor(processor)//
.writer(writer)//
.build();
}
#Bean
public ItemReader<PurchaseOrder> reader() {
JpaPagingItemReader<PurchaseOrder> reader = new JpaPagingItemReader<PurchaseOrder>();
reader.setEntityManagerFactory(emf);
reader.setQueryString(" select p from PurchaseOrder p ");
reader.setTransacted(false);
return reader;
}
#Bean
public ItemProcessor<PurchaseOrder, PurchaseOrder> processor() {
return new PurchaseOrderItemProcessor();
}
#Bean
public ItemWriter<PurchaseOrder> writer() {
JpaItemWriter<PurchaseOrder> writer = new JpaItemWriter<PurchaseOrder>();
writer.setEntityManagerFactory(emf);
return writer;
}

javax.ejb.EJBException java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName

I'm working on a JavaEE application with EJB.
I have an Entity called Medico which code is:
#Entity
public class Medico implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
/**
*
*/
public Medico(String nome_medico, String morada_medico,
String esp, GregorianCalendar dnasc_medico, int tel_medico) { //construtor parametrico
super();
this.nome_medico = nome_medico;
this.morada_medico = morada_medico;
this.esp = esp;
this.dnasc_medico = dnasc_medico;
this.tel_medico = tel_medico;
}
#Id
#GeneratedValue
private int cod_medico; //bi
private String nome_medico;
private String morada_medico;
private String esp;
#Temporal(TemporalType.DATE)
private GregorianCalendar dnasc_medico;
private int tel_medico;
private ArrayList<GregorianCalendar> agenda_consultas;
private ArrayList<GregorianCalendar> agenda_atos;
private int total_atos;
private int total_presc;
public int getTotal_presc() {
return total_presc;
}
public void setTotal_presc(int total_presc) {
this.total_presc = total_presc;
}
public Medico(){ //construtor vazio
super();
}
public int getTotal_atos() {
return total_atos;
}
public void setTotal_atos(int total_atos) {
this.total_atos = total_atos;
}
public ArrayList<GregorianCalendar> getAgenda_consultas() {
return agenda_consultas;
}
public void setAgenda_consultas(ArrayList<GregorianCalendar> agenda_consultas) {
this.agenda_consultas = agenda_consultas;
}
public ArrayList<GregorianCalendar> getAgenda_atos() {
return agenda_atos;
}
public void setAgenda_atos(ArrayList<GregorianCalendar> agenda_atos) {
this.agenda_atos = agenda_atos;
}
public int getCod_medico() {
return cod_medico;
}
public void setCod_medico(int cod_medico) {
this.cod_medico = cod_medico;
}
public String getNome_medico() {
return nome_medico;
}
public void setNome_medico(String nome_medico) {
this.nome_medico = nome_medico;
}
public String getMorada_medico() {
return morada_medico;
}
public void setMorada_medico(String morada_medico) {
this.morada_medico = morada_medico;
}
public String getEsp() {
return esp;
}
public void setEsp(String esp) {
this.esp = esp;
}
public GregorianCalendar getDnasc_medico() {
return dnasc_medico;
}
public void setDnasc_medico(GregorianCalendar dnasc_medico) {
this.dnasc_medico = dnasc_medico;
}
public int getTel_medico() {
return tel_medico;
}
public void setTel_medico(int tel_medico) {
this.tel_medico = tel_medico;
}
#Override
public String toString() {
return "Medico [cod_medico=" + cod_medico + ", nome_medico="
+ nome_medico + ", morada_medico=" + morada_medico + ", esp="
+ esp + ", dnasc_medico=" + dnasc_medico + ", tel_medico="
+ tel_medico + "]";
}
}
Then I created a session bean implementation class:
#Stateless
public class HospitalManagement implements AdministradorSessionRemote,GestorSessionRemote {
/**
* Default constructor.
*/
#PersistenceContext(unitName="Hospital")
private EntityManager em;
public HospitalManagement() {
// TODO Auto-generated constructor stub
}
#Override
public String cria_medico(String nome_medico, String morada_medico,
String esp, GregorianCalendar dnasc_medico, int tel_medico) {
Medico md = new Medico (nome_medico, morada_medico, esp, dnasc_medico,tel_medico);
em.persist(md);
return "Medico "+Integer.toString(md.getCod_medico())+" criado!";
}
This class implements two interfaces, but the method above is only used in the following one:
#Remote
public interface GestorSessionRemote {
public String cria_medico(String nome_medico,String morada_medico,String esp,GregorianCalendar dnasc_medico, int tel_medico);
public String procura_nome_medico(String nome);
public String procura_cod_medico(int cod);
public String altera_morada_med(int cod, String morada);
public String altera_telemovel_med(int cod, int tel);
Then I created a client:
public class GestorClient {
public static void main(String[] args){
InitialContext ctx =new InitialContext();
GestorSessionRemote g=(GestorSessionRemote)ctx.lookup("java:global/HospitalEAR/Hospital/HospitalManagement!Sessions.GestorSessionRemote");
System.out.println(g.cria_medico(nomem, moradam, esp,cal,telm));
where the parameters of the method are obtained by scannig from the keyboard.
I've also created the following persistence.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="Hospital">
<properties>
<property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>
</properties>
</persistence-unit>
</persistence>
When I try to deploy the application, an error occurs. Here is the complete stacktrace:
Exception in thread "main" javax.ejb.EJBException
at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:748)
at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:698)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:503)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:212)
at com.sun.ejb.containers.EJBObjectInvocationHandlerDelegate.invoke(EJBObjectInvocationHandlerDelegate.java:79)
at com.sun.proxy.$Proxy236.cria_medico(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie.dispatchToMethod(ReflectiveTie.java:143)
at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:173)
at com.sun.corba.ee.impl.protocol.ServerRequestDispatcherImpl.dispatchToServant(ServerRequestDispatcherImpl.java:528)
at com.sun.corba.ee.impl.protocol.ServerRequestDispatcherImpl.dispatch(ServerRequestDispatcherImpl.java:199)
at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequestRequest(MessageMediatorImpl.java:1549)
at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequest(MessageMediatorImpl.java:1425)
at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleInput(MessageMediatorImpl.java:930)
at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:213)
at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequest(MessageMediatorImpl.java:694)
at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.dispatch(MessageMediatorImpl.java:496)
at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.doWork(MessageMediatorImpl.java:2222)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
Caused by: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName Hospital
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.init(EntityManagerWrapper.java:138)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTxRequiredCheck(EntityManagerWrapper.java:158)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.doTransactionScopedTxCheck(EntityManagerWrapper.java:151)
at com.sun.enterprise.container.common.impl.EntityManagerWrapper.persist(EntityManagerWrapper.java:281)
at Sessions.HospitalManagement.cria_medico(HospitalManagement.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1081)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1153)
at com.sun.ejb.containers.BaseContainer.invokeBeanMethod(BaseContainer.java:4786)
at com.sun.ejb.EjbInvocation.invokeBeanMethod(EjbInvocation.java:656)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at org.jboss.weld.ejb.AbstractEJBRequestScopeActivationInterceptor.aroundInvoke(AbstractEJBRequestScopeActivationInterceptor.java:55)
at org.jboss.weld.ejb.SessionBeanInterceptor.aroundInvoke(SessionBeanInterceptor.java:52)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.EjbInvocation.proceed(EjbInvocation.java:608)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.doCall(SystemInterceptorProxy.java:163)
at com.sun.ejb.containers.interceptors.SystemInterceptorProxy.aroundInvoke(SystemInterceptorProxy.java:140)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.sun.ejb.containers.interceptors.AroundInvokeInterceptor.intercept(InterceptorManager.java:883)
at com.sun.ejb.containers.interceptors.AroundInvokeChainImpl.invokeNext(InterceptorManager.java:822)
at com.sun.ejb.containers.interceptors.InterceptorManager.intercept(InterceptorManager.java:369)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:4758)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4746)
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(EJBObjectInvocationHandler.java:205)
... 19 more
Could someone help me understand the reason why this is happening?
The obvious problem is that you didn't specify a jta-data-source and the transaction-type in your persistence.xml.
A jta-data-source is specified like this:
<persistence-unit name="Hospital">
<jta-data-source>jdbc/sample</jta-data-source>
</persistence-unit>
You have to create the JDBC resource in your Glassfish instance. To do this open the Glassfish Admin GUI under http://localhost:4848 and create a Connection Pool under Resources -> JDBC Connection Pools. Then create a JDBC resource under Resources -> JDBC Resources named jdbc/sample and make it reference the new connection pool.
Further, it looks like the server somehow thinks that you want to use transaction-type RESOURCE_LOCAL which requires that you specify an EntityManagerFactory to get an instance of the EntityManager.
JTA should be the default transaction-type in a Java EE environment but you may have to explicitly specifiy the transaction-type in the persistence.xml like this:
<persistence-unit name="Hospital" transaction-type="JTA">
See also:
persistence.xml different transaction-type attributes