Problem in Building Spring Boot Batch Application: Spring Boot - java

I am building a Spring Boot application (version 2.7.7) to dump data from .csv to MySQL db. I am getting several exceptions on building the project.
application.properties-
spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/batch_db
spring.datasource.username=hbstudent
spring.datasource.password=hbstudent
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
server.port=8081
spring.batch.jdbc.initialize-schema=always
#to initalize the tables
Batch Configuration-
#Configuration
#EnableBatchProcessing
public class BatchConfig {
#Autowired
private DataSource dataSource;
#Bean
public FlatFileItemReader<User> reader(){
FlatFileItemReader<User> reader=new FlatFileItemReader<>();
reader.setResource(new ClassPathResource("records.csv"));
reader.setLineMapper(getLineMapper()); //how to map the line which is read.
reader.setLinesToSkip(1); // skip lines when error occurs
return reader;
}
private LineMapper<User> getLineMapper() {
DefaultLineMapper<User> lineMapper=new DefaultLineMapper<>();
DelimitedLineTokenizer delimitedLineTokenizer=new DelimitedLineTokenizer();
delimitedLineTokenizer.setNames(new String[]{"Roll Number","Name of Student","Personal Email ID","Email ID","MOBILE NO"});
delimitedLineTokenizer.setIncludedFields(new int[]{1,2,3,4,5});
BeanWrapperFieldSetMapper<User> fieldSetMapper=new BeanWrapperFieldSetMapper<>();
fieldSetMapper.setTargetType(User.class);
lineMapper.setLineTokenizer(delimitedLineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
return lineMapper;
}
#Bean
public UserItemProcessor processor(){
return new UserItemProcessor();
}
#Bean
public JdbcBatchItemWriter<User> writer(){
JdbcBatchItemWriter<User> writer= new JdbcBatchItemWriter<>();
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<User>());
writer.setSql("insert into user(rollNo,name,personalEmail,officialEmail,mobileNo) values (:rollNo,:name,:personalEmail,:officalEmail,:mobileNo)");
writer.setDataSource(dataSource);
return writer;
}
#Bean
public Job importUserJob(){
return new JobBuilder("USER_IMPORT_JOB")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
#Bean
public Step step1(){
return new StepBuilder("Step 1")
.<User,User>chunk(5)
.reader(reader())
.writer(writer())
.build();
}
}
On building the project I am getting the following exceptions-
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [com.example.spring_boot_batch_demo.SpringBootBatchDemoApplication]; nested exception is java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration$DataSourceInitializerConfiguration
at org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClassParser.java:609) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser.access$800(ConfigurationClassParser.java:110) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.lambda$processGroupImports$1(ConfigurationClassParser.java:812) ~[spring-context-5.3.24.jar:5.3.24]
at java.base/java.util.ArrayList.forEach(Unknown Source) ~[na:na]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:809) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:780) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:192) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.7.jar:2.7.7]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.7.jar:2.7.7]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.7.jar:2.7.7]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.7.jar:2.7.7]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.7.jar:2.7.7]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.7.jar:2.7.7]
at com.example.spring_boot_batch_demo.SpringBootBatchDemoApplication.main(SpringBootBatchDemoApplication.java:10) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.7.7.jar:2.7.7]
Caused by: java.lang.IllegalStateException: Error processing condition on org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration$DataSourceInitializerConfiguration
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) ~[spring-boot-autoconfigure-2.7.7.jar:2.7.7]
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:225) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser.processMemberClasses(ConfigurationClassParser.java:371) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:271) ~[spring-context-5.3.24.jar:5.3.24]
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:249) ~[spring-context-5.399) ~[spring-context-5.3.24.jar:5.3.24]
... 24 common frames omittedCaused by: java.lang.IllegalArgumentException: No enum constant org.springframework.boot.sql.init.DatabaseInitializationMode.ALWAYS
at java.base/java.lang.Enum.valueOf(Unknown Source) ~[na:na]
at org.springframework.boot.sql.init.DatabaseInitializationMode.valueOf(DatabaseInitializationMode.java:26) ~[spring-boot-2.7.7.jar:2.7.7]
at org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition.getDatabaseInitializationMode(OnDatabaseInitializationCondition.java:75) ~[spring-boot-autoconfigure-2.7.7.jar:2.7.7]
at org.springframework.boot.autoconfigure.sql.init.OnDatabaseInitializationCondition.getMatchOutcome(OnDatabaseInitializationCondition.java:60) ~[spring-boot-autoconfigure-2.7.7.jar:2.7.7]
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.7.7.jar:2.7.7]
... 30 common frames omitted
For referred several other posts which stated versioning problem, but it didn't help.
I cannot find the problem with the code, can somebody help me?

