cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyTastTasklet' - spring

I am developing Spring Boot Batch Example. In this example, I have created BatchJPA core module which has Entities, JPARepository and DB configurations.
This module adding into another Spring Module as dependency and in this module, I am adding code related specific batch jobs (like custom repository etc). I have total 15 batch jobs and I will be creating separate Spring Boot project with BatchJPA dependency.
10-08-2018 14:54:11.853 [main] WARN org.springframework.context.support.ClassPathXmlApplicationContext.refresh - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'MyTestTasklet': Initialization of bean failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'transactionManager' available
10-08-2018 14:54:11.855 [main] INFO org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener.logAutoConfigurationReport -
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
10-08-2018 14:54:11.919 [main] ERROR org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter.report -
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named 'transactionManager' that could not be found.
Action:
Consider defining a bean named 'transactionManager' in your configuration.
Code below:
#Service
public class MyTaskTasklet implements Tasklet {
#Autowired
private MyCustomerCustomRepository myCustomerCustomRepository;
#Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
List<MyTest> mydata = myCustomerCustomRepository.getElligibleData();
if (!mydata.isEmpty()) {
System.out.println("XXXXXX = " + mydata.size());
}
chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext()
.put("listOfData", mydata);
return RepeatStatus.FINISHED;
}
}
Another file:
#Component
#EnableBatchProcessing
public class MyJobLauncher {
public void executeJob() {
String[] springConfig = { "jobs/ABC.xml"};
ApplicationContext context = new ClassPathXmlApplicationContext(springConfig);
JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
Job job = (Job) context.getBean("MyJobId");
try {
JobParameters jobParameters = new JobParametersBuilder().addString("runMode", "DATA")
.addDate("date", new Date()).addLong("time", System.currentTimeMillis()).toJobParameters();
jobLauncher.run(job, jobParameters);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
and another file
MainApplication
#SpringBootApplication
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
public class MainApplication implements CommandLineRunner {
#Autowired
private MyJobLauncher jobLauncher;
public static void main(String[] args) {
SpringApplication.run(MyJobLauncher.class, args);
}
#Override
public void run(String... args) throws Exception {
jobLauncher.executeJob();
}
}

Related

SpringBootTest, Testcontainers, container start up - Mapped port can only be obtained after the container is started

I am using docker/testcontainers to run a postgresql db for testing. I have effectively done this for unit testing that is just testing the database access. However, I have now brought springboot testing into the mix so I can test with an embedded web service and I am having problems.
The issue seems to be that the dataSource bean is being requested before the container starts.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [com/myproject/integrationtests/IntegrationDataService.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
Caused by: java.lang.IllegalStateException: Mapped port can only be obtained after the container is started
Here is my SpringBootTest:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes = {IntegrationDataService.class, TestApplication.class},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringBootTestControllerTesterIT
{
#Autowired
private MyController myController;
#LocalServerPort
private int port;
#Autowired
private TestRestTemplate restTemplate;
#Test
public void testRestControllerHello()
{
String url = "http://localhost:" + port + "/mycontroller/hello";
ResponseEntity<String> result =
restTemplate.getForEntity(url, String.class);
assertEquals(result.getStatusCode(), HttpStatus.OK);
assertEquals(result.getBody(), "hello");
}
}
Here is my spring boot application referenced from the test:
#SpringBootApplication
public class TestApplication
{
public static void main(String[] args)
{
SpringApplication.run(TestApplication.class, args);
}
}
Here is the IntegrationDataService class which is intended to startup the container and provide the sessionfactory/datasource for everything else
#Testcontainers
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#EnableTransactionManagement
#Configuration
public class IntegrationDataService
{
#Container
public static PostgreSQLContainer postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer("postgres:9.6")
.withDatabaseName("test")
.withUsername("sa")
.withPassword("sa")
.withInitScript("db/postgresql/schema.sql");
#Bean
public Properties hibernateProperties()
{
Properties hibernateProp = new Properties();
hibernateProp.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
hibernateProp.put("hibernate.format_sql", true);
hibernateProp.put("hibernate.use_sql_comments", true);
// hibernateProp.put("hibernate.show_sql", true);
hibernateProp.put("hibernate.max_fetch_depth", 3);
hibernateProp.put("hibernate.jdbc.batch_size", 10);
hibernateProp.put("hibernate.jdbc.fetch_size", 50);
hibernateProp.put("hibernate.id.new_generator_mappings", false);
// hibernateProp.put("hibernate.hbm2ddl.auto", "create-drop");
// hibernateProp.put("hibernate.jdbc.lob.non_contextual_creation", true);
return hibernateProp;
}
#Bean
public SessionFactory sessionFactory() throws IOException
{
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setHibernateProperties(hibernateProperties());
sessionFactoryBean.setPackagesToScan("com.myproject.model.entities");
sessionFactoryBean.afterPropertiesSet();
return sessionFactoryBean.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() throws IOException
{
return new HibernateTransactionManager(sessionFactory());
}
#Bean
public DataSource dataSource()
{
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(postgreSQLContainer.getDriverClassName());
dataSource.setUrl(postgreSQLContainer.getJdbcUrl());
dataSource.setUsername(postgreSQLContainer.getUsername());
dataSource.setPassword(postgreSQLContainer.getPassword());
return dataSource;
}
}
The error occurs on requesting the datasource bean from the sessionFactory from one of the Dao classes before the container starts up.
What the heck am I doing wrong?
Thanks!!!
The reason for your java.lang.IllegalStateException: Mapped port can only be obtained after the container is started exception is that when the Spring Context now gets created during your test with #SpringBootTest it tries to connect to the database on application startup.
As you only launch your PostgreSQL inside your IntegrationDataService class, there is a timing issue as you can't obtain the JDBC URL or create a connection on application startup as this bean is not yet properly created.
In general, you should NOT use any test-related code inside your IntegrationDataService class. Starting/stopping the database should be done inside your test setup.
This ensures to first start the database container, wait until it's up- and running, and only then launch the actual test and create the Spring Context.
I've summarized the required setup mechanism for JUnit 4/5 with Testcontainers and Spring Boot, that help you get the setup right.
In the end, this can look like the following
// JUnit 5 example with Spring Boot >= 2.2.6
#Testcontainers
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ApplicationIT {
#Container
public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer()
.withPassword("inmemory")
.withUsername("inmemory");
#DynamicPropertySource
static void postgresqlProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
#Test
public void contextLoads() {
}
}

No qualifying bean of type 'org.springframework.batch.core.Step' available

Error:
2020-04-24 00:52:50,892 INFO bcm.BankruptcyCasePurgeDownloadJobProcessingApplication - No active profile set, falling back to default profiles: default
2020-04-24 00:52:53,038 WARN annotation.AnnotationConfigApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.spri
ngframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bankruptcyCasePurgeDownloadJob' defined in class path resource [com/cgi/ec/down
load/bcm/BankruptcyCasePurgeDownloadSetupConfiguration.class]: Unsatisfied dependency expressed through method 'bankruptcyCasePurgeDownloadJob' parameter 1; nested exce
ption is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.batch.core.Step' available: expected at least
1 bean which qualifies as autowire candidate. Dependency annotations: {}
2020-04-24 00:52:53,071 INFO logging.ConditionEvaluationReportLoggingListener -
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
//Java code
#SpringBootApplication
#ComponentScan(basePackages = {"com.cgi.ec.download.bcm", "com.cgi.ec.interfaces.util.properties"})
public class BankruptcyCasePurgeDownloadJobProcessingApplication {
private static final XLogger LOG = XLoggerFactory.getXLogger(BankruptcyCasePurgeDownloadJobProcessingApplication.class);
public static void main(String[] args) throws Exception {
String arguments = Arrays.toString(args);
LOG.debug("[main] starting with args: {}", arguments);
ConfigurableApplicationContext ctx = SpringApplication.run(BankruptcyCasePurgeDownloadJobProcessingApplication.class, args);
JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);
System.out.println("Spring boot success");
Job jobInstance = ctx.getBean("bankruptcyCasePurgeDownloadJob", Job.class);
jobLauncher.run(jobInstance, InterfacesCommonConfiguration.getJobParameters());
}
}
#Configuration
#EnableBatchProcessing
public class BankruptcyCasePurgeDownloadSetupConfiguration {
private static final XLogger LOG = XLoggerFactory.getXLogger(BankruptcyCasePurgeDownloadSetupConfiguration.class);
private static final String JOB_NAME = "bankruptcyCasePurgeDownload";
/**
* Main SpringBatch Job that defines the steps to the batch job
*
* #return SpringBatch Job object
*/
#Bean
public Job testStepJob(JobBuilderFactory jobBuilderFactory, Step bankruptcyCasePurgeDownloadStep) {
LOG.entry();
return LOG.exit(jobBuilderFactory.get(JOB_NAME + "Job")
.incrementer(new RunIdIncrementer())
.flow(testStep)
.end()
.build());
}
You are trying to inject a bean of type Step here:
#Bean
public Job testStepJob(JobBuilderFactory jobBuilderFactory, Step bankruptcyCasePurgeDownloadStep) {
...
}
but according to the error, your application context does not contain a bean of that type.
Make sure you import a configuration class containing your step bean definition or define a bean of that type in your scanned packages.

Encountered invalid #Scheduled method 'methodName': Only no-arg methods may be annotated with #Scheduled

plz I don't know wath is the exact problem in the code if I add Scheduled annotatiçon in my code suddenly this error appears
if you have any soulustion please.
plz I don't know wath is the exact problem in the code if I add Scheduled annotatiçon in my code suddenly this error appears
if you have any soulustion please.
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
12-09-2019 18:11:54.908 [restartedMain] ERROR o.s.boot.SpringApplication.reportFailure - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'missionResource': Unsatisfied dependency expressed through field 'missionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'missionImpl' defined in file [C:\Users\El Oussa\Desktop\vgas-api\vgas-manager\target\classes\ma\valueit\vgas\manager\business\impl\MissionImpl.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: Encountered invalid #Scheduled method 'editMission': Only no-arg methods may be annotated with #Scheduled
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
I have added #EnableScheduling in SpringBootApplication
--------------------------------------------------------
#SpringBootApplication
#EnableScheduling
#ComponentScan("com.qaiboub.vs")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#Service
public class MissionImpl extends CrudManagerImpl<MissionDto, Integer, MissionEntity, MissionService, MissionConverter> implements MissionManager {
#Autowired
private MissionService missionService;
#Autowired
private MissionConverter missionConverter;
enter code here
#Override
public MissionService getService() {
return missionService;
}
#Override
public MissionConverter getConverter() {
return missionConverter;
}
#Scheduled(cron = "0 15 18 * * *")
public void editMission(Integer id, MissionDto missionDto) {
if (StringUtils.isEmpty(id)) {
throw new MissingIdException();
}
if (missionDto == null) {
throw new InvalidPayloadException();
}
if (!id.equals(missionDto.getId())) {
throw new BusinessException(CommonErrorCode.TRYING_TO_EDIT_ANOTHER_ENTITY);
}
missionEntity = missionConverter.convertFrom(missionDto);
missionEntity = missionService.save(missionEntity);
}
}
remove the function arg. Scheduler don't take arg in their functions
You need to remove all the arguments from the function, the scheduler does not accept any argument
public void syncData(#RequestParam(name = "created_at_from") String createdAtFrom,
#RequestParam(name = "created_at_to") String createdAtTo) {}
Correct format is
public void syncData() throws Exception {}
Use this link for additional details:
https://www.baeldung.com/shedlock-spring

Unable to schedule Quartz job

I have written a small Spring Boot service using Quartz. I am trying to schedule a job using the code below. However, I am repeatedly getting the following error:
ERROR[my-service] [2017-01-22 17:38:37,328] [] [main] [SpringApplication]: Application startup failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'schedulerFactoryBean' defined in class path resource [com/myservice/configuration/QuartzConfiguration.class]: Invocation of init method failed; nested exception is org.quartz.JobPersistenceException: Couldn't store trigger 'group1.trigger1' for 'group1.job1' job:The job (group1.job1) referenced by the trigger does not exist. [See nested exception: org.quartz.JobPersistenceException: The job (group1.job1) referenced by the trigger does not exist.]
Needless to say, the job never gets scheduled. Here is the relevant code:
#Slf4j
#NoArgsConstructor
public class TimedJob implements Job {
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
log.debug("**********timed job****************");
}
}
#Configuration
public class QuartzConfiguration {
...
#Inject
MyDao myDao;
#Bean
public SchedulerFactoryBean schedulerFactoryBean(ApplicationContext applicationContext) throws SchedulerException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setAutoStartup(true);
factory.setOverwriteExistingJobs(true);
QuartzJobFactory jobFactory = new QuartzJobFactory();
jobFactory.setApplicationContext(applicationContext);
factory.setJobFactory(jobFactory);
factory.setDataSource(dataSource());
factory.setSchedulerContextAsMap(Collections.singletonMap("my_dao", myDao));
JobDetail jobDetail = JobBuilder.newJob()
.ofType(TimedJob.class)
.storeDurably()
.withDescription("desc")
.withIdentity("job1", "group1")
.build();
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, 10);
Trigger trigger = TriggerBuilder
.newTrigger()
.startAt(calendar.getTime())
.withSchedule(
SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()
)
.forJob(jobDetail)
.withIdentity("trigger1", "group1")
.build();
factory.setTriggers(trigger);
Properties quartzProperties = new Properties();
quartzProperties.setProperty("org.quartz.scheduler.instanceName", instanceName);
quartzProperties.setProperty("org.quartz.scheduler.instanceId", instanceId);
quartzProperties.setProperty("org.quartz.threadPool.threadCount", threadCount);
quartzProperties.setProperty("org.quartz.jobStore.driverDelegateClass", driverDelegateClassName);
factory.setQuartzProperties(quartzProperties);
factory.start();
return factory;
}
This is almost exactly copied from the Quartz tutorials here. What am I doing wrong?
I guess you need setting your jobDetail to your factory instance.
The below URL might help you.
http://www.baeldung.com/spring-quartz-schedule

NullPointerException while deploying Quartz Scheduler with spring on Tomcat

I am trying to use Quartz 2.2.0 with spring 3.2.x, using ServletContextListener for listening FileChangeListener class.Is My importManagerService object is null? Any suggestions? Not getting how to resolve it
Error While deploying
INFO [2013-10-04 15:13:16.009] [localhost-startStop-1]: org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
ERROR [2013-10-04 15:13:16.061] [DefaultQuartzScheduler_Worker-1]: org.quartz.core.JobRunShell - Job g1.t1 threw an unhandled Exception:
java.lang.NullPointerException at
com.demo.portal.web.importExportFile.ScheduleImportFile.execute(ScheduleImportFile.java:40)
at org.quartz.core.JobRunShell.run(JobRunShell.java:207)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:560)
ERROR [2013-10-04 15:13:16.065] [DefaultQuartzScheduler_Worker-1]: org.quartz.core.ErrorLogger - Job (g1.t1 threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: java.lang.NullPointerException]
at org.quartz.core.JobRunShell.run(JobRunShell.java:218)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:560)
Caused by: java.lang.NullPointerException
at com.happiestminds.portal.web.importExportFile.ScheduleImportFile.execute(ScheduleImportFile.java:40)
at org.quartz.core.JobRunShell.run(JobRunShell.java:207)
... 1 more
FileChangeListener
public class FileChangeListener implements ServletContextListener {
private static final Logger logger = Logger.getLogger(FileChangeListener.class);
#Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("Stopping Application successfully");
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
logger.info("Initializing Application successfully..........");
JobDetail job = JobBuilder.newJob(ScheduleImportFile.class).withIdentity("t1", "g1").build();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "g1").startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(60).repeatForever()).forJob("t1", "g1").build();
SchedulerFactory schFactory = new StdSchedulerFactory();
Scheduler sch;
try {
sch = schFactory.getScheduler();
sch.start();
sch.scheduleJob(job, trigger);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
ScheduleImportFile
**public class ScheduleImportFile implements Job{
#Autowired
ImportManagerService importManagerService;
#Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {
//some logic for reading and parsing files
Line no. 40
Map<String, List<File>> fileToBeProcessMap = importManagerService.getFilesInfo(config);
Config is object of Configuration class
}**
Web.xml
<listener>
<listener-class>com.demo.portal.web.importExportFile.FileChangeListener</listener-class>
</listener>
As you identified, We can not auto wire of Spring beans inside Quartz job as Spring Bean's life cycle is forbidden in side a job class.
But we can get those spring beans through a simple way without loading Spring bean xml again.
Here is it.
public class MyJob Implements Job
{
private MyBean myBean;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException
{
getBeansFromContext(context);
mybean.doSomeThing();
}
private void getBeansFromContext(JobExecutionContext context) throws SchedulerException
{
ApplicationContext applicationContext = (ApplicationContext)context.getScheduler().getContext().get("applicationContext");
this.mybean=applicationContext.getBean(MyBean.class);
}
}
You should have your schedulerFactoryBean configired in your beans.xml.
<beans:bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<beans:property name="jobFactory">
<beans:bean class="org.springframework.scheduling.quartz.SpringBeanJobFactory"></beans:bean>
</beans:property>
...
<beans:property name="applicationContextSchedulerContextKey"
value="applicationContext" /> -- Here is the guy!!
Hope this helps you.

Resources