Java Bean not found in configuration with multiple module - java

I having a configuration problem that cause the error below. I know there are a tons of similar problem but I read a lot of answer that stackoverflow suggest with my title but I don't find the right answer yet.
Description:
Field collaborateurJpaRepository in com...infrastructure.persistence.user.UserRepositoryImpl required a bean of type 'com...infrastructure.persistence.jurisdiction.CollaborateurJpaRepository' that could not be found.
Action:
Consider defining a bean of type 'com...infrastructure.persistence.jurisdiction.CollaborateurJpaRepository' in your configuration.
Before to give some details of the code, I think it could be nice that I describe you brievly the context.
I work on a client project which has 8 maven modules (DDD methods) because at the end of the year 4 modules will be separate in an other server.
Recently we create a second oracle database so I had to create multiple configuration to refer to the good dataSource.
I think the problem is due to bad datasource configuration that block the bean spring instanciation.
We are using spring boot version 1.5.7.release.
First Infrastructure configuration
#Configuration
#ComponentScan(basePackages = "com...jade")
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "jadeEntityManager", transactionManagerRef = "jadeTransactionManager")
#EntityScan(basePackages = { "com...jade", "org.springframework.data.jpa.convert.threeten" })
#Profile({"ARA_JADE_CONF", "LOCAL_JADE_CONF"})
public class InfrastructureConfig {
private final static int JDBC_FETCH_SIZE = 1000;
#Autowired
private Environment environment;
#Bean
public LocalContainerEntityManagerFactoryBean jadeEntityManager() throws SQLException {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSourceJade());
em.setPackagesToScan(new String[] {"com...jade"});
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
#Primary
public OracleDataSource dataSourceJade() throws SQLException {
OracleDataSource dataSource = new OracleDataSource();
dataSource.setUser(environment.getProperty("db.datasource.jade.username"));
dataSource.setPassword(environment.getProperty("db.datasource.jade.password"));
dataSource.setURL(environment.getProperty("db.datasource.jade.url"));
dataSource.setImplicitCachingEnabled(true);
dataSource.setFastConnectionFailoverEnabled(true);
return dataSource;
}
#Bean(name="jdbcTemplateJade")
public JdbcTemplate jdbcTemplateJade() throws SQLException {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSourceJade());
jdbcTemplate.setResultsMapCaseInsensitive(true);
jdbcTemplate.setFetchSize(JDBC_FETCH_SIZE);
return jdbcTemplate;
}
#Bean
public PlatformTransactionManager transactionManager() throws SQLException{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(jadeEntityManager().getObject());
return transactionManager;
}
#Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
} ...
Seconde Infrastructure configuration
#Configuration
#ComponentScan(basePackages = "com.bnpparibas.sit.risk.art")
#EnableTransactionManagement
#EnableJpaRepositories(entityManagerFactoryRef = "artEntityManager", transactionManagerRef = "artTransactionManager")
#EntityScan(basePackages = { "com...art", "org.springframework.data.jpa.convert.threeten" })
#Profile({"LOCAL_ART_CONF,'ARA_ART_CONF"})
public class ArtInfrastructureConfig {
private final static int JDBC_FETCH_SIZE = 1000;
#Autowired
private Environment environment;
#Bean
#Primary
public LocalContainerEntityManagerFactoryBean artEntityManager() throws SQLException {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSourceArt());
em.setPackagesToScan(new String[] {"com...art.infrastructure.persistence"});
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
#Bean
#Primary
public OracleDataSource dataSourceArt() throws SQLException {
OracleDataSource dataSource = new OracleDataSource();
dataSource.setUser(environment.getProperty("db.datasource.art.username"));
dataSource.setPassword(environment.getProperty("db.datasource.art.password"));
dataSource.setURL(environment.getProperty("db.datasource.art.url"));
dataSource.setImplicitCachingEnabled(true);
dataSource.setFastConnectionFailoverEnabled(true);
return dataSource;
}
#Bean
#Primary
public PlatformTransactionManager artTransactionManager()throws SQLException{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(artEntityManager().getObject());
return transactionManager;
}
#Bean
#Primary
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}...
Interface link to Entity.
#DDD.Repository
#Repository
public interface CollaborateurJpaRepository extends CrudRepository<Collaborateur,String>{
#Query("FROM ART_PARAM.ART_USER u WHERE u.refogUID = :uid")
Collaborateur findCollaborateurById(#Param("uid") String uid);
}
Class that contain the autowired interface to retrieve some data of the second database.
#DDD.RepositoryImpl
#Repository
#Primary
public class UserRepositoryImpl implements UserRepository {
#Autowired
private CollaborateurJpaRepository collaborateurJpaRepository;
#Override
//#Cacheable(cacheNames = CacheConfig.CACHE_JURIDICTION, key = CacheConfig.CACHE_KEY_UTILISATEUR_ID)
#Transactional("entityManagerFactoryArt")
public User retrieveUser(UserId userId) {
if(userId.getValue() == null) {
return null;
} else {
Collaborateur collaborateur = collaborateurJpaRepository.findOne(userId.getValue());
return new User(collaborateur.getRefogUID(),collaborateur.getRefogFirstName(),collaborateur.getRefogLastName(),collaborateur.getProfile(),collaborateur.isActiveUser(),collaborateur.isBankingSecrecy());
}
}

Related

Configured two data source in spring data JPA but second data source still considering first DB URL

In this official example of configuring 2 data sources, they have used embedded DB.
So, with the help of Spring boot's How to documentations, Configure Two DataSources and Using Multiple EntityManagerFactories, I customized that to use MySQL DB.
You can find the complete code under this Github repository. Don't forget to checkout the "two_data_sources_in_separate_files" branch.
But with this modification, "secondDBTransactionManager" is not pointing second_db. Instead, it is inserting data into first_db.
FirstDataSource.java
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "firstDBEntityManagerFactory", transactionManagerRef = "firstDBTransactionManager")
public class FirstDataSource {
#Bean
PlatformTransactionManager firstDBTransactionManager(DataSourceProperties firstDataSourceProperties) {
return new JpaTransactionManager(firstDBEntityManagerFactory(firstDataSourceProperties).getObject());
}
#Bean
#Primary
LocalContainerEntityManagerFactoryBean firstDBEntityManagerFactory(DataSourceProperties firstDataSourceProperties) {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(firstDS(firstDataSourceProperties));
factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
factoryBean.setPackagesToScan(FirstDataSource.class.getPackage().getName());
return factoryBean;
}
#Bean
#Primary
#ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDS(DataSourceProperties firstDataSourceProperties) {
return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
}
SecondDataSource.java
#Configuration
#EnableJpaRepositories(entityManagerFactoryRef = "secondDBEntityManagerFactory", transactionManagerRef = "secondDBTransactionManager")
public class SecondDataSource {
#Bean
PlatformTransactionManager secondDBTransactionManager(DataSourceProperties secondDataSourceProperties) {
return new JpaTransactionManager(secondDBEntityManagerFactory(secondDataSourceProperties).getObject());
}
#Bean
#ConfigurationProperties("app.datasource.second")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("app.datasource.second.configuration")
public HikariDataSource secondDS(
#Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
return secondDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}
#Bean
public LocalContainerEntityManagerFactoryBean secondDBEntityManagerFactory(DataSourceProperties secondDataSourceProperties) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(secondDS(secondDataSourceProperties));
factoryBean.setJpaVendorAdapter(vendorAdapter);
factoryBean.setPackagesToScan(SecondDataSource.class.getPackage().getName());
return factoryBean;
}
}
FetchData.java
#Controller // This means that this class is a Controller
#RequestMapping(path = "/demo") // This means URL's start with /demo (after Application path)
public class FetchData {
#Autowired
private TableARepository tableARepository;
#Autowired
private TableCRepository tableCRepository;
#GetMapping(path = "/addDataToFirstDB")
public #ResponseBody void addDataToFirstDB() {
// This returns a JSON or XML with the users
Table_A tableA = new Table_A();
tableA.setTable_a_col_1("test1");
tableA.setTable_a_col_2("test2");
tableA.setTable_a_col_3("test3");
tableA.setTable_a_col_4("test4");
System.out.println("Inserting data into first DB.");
tableARepository.save(tableA);
}
#GetMapping(path = "/addDataToSecondDB")
#Transactional("secondDBTransactionManager")
public #ResponseBody void addDataToSecondDB() {
// This returns a JSON or XML with the users
Table_C tableC = new Table_C();
tableC.setTable_c_col_1("test1");
tableC.setTable_c_col_2("test2");
tableC.setTable_c_col_3("test3");
tableC.setTable_c_col_4("test4");
System.out.println("Inserting data into second DB.");
tableCRepository.save(tableC);
}
}
Observe that, I've used #Transactional("secondDBTransactionManager") for second REST API, "addDataToSecondDB".
It is easy to resolve issue if any Exception is thrown. There is no Exception here but the behavior is not as expected.

