Spring ignores Beans, Qualifier and Transactional - spring

Hi trying to set simple rest controller with several databases. Problem is Spring ignores both Transactional from my service, it always go to #Primary. Also Spring ignores the Qualifier inside DataSourceTransactionaManager and seems to go to default #Primary. Anyone help much appreciated.
edit: added import statements.. hikari imports i due too i changed the code little bit and instead use hikari database and also tried entitymanager..but neither of those things helped..
package com.example.miniredditbackend.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
public class UserService implements UserSer{
private UserRepo userRep;
#Autowired
public UserService(UserRepo userRep){
this.userRep = userRep;
}
#Override
#Transactional("tm1")
public User createUser(User user){
return userRep.save(user);
}
}
package com.example.miniredditbackend.user;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(
entityManagerFactoryRef = "entityuser",
transactionManagerRef = "tm2",
basePackages = {
"com.example.miniredditbackend.user"
}
)
public class userDatabase {
#Bean(name = "userdb")
#ConfigurationProperties(prefix = "userdatabase.datasource")
public DataSource userdb(){
return DataSourceBuilder.create().build();
}
#Bean(name = "entityuser")
public LocalContainerEntityManagerFactoryBean entityU(EntityManagerFactoryBuilder builder,
#Qualifier ("userdb") DataSource datasource){
return builder.dataSource(datasource).packages("com.example.miniredditbackend.user").persistenceUnit("usersx").build();
}
#Bean(name = "tm2")
public PlatformTransactionManager tm2(#Qualifier ("entityuser") EntityManagerFactory entityuser){
return new JpaTransactionManager(entityuser);
}
}

Related

Spring can't find repository bean

I'm using spring boot with spring data jdbc and I got trouble with run my app
I have StudentService class:
package ru.turnip.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import ru.turnip.model.Student;
import ru.turnip.repository.StudentRepository;
import ru.turnip.utils.student.BusyStudents;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#Service
public class StudentService {
private final BusyStudents busyStudents;
private final StudentRepository studentRepository;
public StudentService(BusyStudents busyStudents, StudentRepository studentRepository) {
this.busyStudents = busyStudents;
this.studentRepository = studentRepository;
}
...
}
And StudentRepository interface:
package ru.turnip.repository;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import ru.turnip.model.Student;
import java.util.UUID;
#Repository
public interface StudentRepository extends CrudRepository<Student, UUID> { }
So, when I try to run app, I get an eror, and I can't figure out where the problem is.
That my config class:
package ru.turnip;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.relational.core.mapping.event.BeforeSaveEvent;
import org.springframework.scheduling.annotation.EnableScheduling;
import ru.turnip.model.Student;
import java.time.Clock;
import java.util.UUID;
#ComponentScan
#Configuration
#EnableScheduling
public class ApplicationConfig {
#Bean
public Clock clock() {
return Clock.systemDefaultZone();
}
#Bean
public ApplicationListener<BeforeSaveEvent> idGenerator() {
return event -> {
var entity = event.getEntity();
if (entity instanceof Student) {
((Student) entity).setId(UUID.randomUUID());
}
};
}
}
And project structure:
I tried to explicitly set package to be scanned, and also moved the repository to the package with the config. Also I tried to annotate with #Autowired field and constructor in StudentService

Missing bean in controller even after adding ComponentScan annotation