I have analysed your code, Here are my findings.
Found some issues in BatchConfig class. You are using new JobBuilder(), new StepBuilder() while creating Job and Step. The right way is to use JobBuilderFactory, StepBuilderFactory.
I can see entity class (user) name is in lower, It should be in camelcase (User).
PS: I tested with PostgreSQL database using these properties but I am sure it will work with MySQL database as well
application.properties
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/batch_db
spring.datasource.username=root
spring.datasource.password=admin
#show the queries in the console
spring.jpa.show-sql=true
#to format the queries for readability
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.globally_quoted_identifiers=true
server.port=8081
spring.batch.jdbc.initialize-schema=always
#spring.batch.job.enabled=false
#to initalize the tables
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ayushsingh</groupId>
<artifactId>spring_boot_batch_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring_boot_batch_demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.mysql</groupId>-->
<!-- <artifactId>mysql-connector-j</artifactId>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
BatchConfig
package com.ayushsingh.spring_boot_batch_demo.config;
import com.ayushsingh.spring_boot_batch_demo.entities.User;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.LineMapper;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import javax.sql.DataSource;
#Configuration //this is important- enables batch processing in the project
#EnableBatchProcessing
public class BatchConfig {
#Autowired
private DataSource dataSource;
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Bean
public FlatFileItemReader<User> reader(){
FlatFileItemReader<User> reader=new FlatFileItemReader<>();
reader.setResource(new ClassPathResource("records.csv"));
reader.setLineMapper(getLineMapper()); //how to map the line which is read.
reader.setLinesToSkip(1); // skip lines when error occurs
return reader;
}
private LineMapper<User> getLineMapper() {
DefaultLineMapper<User> lineMapper=new DefaultLineMapper<>();
DelimitedLineTokenizer delimitedLineTokenizer=new DelimitedLineTokenizer();
delimitedLineTokenizer.setNames(new String[]{"Roll Number","Name of Student","Personal Email ID","SMVDU Email ID","MOBILE NO"});
delimitedLineTokenizer.setIncludedFields(new int[]{1,2,3,4,5});
BeanWrapperFieldSetMapper<User> fieldSetMapper=new BeanWrapperFieldSetMapper<>();
fieldSetMapper.setTargetType(User.class);
lineMapper.setLineTokenizer(delimitedLineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
return lineMapper;
}
#Bean
public UserItemProcessor processor(){
return new UserItemProcessor();
}
#Bean
public JdbcBatchItemWriter<User> writer(){
JdbcBatchItemWriter<User> writer= new JdbcBatchItemWriter<>();
writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<User>());
writer.setSql("insert into user(rollNo,name,personalEmail,officialEmail,mobileNo) values (:rollNo,:name,:personalEmail,:officalEmail,:mobileNo)");
writer.setDataSource(dataSource);
return writer;
}
#Bean
public Job importUserJob(){
return jobBuilderFactory.get("USER_IMPORT_JOB")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
#Bean
public Step step1(){
return stepBuilderFactory.get("Step 1")
.<User,User>chunk(5)
.reader(reader())
.writer(writer())
.build();
}
}

Related

Spring MVC RestController 404 The requested resource is not available

I am trying to write a simple 'hello world' application using Spring MVC.
My goal is to send a GET response and receive a text message, however it keeps returning 404 "The requested resource [/api/hello] is not available". What can potentially be wrong? Below is my code:
package org.example.rest.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/api")
public class MyRestController {
#GetMapping("/hello")
public String hello() {
return "Hello";
}
}
Config
package org.example.rest.configuration;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.util.Properties;
#EnableWebMvc
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "org.example.rest")
public class MyConfig {
#Bean
public DataSource dataSource() {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/my_db?useSSL=false&serverTimezone=UTC");
dataSource.setUser("bestuser");
dataSource.setPassword("bestuser");
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactoryBean() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("org.example.rest.entity");
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect",
"org.hibernate.dialect.MySQLDialect");
hibernateProperties.setProperty("hibernate.show_sql",
"true");
sessionFactoryBean.setHibernateProperties(hibernateProperties);
return sessionFactoryBean;
}
#Bean
public HibernateTransactionManager hibernateTransactionManager() {
HibernateTransactionManager manager = new HibernateTransactionManager();
manager.setSessionFactory(sessionFactoryBean().getObject());
return manager;
}
}
package org.example.rest.configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class MyWebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{MyConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring-rest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.4.24.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
</dependency>
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
I am using IntelliJ IDEA 2022.2.2 (Ultimate Edition).
Server is Tomcat 9.0.71

Could not autowire. No beans of 'JobRepositoryTestUtils' type found. With SpringBatchTest Annotation added

I am working on a Spring Batch unit testing using the #SpringBatchTest annotation which is supposed to automatically add the beans for JobLauncherTestUtils and JobRepositoryTestUtils.
Here's the Job configuration class:
#Configuration
#EnableBatchProcessing
public class JobConfiguration {
#Bean
public Job getJob(JobBuilderFactory jobBuilderFactory,
#Qualifier("flow_master") Flow flowMaster) {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.start(flowMaster)
.build().build();
}
}
Here's the Test Class:
#ExtendWith(SpringExtension.class)
#SpringBatchTest
#ContextConfiguration(classes = JobConfiguration.class)
public class SpringBatchTest {
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Before
public void clearJobExecutions() {
this.jobRepositoryTestUtils.removeJobExecutions();
}
#Test
public void testMyJob() throws Exception {
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
Problem:
I am getting the error messages:
Could not autowire. No beans of 'JobLauncherTestUtils' type found.
I have cloned some repo examples which are supposed to work but I am getting the same error for all of them.
Am I missing something?
You did not share your imports but you are probably mixing imports between junit4 and junit5. I'm not able to reproduce your error. Here is a complete example:
The job configuration class:
package com.example.demo;
import javax.sql.DataSource;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
#Configuration
#EnableBatchProcessing
public class MyJobConfig {
#Bean
public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) {
return jobs.get("job")
.start(steps.get("step")
.tasklet((contribution, chunkContext) -> {
System.out.println("Hello world!");
return RepeatStatus.FINISHED;
}).build())
.build();
}
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("/org/springframework/batch/core/schema-h2.sql")
.build();
}
public static void main(String[] args) throws Exception {
ApplicationContext context = new AnnotationConfigApplicationContext(MyJobConfig.class);
JobLauncher jobLauncher = context.getBean(JobLauncher.class);
Job job = context.getBean(Job.class);
jobLauncher.run(job, new JobParameters());
}
}
The test class:
package com.example.demo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.JobRepositoryTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
#ExtendWith(SpringExtension.class)
#SpringBatchTest
#ContextConfiguration(classes = MyJobConfig.class)
class MyJobConfigTest {
#Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
#Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
#BeforeEach
public void clearJobExecutions() {
this.jobRepositoryTestUtils.removeJobExecutions();
}
#Test
public void testMyJob() throws Exception {
// given
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
// when
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
// then
Assertions.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
and the pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>so67767525</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>so67767525</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- While this has "boot" in the name, it does not bring any Spring Boot feature. -->
<!-- It is used to manage Spring projects dependencies that are known to work correctly together -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.4.6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
The test runs successfully without the error you mentioned.

Hibernate - Unable to resolve connection default schema: Unable to use Java 1.7 Connection#getSchema

Summary
While trying to save items to database i faced an issue, that hibernate creates tables with correct columns, but never populates them. I assume there is a problem with obtaining default schema in some cases, but the cause is spring, driver or hibernate itself?
stacktrace:
""2019-01-28 12:49:31 - Database ->
name : PostgreSQL
version : 10.6
major : 10
minor : 6
""2019-01-28 12:49:31 - Driver ->
name : PostgreSQL Native Driver
version : PostgreSQL 9.1 JDBC4 (build 901)
major : 9
minor : 1
""2019-01-28 12:49:31 - JDBC version : 4.0
""2019-01-28 12:49:31 - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQL94Dialect
""2019-01-28 12:49:31 - Unable to use Java 1.7 Connection#getSchema
""2019-01-28 12:49:31 - Unable to resolve connection default schema
"org.hibernate.HibernateException: Use of DefaultSchemaNameResolver requires Dialect to provide the proper SQL statement/command but provided Dialect [org.hibernate.dialect.PostgreSQL94Dialect] did not return anything from Dialect#getCurrentSchemaCommand
at org.hibernate.engine.jdbc.env.internal.DefaultSchemaNameResolver$SchemaNameResolverFallbackDelegate.resolveSchemaName(DefaultSchemaNameResolver.java:100)
at org.hibernate.engine.jdbc.env.internal.DefaultSchemaNameResolver.resolveSchemaName(DefaultSchemaNameResolver.java:76)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.determineCurrentSchemaName(JdbcEnvironmentImpl.java:298)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl.<init>(JdbcEnvironmentImpl.java:232)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:114)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:179)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:84)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:474)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:85)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:689)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:724)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:615)
at org.springframework.orm.hibernate5.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1804)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1741)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1112)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1079)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:580)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:543)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:711)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:684)
at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessProperties(PersistenceAnnotationBeanPostProcessor.java:356)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:338)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1237)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:218)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1308)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1154)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
at ru.legionofone.klassikaplusserver.KlassikaplusServerApplication.main(KlassikaplusServerApplication.java:15)
Background:
This is a backend server for a mobile app, tipical heroku free dyno.
Using postgreSQL 10.0.
Problem reproduces on both local environment and on heroku dyno.
POM.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.legionofone</groupId>
<artifactId>klassikaplusserver</artifactId>
<version>0.0.2-SNAPSHOT</version>
<name>klassikaplusserver</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>9</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>7.0.55</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.12.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/postgresql/postgresql -->
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-hibernate -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-hibernate</artifactId>
<version>1.2.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.intellij/annotations -->
<dependency>
<groupId>com.intellij</groupId>
<artifactId>annotations</artifactId>
<version>12.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Code
I've tried to configure hibernate with different dialects, but it does not change a thing. Also tried to persist items with session or entity manager, no success either.
HibernateConf
import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
#EnableTransactionManagement
public class HibernateConf {
private static final Logger logger = LoggerFactory.getLogger(HibernateConf.class);
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("ru.legionofone.klassikaplusserver.model.persistance");
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
#Bean
public DataSource dataSource() {
String dbUrl = System.getenv("JDBC_DATABASE_URL");
String username = System.getenv("JDBC_DATABASE_USERNAME");
String password = System.getenv("JDBC_DATABASE_PASSWORD");
logger.info(new StringBuilder()
.append("Starting server on database: ")
.append("URL: ").append(dbUrl).append(";")
.append("User ").append(username).append(";")
.append("Password ").append(password).append(";")
.toString());
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl(dbUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
#Bean
public PlatformTransactionManager hibernateTransactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
private final Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "update");
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL94Dialect");
hibernateProperties.setProperty("ShowSqlEnabled", "true");
// hibernateProperties.setProperty("hibernate.default_schema", "public");
// hibernateProperties.setProperty("hibernate.connection.autocommit", "true");
return hibernateProperties;
}
}
Dao
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.naming.OperationNotSupportedException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.io.Serializable;
import java.util.List;
public abstract class AbstractHibernateDao<T extends Serializable> {
private static final Logger logger = LoggerFactory.getLogger(AbstractHibernateDao.class);
protected Class<T> clazz;
#Autowired
SessionFactory sessionFactory;
#PersistenceContext
private EntityManager entityManager;
public final void setClazz(Class<T> clazzToSet) {
this.clazz = clazzToSet;
}
public T findOne(long id) {
logger.info("Getting entity " + clazz.getName() + "\n id: " + id);
return (T) getCurrentSession().get(clazz, id);
}
public List<T> findAll() {
logger.info("Find All entities " + clazz.getName());
return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
public void create(T entity) {
logger.info("Creating entity" + clazz.getName());
getCurrentSession().beginTransaction();
getCurrentSession().persist(entity);
getCurrentSession().getTransaction().commit();
// entityManager.persist(entity);
// entityManager.detach(entity);
// entityManager.getTransaction().commit();
}
public void update(T entity) {
logger.info("Merging entity" + clazz.getName());
getCurrentSession().beginTransaction();
getCurrentSession().merge(entity);
getCurrentSession().getTransaction().commit();
}
public void delete(T entity) {
logger.info("Deleting entity" + clazz.getName());
getCurrentSession().beginTransaction();
getCurrentSession().delete(entity);
getCurrentSession().getTransaction().commit();
}
public void deleteById(long entityId) {
logger.info("Deleting entity " + clazz.getName() + "\n id: " + entityId);
T entity = findOne(entityId);
getCurrentSession().beginTransaction();
delete(entity);
getCurrentSession().getTransaction().commit();
}
protected final Session getCurrentSession() {
// if (entityManager != null ) {
// return entityManager.getEntityManagerFactory().unwrap(SessionFactory.class).getCurrentSession();
// } else {
// logger.error("Failed to obtain session factory");
// throw new NullPointerException(); // FIXME: 1/28/2019
// }
return sessionFactory.getCurrentSession();
}
}
PS:
I'm not quite sure, but this might be the bug:
https://hibernate.atlassian.net/browse/HHH-11424?jql=Participants%20%3D%20bvarner
In this case, any recommendations?
Okay, with some help i was able to figure it out.
What helped:
1) In DataSource bean replaced SimpleDataSource with DataSourceBuilder.build();
2) Added #Transactional annotation for all methods in Dao class.