How can I read object from one datasource and write to another with spring data?

I have a config class:
#SpringBootConfiguration
#ComponentScan(basePackages = "vap")
public class AppConfig {
Logger logger = LoggerFactory.getLogger(this.getClass());
public AppConfig() {
}
#Bean
public ServerRuntime runtime() {
ServerRuntime runtime = ServerRuntime.builder().addConfig("cayenne-project.xml").build();
return runtime;
}
#Bean
public ObjectContext getContext(#Autowired ServerRuntime serverRuntime) {
return serverRuntime.newContext();
}
#Bean(name = "pgDataSource")
public DataSource getDataSource() {
Properties props = new Properties();
props.setProperty("user", "postgres");
props.setProperty("password", "");
PoolConfiguration configuration = new PoolProperties();
configuration.setDbProperties(props);
configuration.setUrl("jdbc:postgresql://localhost/mikro00");
configuration.setDriverClassName("org.postgresql.Driver");
DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(configuration);
return dataSource;
}
#Bean(name = "hsqldbDataSource")
public DataSource getHSQLDataSource() {
Properties props = new Properties();
props.setProperty("user", "sa");
props.setProperty("password", "");
PoolConfiguration configuration = new PoolProperties();
configuration.setDbProperties(props);
configuration.setUrl("jdbc:h2:file:./outbase");
configuration.setDriverClassName("org.h2.Driver");
DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource(configuration);
return dataSource;
}
}
my PGConfig.java
#Configuration
#EnableTransactionManagement
public class PGConfig {
#Primary
#Bean(name = "entityManagerFactoryPG")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, #Qualifier(value = "pgDataSource") DataSource dataSource) {
LocalContainerEntityManagerFactoryBean vap = builder.dataSource(dataSource)
.packages("vap")
.build();
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
vap.setJpaVendorAdapter(jpaVendorAdapter);
return vap;
}
#Primary
#Bean(name = "transactionManagerPG")
public PlatformTransactionManager transactionManager(
#Qualifier("entityManagerFactory") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
My H2Config.java
#Configuration
#EnableTransactionManagement
public class H2Config {
#Primary
#Bean(name = "dataSource")
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource(){
return DataSourceBuilder.create().build();
}
#Primary
#Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, #Qualifier(value = "hsqldbDataSource") DataSource dataSource){
LocalContainerEntityManagerFactoryBean vap = builder.dataSource(dataSource)
.packages("vap")
.build();
JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
vap.setJpaVendorAdapter(jpaVendorAdapter);
return vap;
}
#Primary
#Bean(name = "transactionManagerH2")
public PlatformTransactionManager transactionManager(
#Qualifier("entityManagerFactory") EntityManagerFactory
entityManagerFactory
) {
return new JpaTransactionManager(entityManagerFactory);
}
}
KlientRepository
#Repository
public interface KlientRepository extends CrudRepository<Klient,Integer> {
}
How can I read Klient from one repository and write to another. I need to read from PG, work with data and save to h2. I can't find how two object of repository with different datasource, or simply create repository object with concrete datasource
You have pretty much everything out there in your code, you only need to do a bit of fine tuning thats all
Create two configuration classes with bean declaration for Datasource, EntityManagerFactory and TransactionManager
Mark one of the two as primary
Create two model classes(one for each database model)
Create two Repository classes in two different package**(very Important)**
In your service class Autowire both Repositories, read from one DB, manipulate and save to other.
Only thing missing in your code is you need to tell Spring which Repository class should use which EntityManager /Datasource(Since you have two). This can be done by Annotation #EnableJpaRepositories(basepackages=...). Use this annotation on each configuration classes, with basePackages indicating your repository classes