I am trying to run a spring boot application which gets a list of names of people from the database. I am getting the below error :
Description:
Field peopleserviceinterface in com.sample.lombpackdemo.controller.FriendController required a bean of type 'com.sample.lombpackdemo.service.FriendsServiceInterface' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.sample.lombpackdemo.service.FriendsServiceInterface' in your configuration.
package com.sample.lombpackdemo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sample.lombpackdemo.entity.Friends;
import com.sample.lombpackdemo.rowmapper.FriendsRowMapper;
import com.sample.lombpackdemo.service.FriendsServiceInterface;
#CrossOrigin(origins = { "http://localhost:3000"})//to allow access from other servers
#RestController
#RequestMapping("/code")
#ComponentScan(basePackages="com.sample.lombpackdemo.service")
public class FriendController {
#Autowired
private FriendsServiceInterface peopleserviceinterface;//autowire the service
#GetMapping("/all")
public ResponseEntity<List<Friends>> getAllPeople(){
List <Friends> listOfAllPpl = peopleserviceinterface.getAllFriends();
System.out.println("Getting all friends"+listOfAllPpl.toString());
return new ResponseEntity<List<Friends>>(listOfAllPpl,HttpStatus.OK);
}
}
The FriendServiceInterface class is as below:
package com.sample.lombpackdemo.service;
import java.util.List;
import org.springframework.stereotype.Component;
import com.sample.lombpackdemo.entity.Friends;
#Component
public interface FriendsServiceInterface {
public List<Friends> getAllFriends();
}
The FriendService class:
package com.sample.lombpackdemo.service;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.sample.lombpackdemo.entity.Friends;
import com.sample.lombpackdemo.repos.FriendsRepo;
import com.sample.lombpackdemo.rowmapper.FriendsRowMapper;
#Service
#Profile("devel")//added to disable CORS only on development time
#Configuration
#Component
public class FriendService implements FriendsServiceInterface {
#Autowired
private FriendsServiceInterface peopleserviceinterface;
#Autowired
private FriendsRepo pplRepo;//should always autowire repository
#Autowired
private JdbcTemplate jdbc;
private static long idCounter = 0;
//FriendsRowMapper fRowMap=new FriendsRowMapper();
#Override
public List<Friends> getAllFriends() {
String sql="select f_name from list_friends";
return jdbc.query(sql, new FriendsRowMapper() );
/*
List<Friends> ppList= (List<Friends>) fRowMap.findAll();
try {
System.out.println("Repository value"+pplRepo.findAll());
System.out.println("Inside findAll of service class" +ppList.toString() );
}
catch(Exception e)
{
}
return ppList;
//
*/}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
//registry.addMapping("/save-javaconfig").allowedOrigins("http://localhost:3000");
}
};
}
Please let me know what else needs to be changed. I have tried adding Component annotation to FriendService class and ComponentScan annotation to the controller class.
Edited to add JdbcConfig class
package com.sample.lombpackdemo.repos;
//import java.util.logging.Logger;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
#Configuration
#ComponentScan(basePackages = "com.sample.lombpackdemo")
public class SpringJdbcConfig {
protected final Logger log = LoggerFactory.getLogger(getClass());
#Bean
public DataSource mysqlDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/person_example");
dataSource.setUsername("root");
dataSource.setPassword("subfio");
return dataSource;
}
#Bean(name = "dbProductService")
#ConfigurationProperties (prefix = "spring.datasource")
#Primary public DataSource createProductServiceDataSource()
{ System.out.println("Inside db cofig ");
return DataSourceBuilder.create().build(); }
}
}

when using miltiple datasource hibernate envers are not working

