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;
}
}
Related
I am migrating the spring boot app from spring boot 1.5.4 to spring boot 2.7.5, In old code I have hibernate at DAO layer. (does the migration caused the issue, I did not find very particular about the issue )
properties file has connection details and used below key
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate5.SpringSessionContext
Application class have following annotations,
#EnableTransactionManagement #EnableJpaRepositories(basePackages = {"repository package"}) #ComponentScan(basePackages = {"base package"}) #EntityScan(basePackages = {"entity package"})
DAO code :
private EntityManager entityManager;
private Session getSession() {
return entityManager.unwrap(Session.class);
}
// problematic code
public void doSomething(){
String hqlBuilder = "Update Query statement"
Query query = getSession().createQuery(hqlBuilder);
int result = query.executeUpdate();
}```
Service code:
Service class has #Transctional defined at class level however it throws exception on invoking the doSomething() method on DAO instance
`**Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query**
at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:445)
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1692)
at <removed the package path>.dao.impl.LastViewedHistoryElementDaoHibernate.insertOrUpdate(LastViewedHistoryElementDaoHibernate.java:122)
at impl.LastViewedHistoryElementDaoHibernate$$FastClassBySpringCGLIB$$f8fba493.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
... 271 common frames omitted`
**In DAO method returns it throws the TransactionRequiredException : No Transaction in progress**
Thank you, I did applied the #EnableTransactionManagement #Transactional, added spring jpa. I did configure Transaction manager in config also however not luck,
```#Autowired
HikariDataSource dataSource;
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setPackagesToScan(
new String[]{"<My packages>"});
//sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public PlatformTransactionManager transactionManager() {
HibernateTransactionManager hibernateTransactionManager
= new HibernateTransactionManager();
hibernateTransactionManager.setSessionFactory(sessionFactory().getObject());
return hibernateTransactionManager;
}```
but still same error as Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:445)
at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3496)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1399)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1394)
at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:113)
at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:97)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:916)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:727)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
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());
}
}
I am setting up an application that accept a REST call and then does some DB work. I am trying to use Spring to do everything via annotations, except I would like to keep the persistence.xml file. However, I am being thrown an error that there is not a Bean called the unitName I have added to the #PersistenceContext.
#Repository
#Transactional
public class UserController implements Serializable {
private static final long serialVersionUID = 4625223295588959802L;
#PersistenceContext(unitName="PerfJPASpring")
private EntityManager em;
#Transactional
public void addUser(User user) {
em.persist(user);
}
#Transactional
public void deleteAll() {
em.createNamedQuery("User.deleteAll").executeUpdate();
}
#Transactional
public List<User> selectAllRecords() {
return em.createNamedQuery("User.findAll").getResultList();
}
}
The other issue I have is how do I get Spring to use the persistence.xml and not define the DataSource in the LocalContainerEntityManagerFactoryBean. I have added the Datasource to the App Server.
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackageClasses=UserController.class)
public class DatabaseConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(false);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.example.jpa.model");
factory.setDataSource(dataSource());
Properties jpaProps = new Properties();
jpaProps.put("eclipselink.weaving", "false");
factory.setJpaProperties(jpaProps);
return factory;
}
#Bean
public JpaTransactionManager transactionManager() throws SQLException {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
return txManager;
}
public DataSource dataSource() {
try {
Context initCtx = new InitialContext();
return (DataSource) initCtx.lookup("jdbc/userdb");
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Unable to lookup datasource", e);
}
}
}
The unitName does match that in the 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="PerfJPASpring" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/userdb</jta-data-source>
<class>com.example.jpa.model.User</class>
</persistence-unit>
</persistence>
And this is the error I am receiving.
Uncaught init() exception created by servlet [DispatcherServlet] in application [PerfJPASpring]: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userController': Injection of persistence dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'PerfJPASpring' is defined
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:357)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1219)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:540)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
at [internal classes]
Could point me in the right direction for Spring to use the unitName and how I can avoid specifying the datasource in the Db Config?
Thanks.
I found the issue. First, since I am using JTA, then I can remove #Transactional and remove the Datasource and replace it with the setPersistenceUnitName. Now it uses the persistence.xml file and JTA.
The Service:
#Repository
public class UserController implements Serializable {
private static final long serialVersionUID = 4625223295588959802L;
#PersistenceContext(unitName="PerfJPASpring")
private EntityManager em;
public void addUser(User user) {
em.persist(user);
}
public void deleteAll() {
em.createNamedQuery("User.deleteAll").executeUpdate();
}
public List<User> selectAllRecords() {
return em.createNamedQuery("User.findAll").getResultList();
}
}
Database Config:
#Configuration
#EnableJpaRepositories(basePackageClasses=UserController.class)
public class DatabaseConfig {
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
EclipseLinkJpaVendorAdapter vendorAdapter = new EclipseLinkJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setShowSql(false);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.example.jpa.model");
factory.setPersistenceUnitName("PerfJPASpring");
Properties jpaProps = new Properties();
jpaProps.put("eclipselink.weaving", "false");
factory.setJpaProperties(jpaProps);
return factory;
}
#Bean
public JpaTransactionManager transactionManager() throws SQLException {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory().getObject());
return txManager;
}
}
I am trying to store data synchronously in cache and mongoDB. I am getting this exception
Exception in thread "main" com.hazelcast.core.HazelcastException: CONCURRENT_MAP_PUT failed at Address[192.168.11.208]:5702 because of an exception thrown at Address[192.168.11.208]:5701
at com.hazelcast.impl.BaseManager.rethrowException(BaseManager.java:188)
at com.hazelcast.impl.ConcurrentMapManager$MPut.txnalPut(ConcurrentMapManager.java:1902)
at com.hazelcast.impl.ConcurrentMapManager$MPut.txnalPut(ConcurrentMapManager.java:1818)
at com.hazelcast.impl.ConcurrentMapManager$MPut.put(ConcurrentMapManager.java:1682)
at com.hazelcast.impl.MProxyImpl$MProxyReal.put(MProxyImpl.java:632)
at com.hazelcast.impl.MProxyImpl$MProxyReal.put(MProxyImpl.java:606)
at com.hazelcast.impl.MProxyImpl.put(MProxyImpl.java:173)
at com.hazelcast.impl.MProxyImpl.put(MProxyImpl.java:124)
at mypackage.dao.EmployeeDAO.createNewEmployee(EmployeeDAO.java:52)
at mypackage.services.EmployeeManager.createNewEmployee(EmployeeManager.java:25)
at mypackage.controllers.EmployeeController.createNewEmployee(EmployeeController.java:24)
at mypackage.hazelcastspring.App.main(App.java:29)
Caused by: java.lang.NullPointerException
at mypackage.services.EmployeeMapstore.store(EmployeeMapstore.java:61)
at mypackage.services.EmployeeMapstore.store(EmployeeMapstore.java:1)
at com.hazelcast.impl.concurrentmap.MapStoreWrapper.store(MapStoreWrapper.java:114)
at com.hazelcast.impl.ConcurrentMapManager$PutOperationHandler$PutStorer.doMapStoreOperation(ConcurrentMapManager.java:3091)
at com.hazelcast.impl.ConcurrentMapManager$AbstractMapStoreOperation.run(ConcurrentMapManager.java:3795)
at com.hazelcast.impl.executor.ParallelExecutorService$ParallelExecutorImpl$ExecutionSegment.run(ParallelExecutorService.java:212)
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 com.hazelcast.impl.ExecutorThreadFactory$1.run(ExecutorThreadFactory.java:38
I am having POJO class contains two String and i am using com.hazlecast.core.Mapstore library
Mainclass
public static void main(String[] args) {
CacheTesting testObj = new CacheTesting();
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
EmployeeController obj = (EmployeeController) context.getBean("employeeController");
obj.createNewEmployee();
testObj.cacheMembers();
testObj.clearCacheMembers();
testObj.cacheSize();
testObj.deleteCache(2);
testObj.getCacheMember(1);}
/////Dao class
public EmployeeDTO createNewEmployee() {
System.out.println("----Create new employee of DAO class called----");
getEmployeeDTO.setFirstName("Name");
getEmployeeDTO.setLastName("lastName");
System.out.println("DAO object: "+getEmployeeDTO);
getEmployeeMap().put(3,getEmployeeDTO);
return getEmployeeDTO;
}
////MapStore class
public class EmployeeMapstore implements MapStore<Integer, EmployeeDTO> {
#Autowired
EmployeeDTO getEmployeeDTO;
#Autowired
MongoOperations mongoOperations;
public synchronized void store(Integer key, EmployeeDTO geEmployeeDTO) {
System.out.println("----Store method of mapstore called----");
System.out.println("Before put method/Store method object: "+getEmployeeDTO);
mongoOperations.save(getEmployeeDTO);
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;
}