Why is my entitymanager in Playframework 2.5 still null?

I want to use Playframework 2.5 together with Spring and JPA. I found the following template https://github.com/jamesward/play-java-spring where it works perfectly, unfortunately it’s not for Playframework 2.5. So I decided to adapt this template and create my own one for Playframework 2.5. However, my entitymanager in my controller Application is still null. What am I doing wrong? My code looks like the following:
AppConfig.java
package config;
#Configuration
#ComponentScan({"daos","services","controllers","models"})
public class AppConfig {
}
DataConfig.java
package config;
#Configuration
#EnableTransactionManagement
public class DataConfig
{
#Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setShowSql(true);
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setPackagesToScan("models");
entityManagerFactory.setJpaVendorAdapter(vendorAdapter);
entityManagerFactory.setDataSource(dataSource());
entityManagerFactory.setJpaPropertyMap(new HashMap<String, String>(){{
put("hibernate.hbm2ddl.auto", "create-drop");
put("hibernate.dialect","org.hibernate.dialect.PostgreSQLDialect");
}});
entityManagerFactory.afterPropertiesSet();
return entityManagerFactory.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager(entityManagerFactory());
return transactionManager;
}
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
return dataSource;
}
}
Global.java
package config;
#Singleton
#Configuration
public class Global
{
private ConfigurableApplicationContext context;
#Inject
public Global(ApplicationLifecycle lifecyle)
{
this.context = new AnnotationConfigApplicationContext(AppConfig.class, DataConfig.class);
lifecyle.addStopHook(()-> {
context.close();
return CompletableFuture.completedFuture(null);
});
}
}
Application.java
package controllers;
#Controller
#Transactional
#Component
public class Application extends play.mvc.Controller
{
#PersistenceContext
private EntityManager em;
#Transactional
public Result index()
{
System.out.println("******************* EM " + this.em +" *************************");
return ok(index.render());
}
}
Thank you for your help!