Cannot Autowire DataSource in Spring Boot Project

I am trying to build a simple Spring Boot CRUD application that also has login and signup options with spring boot security. I'm already working with a MySQL database and its working fine to persist the data for my application.
The problem is that, in trying to create my jdbcAuthentication, in my securityConfig class, it says that I cannot autowire Datasource, and that there are no beans of 'DataSource' type found (again, I have used my MySQL database successfully for this project, for a while now). It also automatically imports the javax.sql.DataSource import when I type it in, so it does recognize it.
I tried to search through similar questions, but just could not get it to work.
Here is my code:
Test2Application.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Test2Application {
public static void main(String[] args) {
SpringApplication.run(Test2Application.class, args);
}
}
SecurityConfig.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.sql.DataSource;
#EnableWebSecurity
#RequestMapping("cheese")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select email as principal, password as credentials, true from user where email=?");
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests()
.antMatchers(
"/cheese/index",
"/cheese/",
"/**/webjars/**",
"/cheese/signup",
"/cheese/login",
"/cheese/account",
"/cheese/add",
"/cheese/remove",
"/cheese/success").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/cheese/login")
.permitAll();
http.csrf().disable();
}
}
UserController.java
package com.example.demo.controllers;
import com.example.demo.models.Customer;
import com.example.demo.models.data.CustomerDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("cheese")
public class UserController {
#Autowired
private CustomerDao customerDao;
#RequestMapping(value = "login")
public String loginPage(Model model) {
model.addAttribute("title", "Login Page");
return "cheese/login";
}
#RequestMapping(value = "account")
public String accountInfo(Model model) {
model.addAttribute("title", "Account Page");
return "cheese/account";
}
#GetMapping("signup")
public String displaySignUpForm(Model model) {
model.addAttribute("title", "Sign Up");
model.addAttribute("customer", new Customer());
return "cheese/signup";
}
#PostMapping(value = "signup")
public String processSignUp(Model model, #ModelAttribute Customer customer, Errors errors) {
if (errors.hasErrors()) {
return "cheese/signup";
}
customerDao.save(customer);
return "cheese/success";
}
}
Application.Properties
spring.datasource.url=jdbc:mysql://localhost:8889/******?useSSL=false
spring.datasource.username=****
spring.datasource.password=******
spring.jpa.database=MYSQL
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>test2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>test2</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>
</project>
The Spring Security configuration should applied with the Configuration annotation.
Remove #RequestMapping("cheese") from SecurityConfig
The correct configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
Had the same issue, I created a separate config class where I defined a DataSource bean
#Bean
DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("database_url");
dataSource.setUsername("username");
dataSource.setPassword("password");
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
return dataSource;
}
and in the main config file (in your case Security config) left DataSource #Autowired.
#Autowired
DataSource dataSource;
#Autowired
protected void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
}
And it worked. In case it is useful, I used these Gradle dependencies -
implementation 'mysql:mysql-connector-java:8.0.18'
implementation group: 'org.springframework', name: 'spring-jdbc', version: '5.3.21'
Apart from the #Configuration annotation, add #EnableAutoConfiguration which would attempt and configure code.
#Configuration
#EnableAutoConfiguration
public class SecurityConfig extends WebSecurityConfigurerAdapter
Also, rebuild your sources afterwards.