When I use only one datasource, hibernate envers are working well(not using any config.java. just set application.properties). But Using multiple datasource(with config.java, same DB, different user), envers are not working and logged oracle error message ORA-00942.
audited table is in DB#1. How can I do?
spring boot 1.5.6
application.properties
#################################
# DataBase #1 (Default)
#################################
spring.datasource.initialize=true
spring.datasource.url=jdbc:oracle:thin:#localhost:1521:orcl
spring.datasource.username=id_1
spring.datasource.password=pw_1
spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
#################################
# DataBase #2(Additional)
#################################
db2.datasource.initialize=true
db2.datasource.url=jdbc:oracle:thin:#localhost:1521:orcl
db2.datasource.username=db_2
db2.datasource.password=pw_2
db2.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
config.java
package com.dev;
import javax.sql.DataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
#Configuration
public class DataBaseConfig {
#Bean
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource defaultDataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "defaultEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(defaultDataSource())
.packages("com.dev.core.**", "com.dev.ext.**")
.build();
}
#Primary
#Bean(name = "defaultTransactionManager")
PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactory(builder).getObject());
}
#Configuration
#EnableJpaRepositories(basePackages= {"com.dev.core.**", "com.dev.ext.**"},
entityManagerFactoryRef = "defaultEntityManagerFactory", transactionManagerRef = "defaultTransactionManager")
static class DefaultJpaRepositoriesConfig {
}
/*Additional Data Source - NCRM*/
#Bean
#ConfigurationProperties(prefix = "db2.datasource")
public DataSource ncrmDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "ncrmEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean ncrmEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder.dataSource(ncrmDataSource())
.packages("com.dev.ext.ncrm.*.domain")
.build();
}
#Bean(name = "ncrmTtransactionManager")
PlatformTransactionManager ncrmTransactionManagerMain(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(ncrmEntityManagerFactory(builder).getObject());
}
#Configuration
#EnableJpaRepositories(
basePackages="com.dev.ext.ncrm.*.repo",
entityManagerFactoryRef = "ncrmEntityManagerFactory",
transactionManagerRef = "ncrmTtransactionManager")
static class ncrmJpaRepositoriesConfig {
}
}
defaultDO.java
package com.dev.core.domain;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.Table;
import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.envers.AuditTable;
import org.hibernate.envers.Audited;
import lombok.Data;
#Data
#Entity
#Table(name = "tb_category")
#Audited
#AuditTable("tx_category_audit")
public class CategoryDO {
//codes
}
First add hibernate dialect at application.properties file like below for both data source:
spring.datasource.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
spring.secondDatasource.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
Then Please rewrite the configuration like below
package com.multisource.poc.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
#Configuration
public class ApplicationConfiguration {
#Value("${spring.datasource.hibernate.dialect}")
private String oracleDialect;
#Value("${spring.secondDatasource.hibernate.dialect}")
private String postgresDialect;
#Primary
#Bean(name = "oracleDB")
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource oracleDataSource() {
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "oracleEM")
public LocalContainerEntityManagerFactoryBean oracleEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", oracleDialect);
LocalContainerEntityManagerFactoryBean emf = builder
.dataSource(oracleDataSource())
.packages("entitypackageOne")
.persistenceUnit("oraclePU")
.build();
emf.setJpaProperties(properties);
return emf;
}
#Bean(name = "postgresDB")
#ConfigurationProperties(prefix = "spring.secondDatasource")
public DataSource postgresDataSource() {
return DataSourceBuilder.create().build();
}
#Bean(name = "postgresEM")
public LocalContainerEntityManagerFactoryBean postgresEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", postgresDialect);
LocalContainerEntityManagerFactoryBean emf = builder
.dataSource(postgresDataSource())
.packages("entitypackageTwo")
.persistenceUnit("postgresPU")
.build();
emf.setJpaProperties(properties);
return emf;
}
}
Now you have two different EntityManager to use. The sample would be like
#Repository
public class OracleDao implements InterOracle {
private EntityManager entityManager;
#Autowired
public OracleDao(#Qualifier("oracleEM") EntityManager entityManager) {
this.entityManager = entityManager;
}
}
#Repository
public class PostgresDao implements InterPostGres{
private static final Logger LOG
= LoggerFactory.getLogger(PostgresDao.class);
private EntityManager entityManager;
#Autowired
public PostgresDao(#Qualifier("postgresEM") EntityManager entityManager) {
this.entityManager = entityManager;
}
}
This is how my application is working using two different datasource.
Does user db_2 / pw_2 have the required permission to access the DB?

Spring boot with spring batch and jpa -configuration

