Spring Boot batch plus scheduler - java

I am new to spring batch so trying to schedule a batch works as a job every 5 seconds using spring boot batch and scheduler but somewhere I am missing something so getting below error.Please help me to solve this error.
Error:-
2017-03-12 02:23:26.614 INFO 8292 --- [pool-1-thread-1] com.spring.test.BatchConfig : The time is now 02:23:26
2017-03-12 02:23:26.617 ERROR 8292 --- [pool-1-thread-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at org.springframework.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:721)
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:499)
at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.enhanceFactoryBean(ConfigurationClassEnhancer.java:384)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:292)
at com.spring.test.BatchConfig$$EnhancerBySpringCGLIB$$dcfce226.job(<generated>)
at com.spring.test.BatchConfig.reportCurrentTime(BatchConfig.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
application.properties:-
spring.batch.job.enabled=false
spring-config.xml:-
<beans:beans xmlns="http://www.springframework.org/schema/batch"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch
http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
<job id="job">
<step id="step1">
<tasklet>
<chunk reader="itemReader" processor="itemProcessor" writer="itemWriter"
commit-interval="1" />
</tasklet>
</step>
</job>
<beans:bean id="itemReader" class="com.spring.test.Reader" />
<beans:bean id="itemProcessor" class="com.spring.test.Processor" />
<beans:bean id="itemWriter" class="com.spring.test.Writer" />
</beans:beans>
Application:-
#SpringBootApplication
#EnableScheduling
#ComponentScan
#ImportResource("classpath:spring-config.xml")
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class);
}
}
BatchConfig:-
#Configuration
#EnableBatchProcessing
#Import({BatchScheduler.class})
public class BatchConfig {
private static final Logger log = LoggerFactory
.getLogger(BatchConfig.class);
private static final SimpleDateFormat dateFormat = new SimpleDateFormat(
"HH:mm:ss");
#Autowired
private SimpleJobLauncher jobLauncher;
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Bean
public Job job() {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<String, String> chunk(1)
.reader(new Reader())
.processor(new Processor())
.writer(new Writer())
.build();
}
#Scheduled(fixedRate = 5000)
public void reportCurrentTime() throws Exception{
log.info("The time is now {}", dateFormat.format(new Date()));
JobParameters param = new JobParametersBuilder().addString("JobID",
String.valueOf(System.currentTimeMillis())).toJobParameters();
JobExecution execution = jobLauncher.run(job(), param);
System.out.println("Job Execution Status: " + execution.getStatus());
}
}
BatchScheduler:-
#Configuration
#EnableScheduling
public class BatchScheduler {
#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 SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return launcher;
}
}

It is hard to figure out what is actually wrong with your code but it looks like some of your beans do not have no-args constructor.
Configuring batch with scheduler is relatively simple. I've just downloaded the code from official batch guide and extended it with small amount of my own code.
You can try the same:
1) Add spring.batch.job.enabled=false to application.properties file (just like you already have in your project)
2) Add #EnableScheduling to a Application class (just like you have in your code)
3) Create a Component class for scheduling with the next code:
import org.springframework.batch.core.*;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class Scheduler {
#Autowired
private JobLauncher jobLauncher;
#Autowired
private Job job;
#Scheduled(fixedRate = 5000)
public void reportCurrentTime() throws Exception{
JobParameters param = new JobParametersBuilder().addString("JobID",
String.valueOf(System.currentTimeMillis())).toJobParameters();
JobExecution execution = jobLauncher.run(job, param);
System.out.println("Job Execution Status: " + execution.getStatus());
}
}
That works well. Hope that having this example you'll figure out what is wrong with your own code.

Related

Spring Boot with XML based security configuration doesn't seem to use correct authentication manager?