How to include Spring JPA in the existing Spring Hibernate application

I am working on one enhancement in my application. This application is Spring Hibernate implementation.But the enhancement now I am working is Spring-JPA.
Without disturbing the existing implementation I need to include JPA
Below is my DBconfiguration class.
#Configuration
#EnableJpaRepositories(basePackages = {"packagename","package name" })
#EnableTransactionManagement
public class DataBaseConfiguration {
#Value("${postgres.driver}")
private String postgresDriver;
#Value("${postgres.url}")
private String postgresUrl;
#Value("${postgres.username}")
private String postgresUsername;
#Value("${postgres.password}")
private String postgresPassword;
#Value("${hibernate.dialect}")
private String hibernateDialect;
#Value("${hibernate.dialect.property}")
private String dialectProperty;
#Value("${hibernate.show-sql}")
private String hibernateShowSql;
#Value("${boolean.true}")
private String booleanTrue;
**\\ existing hibernate flow**
#Autowired
#Bean(name = "name")
public SessionFactory getSessionFactory(DataSource dataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(
dataSource);
sessionBuilder.addAnnotatedClasses(entity.class);
sessionBuilder.setProperty(hibernateDialect, dialectProperty);
sessionBuilder.setProperty(postgresDriver, postgresUrl);
sessionBuilder.setProperty(hibernateShowSql, booleanTrue);
return sessionBuilder.buildSessionFactory();
}
**\\ existing hibernate flow**
#Bean(name = "name")
public DataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(postgresDriver);
dataSource.setUrl(postgresUrl);
dataSource.setUsername(postgresUsername);
dataSource.setPassword(postgresPassword);
return dataSource;
}
**\\ existing hibernate flow**
#Autowired
#Bean(name = "manager")
public HibernateTransactionManager getTransactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = null;
transactionManager = new HibernateTransactionManager(sessionFactory);
return transactionManager;
}
**\\included newly for JPA**
#Bean
public org.springframework.orm.jpa.JpaTransactionManager transactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource(getDataSource());
jpaTransactionManager
.setJpaDialect(new org.springframework.orm.jpa.vendor.HibernateJpaDialect());
return jpaTransactionManager;
}
**\\included newly for JPA**
#Bean
public EntityManager entityManger() {
return entityManagerFactory().getObject().createEntityManager();
}
\\included newly for JPA
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(getDataSource());
entityManagerFactory.setPackagesToScan(
"some package",
"some package");
Map<String, Object> jpaProperty = entityManagerFactory
.getJpaPropertyMap();
jpaProperty.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
va.setShowSql(Boolean.valueOf("true"));
entityManagerFactory.setJpaVendorAdapter(va);
return entityManagerFactory;
}
}
When I deployed this application i am getting below exception
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class ------
Caused by: java.lang.NullPointerException
at org.hibernate.hql.internal.antlr.HqlBaseParser.identPrimary(HqlBaseParser.java:4285)
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:980)
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3609)
at org.hibernate.hql.internal.antlr.HqlBaseParser.unaryExpression(HqlBaseParser.java:3387)
at org.hibernate.hql.internal.antlr.HqlBaseParser.multiplyExpression(HqlBaseParser.java:3259)
at org.hibernate.hql.internal.antlr.HqlBaseParser.additiveExpression(HqlBaseParser.java:2964)
at org.hibernate.hql.internal.antlr.HqlBaseParser.concatenation(HqlBaseParser.java:597)
at org.hibernate.hql.internal.antlr.HqlBaseParser.relationalExpression(HqlBaseParser.java:2730)
at org.hibernate.hql.internal.antlr.HqlBaseParser.equalityExpression(HqlBaseParser.java:2591)
at org.hibernate.hql.internal.antlr.HqlBaseParser.negatedExpression(HqlBaseParser.java:2555)
at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalAndExpression(HqlBaseParser.java:2471)
at org.hibernate.hql.internal.antlr.HqlBaseParser.logicalOrExpression(HqlBaseParser.java:2436)
at org.hibernate.hql.internal.antlr.HqlBaseParser.expression(HqlBaseParser.java:2146)
at org.hibernate.hql.internal.antlr.HqlBaseParser.exprList(HqlBaseParser.java:3994)
at org.hibernate.hql.internal.antlr.HqlBaseParser.identPrimary(HqlBaseParser.java:4278)
I would suggest another approach, which could be simpler. Make JPA leading and use the LocalContainerEntityManagerFactoryBean to configure everything (including what you use now for hibernate). Next use the HibernateJpaSessionFactoryBean to expose the underlying SessionFactory.
This would save you duplicate configuration and would allow you to use a single JpaTransactionManager for all your transactions, however you still would be able to use a SessionFactory or HibernateTemplate if you would.
#Configuration
#EnableJpaRepositories(basePackages = {"packagename","package name" })
#EnableTransactionManagement
public class DataBaseConfiguration {
#Autowired
private Environment env;
#Autowired
#Bean(name = "name")
public FactoryBean<SessionFactory> getSessionFactory(EntityManagerFactory emf) {
HibernateJpaSessionFactoryBean factory = new HibernateJpaSessionFactoryBean();
factory.setEntityManagerFactory(emf);
return factory;
}
**\\ existing hibernate flow**
#Bean(name = "name")
public DataSource getDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getRequiredProperty("postgres.driver"));
dataSource.setUrl(env.getRequiredProperty("postgres.url);
dataSource.setUsername(env.getRequiredProperty("postgres.username");
dataSource.setPassword(env.getRequiredProperty("postgres.password");
return dataSource;
}
#Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource(getDataSource());
jpaTransactionManager.setEntityManagerFactory(entityManagerFactory());
return jpaTransactionManager;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
entityManagerFactory.setDataSource(getDataSource());
Map<String, String> properties = new HashMap<String, String>();
properties.put("hibernate.current_session_context_class", SpringSessionContext.class.getName());
entitytManagerFactory.setJpaPropertyMap(properties);
entityManagerFactory.setPackagesToScan(
"some package",
"some package");
HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();
va.setShowSql(env.getProperty("hibernate.show-sql", Boolean.class, true);
va.setDatabasePlatform(env.getProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
entityManagerFactory.setJpaVendorAdapter(va);
return entityManagerFactory;
}
}

CrudRepository save method not returning updated entity

I'm working with Spring and in it spring-data-jpa:1.7.0.RELEASE and hibernate-jpa-2.1-api:1.0.0.Final. My database is a MySQL. In a integration test, when I save an entity, the entityRepository.save() method does not return a update version of it (with the auto-incremented id populated for example), thus I can see it is in the database.
Here's my configuration class:
//#EnableTransactionManagement
#EnableJpaRepositories(basePackages = "core.repository")
#Configuration
#PropertySource("classpath:application.properties")
public class JPAConfiguration {
#Autowired
private Environment env;
private
#Value("${db.driverClassName}")
String driverClassName;
private
#Value("${db.url}")
String url;
private
#Value("${db.username}")
String user;
private
#Value("${db.password}")
String password;
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(user);
dataSource.setPassword(password);
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
vendorAdapter.setDatabasePlatform(env.getProperty("hibernate.dialect"));
final LocalContainerEntityManagerFactoryBean em =
new LocalContainerEntityManagerFactoryBean();
em.setJpaVendorAdapter(vendorAdapter);
em.setPackagesToScan(new String[]{"core.persistence"});
em.setDataSource(dataSource());
em.afterPropertiesSet();
return em;
}
#Bean
public EntityManager entityManager(EntityManagerFactory entityManagerFactory) {
return entityManagerFactory.createEntityManager();
}
#Bean
public JpaTransactionManager transactionManager(final EntityManagerFactory emf) {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
#Bean
public HibernateExceptionTranslator hibernateExceptionTranslator() {
return new HibernateExceptionTranslator();
}
}
Here's my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {JPAConfiguration.class})
//#Transactional
//#TransactionConfiguration(defaultRollback = true)
public class AgencyRepositoryIntegrationTests {
#Autowired
AgencyRepository agencyRepository;
#Test
public void testThatAgencyIsSavedIntoRepoWorks() throws Exception {
Agency c = DomainTestData.getAgency();
Agency d = agencyRepository.save(c);
// here d equals to c but both have id 0.
Collection<Agency> results = Lists.newArrayList(agencyRepository.findAll());
//here results != null and it does contain the agency object.
assertNotNull(results);
}
}
I end up commenting the Transactional annotations (both in the test and in the configuration class) due to research other questions in stackoverflow, but it did not work.
Thanks
Try to uncomment your #Transactional annotation and run. I can't see any visible problem in your snippet but there is something inside me (and it's not hunger) saying that your transaction demarcation is not right. I had similar problems like this before and it was just #transaction annotations missing or transaction misconfiguration.
Use saveAndFlush method to make sure that the entity is in the database.
Make sure to add #Transactional to your methods if a NoTransactionException appears.

Categories

Resources