I have simple batch application, reading csv to postgres database.
I have uploaded the code in this below repo in bitbucket
https://github.com/soasathish/spring-batch-with-jpa.git
I have problems in configuring the writing to database using spring data JPA.
I am getting manage bean not found .issue.
This same jpa spring data configuration works in different project when i tried to integrate with spring batch it fails with manage bean not found.
The batch config has spring job
There is only one step
1) reader -read from csv files.
processor applies some rules on the files .. Drools
please run schema-postgresql.sql to setup database
WRITER USES THE SPRING DATA JPA TO WRITE TO DB
could one help
I have uploaded the code in this below repo in bitbucket
https://github.com/soasathish/spring-batch-with-jpa.git
i know its a minor issue , but any direction or help will be grateful
code for creating repo
=======================
package uk.gov.iebr.batch.config;
import static uk.gov.iebr.batch.config.AppProperties.DRIVER_CLASS_NAME;
import static uk.gov.iebr.batch.config.AppProperties.IEBR_DB_PASSWORD_KEY;
import static uk.gov.iebr.batch.config.AppProperties.IEBR_DB_URL_KEY;
import static uk.gov.iebr.batch.config.AppProperties.IEBR_DB_USER_KEY;
import java.util.Properties;
import javax.sql.DataSource;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#PropertySource({"classpath:application.properties"})
#EnableJpaRepositories({"uk.gov.iebr.batch.repository"})
#EnableTransactionManagement
#ComponentScan(basePackages="uk.gov.iebr.batch.repository")
public class DataSourceConfiguration {
#Autowired
Environment env;
#Bean(name = "allsparkEntityMF")
public LocalContainerEntityManagerFactoryBean allsparkEntityMF() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(allsparkDS());
em.setPersistenceUnitName("allsparkEntityMF");
em.setPackagesToScan(new String[] { "uk.gov.iebr.batch"});
em.setPackagesToScan(new String[] { "uk.gov.iebr.batch.repository"});
em.setPersistenceProvider(new HibernatePersistenceProvider());
HibernateJpaVendorAdapter a = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(a);
Properties p = hibernateSpecificProperties();
p.setProperty("hibernate.ejb.entitymanager_factory_name", "allsparkEntityMF");
em.setJpaProperties(p);
return em;
}
#Bean(name = "allsparkDS")
public DataSource allsparkDS() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty(DRIVER_CLASS_NAME));
dataSource.setUrl(env.getProperty(IEBR_DB_URL_KEY));
dataSource.setUsername(env.getProperty(IEBR_DB_USER_KEY));
dataSource.setPassword(env.getProperty(IEBR_DB_PASSWORD_KEY));
return dataSource;
}
#Bean
public Properties hibernateSpecificProperties(){
final Properties p = new Properties();
p.setProperty("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto"));
p.setProperty("hibernate.dialect", env.getProperty("spring.jpa.hibernate.dialect"));
p.setProperty("hibernate.show-sql", env.getProperty("spring.jpa.show-sql"));
p.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("spring.jpa.hibernate.cache.use_second_level_cache"));
p.setProperty("hibernate.cache.use_query_cache", env.getProperty("spring.jpa.hibernate.cache.use_query_cache"));
return p;
}
#Bean(name = "defaultTm")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(allsparkEntityMF().getObject());
return txManager;
}
}
Batch config file:
package uk.gov.iebr.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.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.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
import uk.gov.iebr.batch.config.AllSparkDataSourceConfiguration;
import uk.gov.iebr.batch.config.DataSourceConfiguration;
import uk.gov.iebr.batch.dao.PersonDao;
import uk.gov.iebr.batch.model.Person;
import uk.gov.iebr.batch.step.Listener;
import uk.gov.iebr.batch.step.Processor;
import uk.gov.iebr.batch.step.Reader;
import uk.gov.iebr.batch.step.Writer;
#Configuration
#EnableBatchProcessing
//spring boot configuration
#EnableAutoConfiguration
//file that contains the properties
#PropertySource("classpath:application.properties")
#Import({DataSourceConfiguration.class, AllSparkDataSourceConfiguration.class})
public class BatchConfig {
private static final Logger log = LoggerFactory.getLogger(BatchConfig.class);
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
public PersonDao PersonDao;
#Autowired
public DataSourceConfiguration dataSourceConfiguration;
#Bean
public Job job() {
long startTime = System.currentTimeMillis();
log.info("START OF BATCH ========================================================================" +startTime);
return jobBuilderFactory.get("job").incrementer(new RunIdIncrementer())
//.listener(new Listener(PersonDao))
.flow(step1()).end().build();
}
#Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Person, Person>chunk(10)
.reader(Reader.reader("tram-data.csv"))
.processor(new Processor()).writer(new Writer(PersonDao)).build();
}
}
Writer calls this PersonDaoImpl:
public class PersonDaoImpl implements PersonDao {
#Autowired
DataSourceConfiguration dataSource;
#Autowired
PersonRepository personrepo;
#Override
public void insert(List<? extends Person> Persons) {
personrepo.save(Persons);
}
}
Based on the code you provided and the stack trace in your comment.
It's complaining that it can't find a #Bean named entityManagerFactory.
The reason this is happening is because you are using #EnableJpaRepositories and the entityManagerFactoryRef property defaults to entityManagerFactory. This property defines the name of the #Bean for the EntityManagerFactory.
I think your application configuration is preventing the normal auto-configuration from spring-boot from being processed.
I would recommend removing the IEBRFileProcessApplication class and following this example for configuring your spring-boot application (you could use ServletInitializer if you want).
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
I also can't really see a need for DataSourceConfiguration and AllSparkDataSourceConfiguration, so I would recommend removing them. If you really need to specify your own DataSource, let me know and I can provide an additional example.
Between the #SpringBootApplication and #EnableBatchProcessing annotations, everything that is necessary will be bootstrapped for you.
All you need on BatchConfig is #Configuration and #EnableBatchProcessing.
If you make these changes to simplify your code base, then your problems should disappear.
UPDATE:
I created a pull request located here https://github.com/soasathish/spring-batch-with-jpa/pull/1
Please take a look at the javadoc here for an explanation on how #EnableBatchProcessing works. http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html

Change #PersistenceContext to #PersistenceUnit while running Junit tests