Spring Batch Custom ItemReader IllegalArgumentException

I'm trying to implement a Spring Batch custom ItemReader and am having issues with an IllegalArgumentException.
The exception trace is here;
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reader' defined in class path resource [com/chrisbeech/batch/JobConfig.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1583) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) ~[spring-context-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541) ~[spring-context-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:371) ~[spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~ [spring-boot-1.4.1.RELEASE.jar:1.4.1.RELEASE]
at com.chrisbeech.batch.Application.main(Application.java:37) [classes/:na]
Caused by: java.lang.IllegalArgumentException: [Assertion failed] - this argument is required; it must not be null
at org.springframework.util.Assert.notNull(Assert.java:115) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.util.Assert.notNull(Assert.java:126) ~[spring-core-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.batch.item.adapter.AbstractMethodInvokingDelegator.afterPropertiesSet(AbstractMethodInvokingDelegator.java:135) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1642) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
... 13 common frames omitted
I have also attached my custom ItemReader...
package com.chrisbeech.batch.step;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.springframework.batch.item.adapter.ItemReaderAdapter;
import org.springframework.stereotype.Component;
import com.chrisbeech.batch.mongodb.collections.Client;
#Component
public class Reader extends ItemReaderAdapter<Client> {
private static final Logger log = LoggerFactory.getLogger(Reader.class);
private int nextClientIndex;
private List<Client> clients;
public Reader(){
populate();
}
// populate in memory array
private void populate(){
clients = new ArrayList<Client>();
Client beryl = new Client();
beryl.setFirstName("Beryl");
beryl.setLastName("A");
clients.add(beryl);
Client frank = new Client();
beryl.setFirstName("Frank");
beryl.setLastName("A");
clients.add(frank);
Client paul = new Client();
beryl.setFirstName("Paul");
beryl.setLastName("A");
clients.add(paul);
Client judith = new Client();
beryl.setFirstName("Judith");
beryl.setLastName("A");
clients.add(judith);
Client lizzy = new Client();
beryl.setFirstName("Lizzy");
beryl.setLastName("A");
clients.add(lizzy);
nextClientIndex = 0;
}
// read the people
public Client read() throws Exception, UnexpectedInputException, ParseException {
Client nextClient = null;
if(nextClientIndex < clients.size()){
nextClient = clients.get(nextClientIndex);
nextClientIndex++;
log.info("### Reading in " + nextClientIndex + " : " + nextClient);
}
return nextClient;
}
}
...Batch job config...
package com.chrisbeech.batch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.data.MongoItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.chrisbeech.batch.config.InfrastructureConfiguration;
import com.chrisbeech.batch.mongodb.collections.Client;
import com.chrisbeech.batch.step.ClientProcessor;
import com.chrisbeech.batch.step.Reader;
#Configuration
#EnableBatchProcessing
public class JobConfig {
private static final Logger log = LoggerFactory.getLogger(JobConfig.class);
#Autowired
private JobBuilderFactory jobBuilderFactory;
#Autowired
private StepBuilderFactory stepBuilderFactory;
#Autowired
public JobLauncher jobLauncher;
#Autowired
public JobRegistry jobRegistry;
#Autowired
public InfrastructureConfiguration infrastructureConfiguration;
// define the reader (which is custom)
#Bean
public ItemReader<Client> reader(){
return new Reader();
}
// define the processor
#Bean
public ItemProcessor<Client, Client> processor(){
return new ClientProcessor();
}
// define the writer
#Bean
public ItemWriter<Client> writer() {
MongoItemWriter<Client> writer = new MongoItemWriter<Client>();
try {
writer.setTemplate(infrastructureConfiguration.mongoTemplate());
} catch (Exception e) {
log.error(e.toString());
}
writer.setCollection("Clients");
return writer;
}
// create the step
#Bean
public Step step(){
return stepBuilderFactory.get("step")
.<Client, Client> chunk(1)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
// create the job
#Bean
public Job springBatchJob(){
return jobBuilderFactory.get("spring-batch-test")
.incrementer(new RunIdIncrementer())
.flow(step())
.end()
.build();
}
}
...and POM...
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chrisbeech.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<version>0.1.0</version>
<properties>
<java.version>1.8</java.version>
<oracle.driver.version>11.2.0</oracle.driver.version>
<junit.version>3.8.1</junit.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
<relativePath></relativePath>
</parent>
<dependencies>
<!-- spring boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- ORACLE database driver -->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>${oracle.driver.version}</version>
</dependency>
<!-- JUnit framework -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Any help would be greatly appreciated!
Bic
I solved this by cleaning maven repository This can be caused by a dirty classpath with different versions of Spring libraries all over the place. Cleanup it and align it to the one and same Spring version with the correct versioned dependencies

Categories