We're trying to upgrade our old, mostly XML-based Spring web application, to Spring Boot (2.5.4). We've almost managed to do so but there's one thing that is still nagging us. Even after using Spring Boot we (still for now) have our Spring Security configuration defined like this in XML:
<http pattern="/api/something/v1/**" use-expressions="true" create-session="stateless" authentication-manager-ref="somethingAuthenticationManager">
<http-basic/>
<custom-filter ref="queryParamAuthFilter" before="BASIC_AUTH_FILTER" />
<intercept-url pattern="/api/something/v1/**" access="hasRole('ROLE_SOMETHING')" />
<csrf disabled="true"/>
</http>
The authentication managers are defined like this:
<authentication-manager alias="somethingAuthenticationManager">
<authentication-provider user-service-ref="somethingUserDetailsService">
</authentication-provider>
</authentication-manager>
<authentication-manager id="authenticationManager">
<authentication-provider user-service-ref="customUserDetailsService">
</authentication-provider>
</authentication-manager>
The problem is that when I make a GET request to /api/something/v1 it seems like it's using the wrong authentication manager (the one with id authenticationManager) and not the somethingAuthenticationManager. This used to work before Spring Boot. Why is this and how can we resolve it?
Note that we're not using #EnableWebSecurity or any Java configuration related to Spring Security (afaik), everything is defined in our XML file.
Update
We start the application like this:
#EnableRabbit
#EnableRetry
#SpringBootApplication
#EnableAsync
#EnableAspectJAutoProxy(proxyTargetClass = true)
#ImportResource(locations = {"classpath*:META-INF/spring/applicationContext*.xml", "classpath:spring/webflow-config.xml"})
public class OurApplication {
public static void main(String[] args) {
SpringApplication.run(OurApplication.class, args);
}
}
which finds the WebappConfiguration that contains some additional configuration:
#Configuration
#ImportResource("classpath:spring/webmvc-config.xml")
public class WebappConfiguration implements WebMvcConfigurer {
#Bean
public TilesConfigurer tilesConfigurer() {
TilesConfigurer tilesConfigurer = new TilesConfigurer();
String[] defs = {
"classpath:WEB-INF/layouts/layouts.xml",
"WEB-INF/views/**/views.xml"
};
// Scan views directory for Tiles configurations
tilesConfigurer.setDefinitions(defs);
return tilesConfigurer;
}
#Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
#Override
protected void postProcessContext(Context context) {
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
context.setResources(new ExtractingRoot());
}
};
}
#Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> servletContainerCustomizer() {
return container -> container.addContextCustomizers(context -> context.setReloadable(false));
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/web-resources/**").addResourceLocations("classpath:/META-INF/web-resources/");
}
#Bean
public TilesViewResolver tilesViewResolver() {
TilesViewResolver tilesViewResolver = new TilesViewResolver();
tilesViewResolver.setRequestContextAttribute("requestContext");
tilesViewResolver.setExposedContextBeanNames("ownerLogoUrlFinder");
return tilesViewResolver;
}
#Bean
public DispatcherServletRegistrationBean dispatcherServletRegistrationBean() {
DispatcherServlet servlet = new DispatcherServlet();
servlet.setApplicationContext(new AnnotationConfigWebApplicationContext());
return new DispatcherServletRegistrationBean(servlet, "/");
}
#Bean
public FilterRegistrationBean<OpenEntityManagerInViewFilter> openEntityManagerInViewFilterRegistrationBean(OpenEntityManagerInViewFilter openEntityManagerInViewFilter) {
FilterRegistrationBean<OpenEntityManagerInViewFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(openEntityManagerInViewFilter);
registration.addUrlPatterns("/*");
registration.setName("openEntityManagerInViewFilter");
registration.setOrder(1);
return registration;
}
#Bean
public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() {
return new OpenEntityManagerInViewFilter();
}
}
Update 2
I get this when starting up:
2021-09-21 13:46:33.933 WARN 46673 --- [ main] o.s.b.f.parsing.FailFastProblemReporter : Configuration problem: Overriding globally registered AuthenticationManager
Offending resource: file [/Users/johan/myproject/target/classes/META-INF/spring/applicationContext-security.xml]
I have seen something similar and solved it by changing alias to id on my authentication-manager after reading this: https://github.com/spring-projects/spring-security/issues/2163

Commit failed while step execution data was already updated. Reverting to old version. Spring batch

I was having problem starting up spring batch application, which I mentioned here. Now I have update the code to use HibernateTransactionManager and my job has 6 steps, and first step works fine now, but second steps fails. Following is update code in which I have added HibernateTransactionManager.
BatchScheduler.Class
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
//#Configuration
#EnableScheduling
public class BatchScheduler {
#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 SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return launcher;
}
}
#Configuration
#EnableBatchProcessing
#Import({BatchScheduler.class})
public class LogBatchConfiguration {
private static final Logger log = LoggerFactory.getLogger(LogBatchConfiguration.class);
#Autowired private SimpleJobLauncher jobLauncher;
//**********New added
#Bean
public PlatformTransactionManager mytransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(createLocalSessionFactory(mainDataSource).getObject());
return transactionManager;
}
#Autowired
#Qualifier(value = "mainDataSource")
public DataSource mainDataSource;
#Autowired
#Qualifier(value = "toolsDataSource")
public DataSource toolsDataSource;
#Autowired public StepBuilderFactory stepBuilderFactory;
#Autowired public JobBuilderFactory jobBuilderFactory;
#Autowired private RestTemplate restTemplate;
#Qualifier(value = "createLocalSessionFactory")
#Autowired
private SessionFactory createLocalSessionFactory;
#Qualifier(value = "createToolSessionFactory")
#Autowired
private SessionFactory createToolSessionFactory;
#Bean
RestTemplate restTemplate(RestTemplateBuilder builder) {
RestTemplate restTemplate = new RestTemplate();
List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jsonConverter =
(MappingJackson2HttpMessageConverter) converter;
jsonConverter.setObjectMapper(new ObjectMapper());
jsonConverter.setSupportedMediaTypes(
ImmutableList.of(
new MediaType(
"application", "json", MappingJackson2HttpMessageConverter.DEFAULT_CHARSET),
new MediaType(
"text", "javascript", MappingJackson2HttpMessageConverter.DEFAULT_CHARSET)));
}
}
return restTemplate;
}
#Bean
public LocalSessionFactoryBean createLocalSessionFactory(
#Qualifier("mainDataSource") DataSource dataSource) {
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setPackagesToScan(
new String[] {
"com.abc.def..entities",
"com.abc.entities"
});
factory.setHibernateProperties(hibernateVCommitProperties());
return factory;
}
#Bean
public LocalSessionFactoryBean createToolSessionFactory(
#Qualifier("toolsDataSource") DataSource dataSource) {
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setPackagesToScan(
new String[] {
"com.abc.def..entities",
"com.abc.entities"
});
factory.setHibernateProperties(hibernateCommitProperties());
return factory;
}
#Scheduled(cron = "${server.cron}")
public void SyncJobTrigger() throws Exception {
if (log.isInfoEnabled()) {
}
JobParameters param =
new JobParametersBuilder()
.addString("JobID", String.valueOf(System.currentTimeMillis()))
.toJobParameters();
JobExecution execution = jobLauncher.run(populateServerDataJob(), param);
if (log.isInfoEnabled()) {
log.info("BATCH tools Server job finished with status: " + execution.getStatus());
}
}
//--------------------------------- JOBS ----------------------------------------------
#Bean
public Job populateServerDataJob() throws Exception {
return jobBuilderFactory
.get("populateData")
.start(serverRequestData()) // this step's writer is failing
.next(a)
.build();
}
#Bean
#StepScope
public HibernateCursorItemReader<Request> myRequestReader() throws Exception {
// returns reader and works fine as seen in logs, data is fetched
}
#Bean
#StepScope
public requestToServerProcessor requestToServerRequestProcessor() {
return new requestToServerProcessor(mainDataSource);
}
// WRITER
#Bean
#StepScope
public HibernateItemWriter<ServerRequestDetails> serverRequestWriter() {
HibernateItemWriter<ServerRequestDetails> writer = new HibernateItemWriter();
writer.setSessionFactory(createLocalSessionFactory(mainDataSource).getObject());
return writer;
}
#Bean
#JobScope
public Step serverRequestData() throws Exception {
return stepBuilderFactory
.get("getServerRequestData")
.transactionManager(mytransactionManager())/***** added manager here.
.<Request, ServerRequestDetails>chunk(100)
.reader(mylRequestReader())
.processor(requestToServerRequestProcessor())
.writer(serverRequestWriter())
.build();
}
}
DataSourceConfiguration.class
#Configuration
public class DataSourceConfiguration {
private static final Logger log = LoggerFactory.getLogger(DataSourceConfiguration.class);
#Value("${spring.datasource.usern}")
private String insightsDbUser;
#Value("${spring.datasource.pass}")
private String insightsDbPass;
#Value("${spring.datasource.url}")
private String insightsDbConnection;
#Value("${tools.datasource.user}")
private String toolsDbUser
#Value("${tools.datasource.pass}")
private String toolsDbPass;
#Value("${tools.datasource.url}")
private String toolsDbConnection;
#Bean(name = "mainDataSource")
#Primary
public DataSource mainDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl(insightsDbConnection);
dataSource.setUsername(insightsDbUser);
dataSource.setPassword(insightsDbPass);
if (log.isInfoEnabled()) {
//
}
return dataSource;
}
#Bean(name = "toolsDataSource")
public DataSource toolsDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl(toolsDbConnection);
dataSource.setUsername(toolsDbUser);
dataSource.setPassword(toolsDbPass);
if (log.isInfoEnabled()) {
//
}
return dataSource;
}
}
Now in this serverRequestData, is the first step of job, and step "a" is second step, step "a" code I have not put because it is exactly similar to step "serverRequestData". I have created a HibernateTransactionManager and specified that while running step, but now first step works fine.Earlier problem with first step was here. Now step "a" fails because of following error which seems similar to earlier failure but I do see extra stackTrace :
2021-04-16 09:56:52.986 INFO 47235 --- [main] o.s.batch.core.job.SimpleStepHandler : Executing step: [a]
2021-04-16 09:56:59.305 INFO 47235 --- [main] o.s.batch.core.step.tasklet.TaskletStep : Commit failed while step execution data was already updated. Reverting to old version.
2021-04-16 09:56:59.308 ERROR 47235 --- [main] o.s.batch.core.step.AbstractStep : Encountered an error executing step getVsyncDetails in job populateVtoolsServerDataJob
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:413)
at org.hibernate.internal.SessionImpl.checkTransactionNeededForUpdateOperation(SessionImpl.java:3397)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1354)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1349)
at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:148)
at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:96)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:919)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:727)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:152)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:258)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:208)
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:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy118.execute(Unknown Source)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:410)
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:776)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at com.CoreApplication.main(CoreApplication.java:29)
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.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
2021-04-16 09:56:59.309 INFO 47235 --- [main] o.s.batch.core.step.AbstractStep : Step: [a] executed in 6s323ms
2021-04-16 09:56:59.309 ERROR 47235 --- [main] o.s.batch.core.step.AbstractStep : Encountered an error saving batch meta data for step a in job populateServerDataJob. This job is now in an unknown state and should not be restarted.
org.springframework.dao.OptimisticLockingFailureException: Attempt to update step execution id=2 with wrong version (1), where current version is 2
at org.springframework.batch.core.repository.dao.MapStepExecutionDao.updateStepExecution(MapStepExecutionDao.java:106)
at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:196)
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:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy93.update(Unknown Source)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:275)
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:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy118.execute(Unknown Source)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:410)
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:136)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:140)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:173)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:160)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:155)
at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:150)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:776)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:322)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at com.CoreApplication.main(CoreApplication.java:29)
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.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
2021-04-16 09:56:59.313 INFO 47235 --- [main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=populateServerDataJob]] completed with the following parameters: [{}] and the following status: [UNKNOWN] in 9s178ms
I see one extra log
2021-04-16 09:56:59.305 INFO 47235 --- [main] o.s.batch.core.step.tasklet.TaskletStep : Commit failed while step execution data was already updated. Reverting to old version.
Which I did not see earlier.
Now since after adding HibernateTransactionManager, the first step writer is working fine, so I added same Transaction Manage while configuring step a. But now I am getting same error but with some extra log, so I think there can be some another reason behind this?
You are declaring a ResourcelessTransactionManager bean that will be used by default in Spring Batch. Since this transaction manager does not create any transaction, your hibernate item writer fails with this error.
You need to configure Spring Batch to use the HibernateTransactionManager (and remove the ResourcelessTransactionManager). This can be done with a custom Batch configurer as mentioned in the documentation here. In your case, it could be something like:
#Bean
public BatchConfigurer batchConfigurer(DataSource ds, SessionFactory sf) {
return new DefaultBatchConfigurer(ds) {
#Override
public PlatformTransactionManager getTransactionManager() {
return new HibernateTransactionManager(sf);
}
};
}

How to convert spring bean integration From XML to Java annotation based Config

I have this xml based configuration. But in my project I want to use java annotation based configuration. How to do the conversion?
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="mail.csonth.gov.uk"/>
</bean>
<bean id="registrationService" class="com.foo.SimpleRegistrationService">
<property name="mailSender" ref="mailSender"/>
<property name="velocityEngine" ref="velocityEngine"/>
</bean>
<bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<value>
resource.loader=class
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</value>
</property>
</bean>
</beans>
Create a class annotated with #Configuration (org.springframework.context.annotation.Configuration) and for each bean declaration in your XML file create a #Bean (org.springframework.context.annotation.Bean) method within this class.
#Configuration
public class MyConfiguration {
#Bean
public JavaMailSenderImpl mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("mail.csonth.gov.uk");
return mailSender;
}
#Bean
public SimpleRegistrationService registrationService(JavaMailSenderImpl mailSender, VelocityEngineFactoryBean velocityEngine) {
SimpleRegistrationService registrationService = new SimpleRegistrationService();
registrationService.setMailSender(mailSender);
registrationService.setVelocityEngine(velocityEngine);
return registrationService;
}
#Bean
public VelocityEngineFactoryBean velocityEngine() {
VelocityEngineFactoryBean velocityEngine = new VelocityEngineFactoryBean();
Properties velocityProperties = new Properties();
velocityProperties.put("resource.loader", "class");
velocityProperties.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
velocityEngine.setVelocityProperties(velocityProperties);
return velocityEngine;
}
}
This example assumes that the mailSender and velocityEngine beans are required elsewhere in your application config since this is implied by the XML config you supplied. If this is not the case i.e. if the mailSender and velocityEngine beans are only required to construct the registrationService bean then you do not need to declare the mailSender() and velocityEngine() methods as public nor do you need to annotate then with #Bean.
You can instruct Spring to read this configuration class by
Component scanning e.g. #ComponentScan("your.package.name")
Registering the class with an AnnotationConfigApplicationContext e.g.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(MyConfiguration.class);
context.refresh();
Answer of #glitch was helpful but I got an error at below line.
velocityEngine.setVelocityProperties("resource.loader=class", "class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
How ever I fixed that. Find below is the full implementation
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import com.vlclabs.adsops.service.SendEmailServiceImpl;
import org.springframework.ui.velocity.VelocityEngineFactoryBean;
import java.util.Properties;
#Configuration
public class EmailConfiguration {
#Bean
public JavaMailSenderImpl mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost("mail.csonth.gov.uk");
return mailSender;
}
#Bean
public SendEmailServiceImpl registrationService(JavaMailSenderImpl mailSender, VelocityEngineFactoryBean velocityEngine) {
SendEmailServiceImpl registrationService = new SendEmailServiceImpl();
registrationService.setMailSender(mailSender);
registrationService.setVelocityEngine(velocityEngine.getObject());
return registrationService;
}
#Bean
public VelocityEngineFactoryBean velocityEngine() {
VelocityEngineFactoryBean velocityEngine = new VelocityEngineFactoryBean();
Properties velocityProperties = new Properties();
velocityProperties.put("resource.loader", "class");
velocityProperties.put("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
velocityEngine.setVelocityProperties(velocityProperties);
return velocityEngine;
}
}

How to get Database connection in Spring using JUnit?

I'm trying to test the correct information given from DB using the services and the correct logic of the methods. In this simple example, I'm only using the statement assertEquals to compare the id given for the roleService, but I'm still getting errors. I have the following code:
[UPDATED]
Test method:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(value = { "classpath:applicationContext.xml" })
#Transactional
#WebAppConfiguration
#ComponentScan(basePackages ={ "com.project.surveyengine" },
excludeFilters = {#ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class) ,
#ComponentScan.Filter(type = FilterType.ANNOTATION, value = WebConfig.class)})
public class RoleServiceTest {
#Configuration
static class ContextConfiguration {
#Bean
public RoleService roleService() {
RoleService roleService = new RoleService();
// set properties, etc.
return roleService;
}
}
private final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
.setDefaultHighRepJobPolicyUnappliedJobPercentage(100));
private Closeable closeable;
#Before
public void setUp() {
helper.setUp();
ObjectifyService.register(Role.class);
closeable = ObjectifyService.begin();
}
#After
public void tearDown() {
closeable.close();
helper.tearDown();
}
#Autowired
private RoleService roleService;
#Test
public void existsRole() throws Exception{
Role role = roleService.getByName("ROLE_ADMIN");
assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());
}
}
RoleService is the service class that consult Database information using objectifyService from Google App Engine.
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
<context:component-scan base-package="com.project.surveyengine.config"/>
<!--Controllers-->
<bean id="inboxController" class="com.project.surveyengine.controller.InboxController" autowire="byType"></bean>
<bean id="mailController" class="com.project.surveyengine.controller.MailController" autowire="byType"></bean>
<bean id="loginController" class="com.project.surveyengine.controller.LoginController" autowire="byType"></bean>
<bean id="initController" class="com.project.surveyengine.controller.InitController" autowire="byType"></bean>
<!--Services-->
<bean id="answerService" class="com.project.surveyengine.service.impl.AnswerService" autowire="byType"></bean>
<bean id="blobService" class="com.project.surveyengine.service.impl.BlobService" autowire="byType"></bean>
<bean id="mailService" class="com.project.surveyengine.service.impl.MailService" autowire="byType"></bean>
<bean id="caseService" class="com.project.surveyengine.service.impl.CaseService" autowire="byType"></bean>
<bean id="roleService" class="com.project.surveyengine.service.impl.RoleService" autowire="byType"></bean>
</beans>
Into the com.project.surveyengine.config I have the folliwing three classes:
1)
public class MyXmlWebApplicationContext extends XmlWebApplicationContext {
protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
super.initBeanDefinitionReader(beanDefinitionReader);
if (SystemProperty.environment.value() == SystemProperty.Environment.Value.Production) {
beanDefinitionReader.setValidating(false);
beanDefinitionReader.setNamespaceAware(true);
}
}
}
2)
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{
#Bean
UrlBasedViewResolver resolver(){
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/views/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/statics/**").addResourceLocations("/statics/");
}
}
3)
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityContext extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/statics/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin()
//...more code
}
}
I'm getting this errors:
Dec 20, 2016 4:40:03 PM
com.google.appengine.api.datastore.dev.LocalDatastoreService init
INFO: Local Datastore initialized: Type: High Replication Storage:
In-memory
java.lang.NullPointerException at
com.project.surveyengine.service.impl.RoleServiceTest.existsRole(RoleServiceTest.java:111)
RoleServiceTest.java:111 = assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());
Did you try to add #WebAppConfiguration as suggested in the documentation http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/web/WebAppConfiguration.html ?
I'd wirte your test code in this way
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(value = { "classpath:applicationContext.xml" })
#TransactionConfiguration(transactionManager="txMgr", defaultRollback=false)
#Transactional
#WebAppConfiguration
#ComponentScan(basePackages ={ "com.project.surveyengine" }, excludeFilters = {
#ComponentScan.Filter(type = FilterType.ANNOTATION, value = Configuration.class) })
public class RoleServiceTest {
#Autowired
private RoleService roleService;
#Test
public void existsRole() throws Exception{
Role role = roleService.getByName("ROLE_ADMIN");
assertEquals("Correct test", Long.valueOf("5067160539889664"), role.getId());
}
}
as you can see i added the annotation #WebAppConfiguration too
I hope this can help you

Spring Batch configuration exception

I have next spring batch configuration class:
#Configuration
#EnableBatchProcessing
public class BatchJobConfiguration {
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet(new Tasklet() {
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
return null;
}
})
.build();
}
#Bean
public Job job(Step step1) throws Exception {
return jobBuilderFactory.get("job1")
.incrementer(new RunIdIncrementer())
.start(step1)
.build();
}
}
When I start my application I receive next exception:
Caused by: java.lang.ClassCastException:
org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean$$EnhancerBySpringCGLIB$$65a19538
cannot be cast to
org.springframework.batch.core.repository.JobRepository at
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$14f7a80d.jobRepository()
at
org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.jobBuilders(AbstractBatchConfiguration.java:58)
at
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$14f7a80d.CGLIB$jobBuilders$6()
at
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$14f7a80d$$FastClassBySpringCGLIB$$c6b630d7.invoke()
at
org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at
org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at
org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$$EnhancerBySpringCGLIB$$14f7a80d.jobBuilders()
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:497) at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
In pom.xml I have next dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
Thanks in advance.
The JobRepository instance needs to be renamed, otherwise Spring context will find incorrect candidates for autowiring.

Categories