I am using #PersistenceContext as of now and working fine. However the same application need to be used in Junit context as well. I want #PersistenceContext to be changed to #PersistenceUnit in DaoImpl classes when Junit test cases are running. How to do that?
Using the following versions in my application
<springframework.version>4.2.5.RELEASE</springframework.version>
<hibernate.version>5.1.0.Final</hibernate.version>
<hibernate.validator.version>5.2.4.Final</hibernate.validator.version>
<mysql.connector.version>6.0.3</mysql.connector.version>
<junit.version>4.12</junit.version>
Hibernate Configuration is:
package com.rsa.springwebclasses.configuration.db;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import ch.qos.logback.classic.Logger;
#Configuration
#EnableTransactionManagement
#PropertySources({
#PropertySource("classpath:hibernate/hibernate.properties"),
#PropertySource("classpath:mysql/mysql.properties")
})
public class HibernateConfiguration {
Logger logger = (Logger) LoggerFactory.getLogger(HibernateConfiguration.class);
#Autowired
Environment env;
private Properties getHibernateProperties() {
Properties hprop = new Properties();
hprop.put("hibernate.dialect", env.getRequiredProperty("mysql.hibernate.dialect"));
hprop.put("hibernate.show_sql", env.getRequiredProperty("hibernate.show_sql"));
hprop.put("hibernate.format_sql", env.getRequiredProperty("hibernate.format_sql"));
logger.info("Hibernate properties: " + hprop.toString());
return hprop;
}
private Properties getMysqlProperties() {
Properties mySqlProp = new Properties();
mySqlProp.put("jdbc.driverClassName", env.getRequiredProperty("mysql.jdbc.driverClassName"));
mySqlProp.put("jdbc.url", env.getRequiredProperty("test.mysql.jdbc.url"));
mySqlProp.put("jdbc.username", env.getRequiredProperty("test.mysql.jdbc.username"));
mySqlProp.put("jdbc.password", env.getRequiredProperty("test.mysql.jdbc.password"));
logger.info("MySQL properties: " + mySqlProp.toString());
return mySqlProp;
}
#Bean
public DataSource getDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
Properties dbProp = this.getMysqlProperties();
dataSource.setDriverClassName(dbProp.getProperty("jdbc.driverClassName"));
dataSource.setUrl(dbProp.getProperty("jdbc.url"));
dataSource.setUsername(dbProp.getProperty("jdbc.username"));
dataSource.setPassword(dbProp.getProperty("jdbc.password"));
logger.info("DataSource object is created.");
return dataSource;
}
#Bean
public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) {
JpaTransactionManager jtm = new JpaTransactionManager();
jtm.setEntityManagerFactory(emf);
logger.info("PlatformTransactionManager is initialized with JpaTransactionManager");
return jtm;
}
#Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean emfb = new LocalContainerEntityManagerFactoryBean();
emfb.setDataSource(getDataSource());
emfb.setPackagesToScan(new String[] {"com.rsa.springwebclasses.model"});
JpaVendorAdapter vendor = new HibernateJpaVendorAdapter();
emfb.setJpaVendorAdapter(vendor);
emfb.setJpaProperties(getHibernateProperties());
logger.info("LocalContainerEntityManagerFactoryBean created: PersistentUnit Name: " + emfb.getJpaVendorAdapter().toString());
return emfb;
}
}
My DaoImpl class is:
package com.rsa.springwebclasses.dao.impl;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import com.rsa.springwebclasses.dao.UserDao;
import com.rsa.springwebclasses.model.User;
import ch.qos.logback.classic.Logger;
#Repository("userDao")
public class UserDaoImpl implements UserDao {
Logger logger = (Logger) LoggerFactory.getLogger(UserDaoImpl.class);
**#PersistenceContext**
EntityManager em;
public List<User> findAllUsers() {
logger.debug("In findAllUsers method.");
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = cb.createQuery(User.class);
Root<User> user = criteria.from(User.class);
criteria.select(user).orderBy(cb.asc(user.get("username")));
logger.debug("Exit findAllUsers method");
return em.createQuery(criteria).getResultList();
}
}
While injecting EntityManager, #PersistenceContext is hard coded. However the same DaoImpl class need to be used for Junit test cases as well. With Junit I prefer to use transaction type as RESOUCE_LOCAL which is possible only with #PersistenceUnit. Is it possible to have a different annotation in DaoImpl class and assign #PersistenceContext or #PersistenceUnit while application is loading or already running?

Resources