Spring Data #CreatedDate annotation doesn't work for me - java

I am working on project where I use Spring Data. I wanted to fill in creationTime field using #CreatedDate annotation instead using method with #PreUpdate or #PrePersist annotation (doing it this way it works perfectly). When I do it with #CreatedDate it just leaves this field blank. I use postgresql database. Documentation is not very helpful.
Do you have any idea how can I fix it? Thank you!
import org.springframework.data.annotation.CreatedDate;
#Entity
#Table(name = "software")
public class Software implements Serializable {
// ...
#Column(name = "creation_time")
#CreatedDate
private Date creationTime;
//...
}
My applicationContext:
<jpa:repositories base-package="path.to.dao"/>
<context:component-scan base-package="path.to.dao"/>
<context:property-placeholder location="classpath:application.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="packagesToScan" value="path.to.bean"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="jpaAdapter"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
<prop key="hibernate.ejb.naming_strategy">${hibernate.ejb.naming_strategy}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
</props>
</property>
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

I may have been in a similar situation where I wanted the Spring Data JPA #CreatedDate annotation to work, but had no need for the user-level auditing that is otherwise described in their documentation.
To get the annotation-based auditing to work, I had to nonetheless add a class to my project that implemented org.springframework.data.domain.AuditorAware. This is odd because you don't actually seem to use the value returned from the getCurrentAuditor() method that you'll be implementing; mine just returns null.
public class NullAuditorBean implements AuditorAware {
#Override
public Object getCurrentAuditor() {
return null;
}
}
I then needed to reference my "null object" AuditorAware implementation in an entry in my applicationContext to activate the JPA auditing. I had to make sure I did this before the line that specifies the jpa:repositories. This looks something like:
<bean id="auditorBean" class="your.package.subbed.here.NullAuditorBean"/>
<jpa:auditing auditor-aware-ref="auditorBean"/>
I also had to add an orm.xml file, and needed to formally reference it as a property of my entityManagerFactory bean, like so:
<property name="mappingResources">
<value>META-INF/orm.xml</value>
</property>
Make sure this META-INF/orm.xml entry is stored with your compile output (mine is in my WAR under WEB-INF/classes.
That orm.xml file, for the record, contained some boilerplate, which can be found in the answer to this related question.
It was a fair amount of work when I got this working. You may prefer your previous working solution!

This question is quite old, but still relevant. For me the key was this, from the documentation
Since Spring Data MongoDB 1.4 auditing can be enabled by annotating a configuration class with the #EnableMongoAuditing annotation.
For example:
#Configuration
#EnableMongoAuditing
class Config {
/**
* Optional, depending on your needs
*/
#Bean
public AuditorAware<AuditableUser> myAuditorProvider() {
return new AuditorAwareImpl();
}
}
Or, in XML:
<mongo:auditing/>

I have experienced the same issue, but wasn't able to get my head around it.
I have chosen to use Hibernate's #CreationTimestamp instead, and it works like a charm!

Related

Multiple Spring datasources for JUnit test

I have such simple class for JUnit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/mysql-datasource-context.xml"})
public class EmployeeDAOTest {
#Autowired
EmployeeDao employeeDao;
#Test
public void findAllTest() {
assertTrue(employeeDao.findByName("noname").size() == 0);
}
}
The content of the mysql-datasource-context.xml looks like this:
<context:component-scan base-package="my.packages.*"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/project"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="my.packages.entity"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
Now the test runs with no problem for my mysql database.
The point is that I also have a postgres database and I need every test run both for the mysql and postgres databases.
The only solution that comes to my mind is creating one more test class with exactly the same tests but annotate it as
#ContextConfiguration(locations = {"classpath:/postgres -datasource-context.xml"})
and create one more datasource context file for it. Unfortunately this way doesn't look like a good solution.
Is there a better way to solve my problem?
I think that the simplest solution is to keep a test class as the base one:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/mysql-datasource-context.xml"})
public class EmployeeDAOTest {
#Autowired
EmployeeDao employeeDao;
#Test
public void findAllTest() {
assertTrue(employeeDao.findByName("noname").size() == 0);
}
}
and then creating one empty subclass for postgres with its own configuration:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/postgres-datasource-context.xml"}, inheritLocations=false)
public class EmployeeDAOTestPostgres extends EmployeeDAOTest {
}
As other suggested you can alter your Spring config files in order to have only one; you can for example put the datasource in a separate context and import it or use a profile (see here for an example)
At a glance is the spring multiple data source configure, actually you can get a lot posts for this via google or quickly search it in stackoverflow
Example:
Spring Boot Multiple Datasource
Another solution I can image is using the spring profile.
I always find it's best to have a top level app context file which includes other files:
appcontext-root.xml
<beans>
<import resource="appcontext-services.xml"/>
<import resource="appcontext-db.xml"/>
</beans>
Then your application can run the context-root.xml, but your tests can test one (or more) of the lower level files.
If you want a swappable back end, you might consider using a PropertyPlaceHolderConfigurer.
eg:
<import resource="appcontext-db-${vendor}.xml"/>
And have a appcontext-db-mysql.xml, appcontext-db-postgres.xml along with System.setProperty("vendor", "mysql")

Null EntityManager Spring 4

I'm trying to setup entity manager with Spring 4 and I always get NullPointerException when I try to inject EntityManager with #PersistenceContext annotation.
I have Maven web application. Here's my applicationContext.xml configuration
<bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="EcommercePU">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.mysite.ecommerceapp.domain</value>
<value>com.mysite.ecommerceapp.domain.*</value>
<value>com.mysite.ecommerceapp.domain.*.*</value>
<value>com.mysite.ecommerceapp.domain.*.*.*</value>
</list>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</prop>
</props>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/ecommercedb" />
<property name="username" value="postgres" />
<property name="password" value="test" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="myEmf" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
applicationContext.xml is located under WEB-INF folder. Because I use NetBeans 8 I added Spring Framework support to my project from project properties -> Frameworks. I'm using EntityManager injection with file called GenericDaoImpl and here's it's code:
public abstract class GenericDaoImpl<E extends EntityClass> implements GenericDao<E> {
private Class<E> entityClass;
#PersistenceContext()
private EntityManager entityManager;
//Constructor
public GenericDaoImpl(final Class<E> entityClass) {
this.entityClass = entityClass;
}
//Getters and Setters
public Class<E> getEntityClass() {
return entityClass;
}
public void setEntityClass(final Class<E> entityClass) {
this.entityClass = entityClass;
}
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(final EntityManager entityManager) {
this.entityManager = entityManager;
}
public void checkEntityManager() {
System.out.println("em: " + this.entityManager);
}
}
I have one test file where I simply print entity manager with checkEntityManager() method. Whenever I run it I always get null value for EntityManager. What could be wrong? My biggest doubt is that my applicationContext.xml is in wrong place or it is not used anywhere and thus it can't find configuration properties in applicationContext. I have tested moving applicationContext.xml file to resources folder but it didn't helped either. Other questions that I also have are following:
Do I need to have persistence.xml? Since I use Spring 4 with packagesToScan feature I heard that persistence.xml is not required but I'm not sure.
Is it wise to use hibernate to take care only basic entities cruds and other dao queries with JdbcTemplate?
All help would be appreciated.
I finally solved the problem and there were lots of things that has to be done.
When I tested my Entity Manager through JUnit tests I got NullPointerException and reason was the configuration file was incorrect folder.
applicationContext.xml was properly setup except there was a small problem that messed the whole file and that was <property name="persistenceUnitName" value="EcommercePU">. Because I didn't had such persistence unit file in whole project it couldn't find it. When you add that property it doesn't mean that you have created a spring configuration file that has such persistence unit name. It simply means that if you want to provide persistence configurations to your LocalContainerEntityManagerFactory you would refer with that name to your persistence unit. This is not required in Spring 4.
applicationContext.xml had to be moved from WEB-INF to resources folder.
When you would run JUnit tests you should use #Autowired annotation to annotate DAO's.
Dao implementation classes should have #Repository annotation.
#Transactional annotation is required at least for CRUD methods if you are going to use. You can also annotate whole class. If you don't add #Transactional annotation EntityManager wouldn't execute persist, remove, update, find and other methods properly. Remember this is required if you are using Spring configurations.

Inject entity manager from XML in Spring

I need to do very similar thing to what is described in Injecting Entitymanager via XML and not annnotations, but I need to inject from XML the real, container-created, entity manager, so that it behaves exactly as if there is a real #PersistenceContext annotation. I've found a LocalEntityManagerFactoryBean (notice missing "Container" word), but I'm affraid that it creates a new entity manager factory and therefore entity manager won't be compatible with that injected via real #PersistenceContext annotation.
I will describe the reason, because it is weird and maybe the solution to my problem is to choose completely different approach. I'm using PropertyPlaceholderConfigurer in my spring configuration and in this configurer I'm referencing other beans. I'm experiencing a bug that autowiring doesn't work in those referenced beans. I don't know why and how PropertyPlaceholderConfigurer turns off autowiring in those referenced beans but the fact is, that if I replace autowiring by xml configuration for those beans, everything works. But I'm unable to replace autowiring of EntityManager, since it's not standard spring bean, but jndi-loaded something I don't fully understand.
One way or the other, is there some solution?
in spring-bean.xml ,
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="USER_TEST"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect"/>
</property>
<property name="jpaPropertyMap">
<props>
<prop key="eclipselink.weaving">false</prop>
</props>
</property>
<bean id="PersonDao" class="com.xxx.java.person.persistence.PersonDAO">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="earlyInitializedApplicationSettingsService" class="...services.impl.ApplicationSettingsServiceImpl" autowire-candidate="false">
<property name="applicationSettingsDao">
<bean class="....impl.ApplicationSettingsDaoImpl">
<property name="entityManager">
<bean class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory">
<bean class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/persistence/somePersistenceUnit"/>
</bean>
</property>
</bean>
</property>
</bean>
</property>
</bean>
Notice mainly the fact, that I'm not using standard jee:jndi-lookup, because it didn't work (in the conditions created by PropertyPlaceholderConfigurer) and that was the source of my confusion. When I used direct JndiObjectFactoryBean, it worked.

#Transactional questions and how to use with #Service

My service makes use of a generic DAO (which explicitly uses Hibernate session factory). I have spent some time before I discovered this error
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
I annotated my service and all works perfectly. Now I want to use context path scanning, and remove this line from my configuration:
<bean id="societaService" class="it.trew.prove.services.SocietaService" />
So.... here's my final version:
#Service
#Transactional(readOnly = true)
public class SocietaService {
private Dao societaDao;
#Autowired
public void setSocietaDao(Dao societaDao) {
this.societaDao = societaDao;
}
public void salvaSocieta(Societa s) {
societaDao.save(s);
}
public List<Societa> listAll() {
return societaDao.getAll(Societa.class);
}
public void deleteById(Long id) {
societaDao.delete(getSocieta(id));
}
public Societa getSocieta(String id) {
return getSocieta(Long.parseLong(id));
}
public Societa getSocieta(Long id) {
return societaDao.get(Societa.class, id);
}
}
Adding #Service annotation makes my app give the awful hibernate error above. Why?
Removing #Service and configuring the service bean via xml = it works. WHY??
In addition:
does transactional annotating my service class makes all its methods to be executing in a transaction?
EDIT
Here's my context xml:
<context:annotation-config />
<context:component-scan base-package="it.trew.prove" />
<!-- Hibernate -->
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.google.appengine.api.rdbms.AppEngineDriver" />
<property name="url" value="jdbc:google:rdbms://xxx:xxx/xxx" />
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>it.trew.prove.model.beans.Scadenza</value>
<value>it.trew.prove.model.beans.Fornitore</value>
<value>it.trew.prove.model.beans.Societa</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
<!-- <prop key="hibernate.hbm2ddl.import_files">/setup.sql</prop> -->
</props>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
Did you enabled annotations ?
<context:annotation-config />
and
<context:component-scan base-package="org.example"/>
this will enable annotations like #Service, #Component and #Repository
First of all, you need to tell spring to enable Transactional annotation with something like that:
<tx:annotation-driven transaction-manager="transactionManager" />
Second, if you use #Transactional at class level, any call to a method of your Service will be transactional. Whether it starts a transaction or not depends on the "propagation" attribute. The default is start one if none started in this session (Propagation.REQUIRED). If you use #Transactional only at class level, all of your methods will inherit its attributes, i.e., if you set "readOnly = true", all of yours methods will be read only, thus, updates/saves/delete won't work. I would recommend you to read more the Spring Transaction Management Doc

using AbstractTransactionalDataSourceSpringContextTests with Hibernate & DbUnit - inserted data not found

All,
I'm attempting to write a unit test for a Dao that uses Hibernate. I'm also using Spring, so I'm trying to extend AbstractTransactionalDataSourceSpringContextTests and also use DBUnit to insert data into the database before each test in the onSetUpInTransaction method.
From my logs, I can see that DbUnit is able to successfully insert the data in onSetUpInTransaction just fine. However, when I run a test method that uses the Dao (and therefore, Hibernate) to try to access that data (testGetPersonById2), the data isn't found, even though all this should be happening in the same transaction. After the test method finishes running (it fails), I see the log statement from the AbstractTransactionalDataSourceSpringContextTests that the transaction does get rolled back correctly.
It seems like the onSetUpInTransaction and Hibernate session must be using different transactions, but I can't figure out why. Does anyone have an example of something like this working? Advice on what I'm missing?
Here's what I've got so far:
public class PersonDaoTest extends AbstractTransactionalDataSourceSpringContextTests{
private Log logger = LogFactory.getLog(PersonDaoTest.class);
private PersonDaoImpl personDao;
#Override
public void onSetUpInTransaction() throws Exception {
// Load test data using DBUnit
super.onSetUpBeforeTransaction();
DataSource ds = jdbcTemplate.getDataSource()
Connection con = DataSourceUtils.getConnection(ds);
IDatabaseConnection dbUnitCon = new DatabaseConnection(con);
DatabaseConfig config = dbUnitCon.getConfig();
config.setFeature("http://www.dbunit.org/features/qualifiedTableNames",
true);
//This dataset contains a single entry in the Persons table,
// a new person with Id = 998877665, it gets inserted successfully
IDataSet dataSet = new FlatXmlDataSet(new FileInputStream(
"./PersonDaoTest.xml"));
logger.warn("dataSet = " + dataSet);
try {
DatabaseOperation.REFRESH.execute(dbUnitCon, dataSet);
SessionFactoryUtils.getSession(getSessionFactory(), false).flush();
} finally {
DataSourceUtils.releaseConnection(con, ds);
}
}
//This test PASSES, because the Person with Id = 9 already
//exists in the database, it does not rely on the data being set up in the
// onSetUpInTransaction method
#Test
public void testGetPersonById() {
Person person = personDao.findById(9L);
assertNotNull("person should not be null", person);
}
//This test FAILS at the assertNotNull line, because
//no Person with Id = 998877665 exists in the database,
//even though that Person was inserted
//in the onSetUpInTransaction method - it seems
//that hibernate cannot see that insertion.
#Test
public void testGetPersonById2() {
Person person = personDao.findById(998877665L);
assertNotNull("person should not be null", person);
}
UPDATE: Here's my spring config:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
<bean id="dataSource" class="com.p6spy.engine.spy.P6DataSource">
<constructor-arg>
<bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>${jdbc.driverClassName}</value>
</property>
<property name="url">
<value>${jdbc.url}</value>
</property>
<property name="username">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
</constructor-arg>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.query_cache_factory">org.hibernate.cache.StandardQueryCacheFactory</prop>
</props>
</property>
</bean>
<!-- The Hibernate interceptor
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>-->
<bean id="personDao" class="my.dao.PersonDaoImpl">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
I spent some more time with this, and never was able to find anything that worked when trying to use the onSetUpInTransaction method. I ended up switching over to using onSetUpBeforeTransaction and onTearDownAfterTransaction instead. It's not exactly ideal, because the onSetUpBeforeTransaction method does end up committing its data insertions to the database, and that data must then be cleaned up in onTearDownAfterTransaction. However, the tests themselves can still insert and update data all they want and have those changes all rolled back, since each test does still operate in its own transaction. So, I don't have to do anything special to clean up when a test inserts new data, which means I met one of my goals anyway!
I had a similar problem. here is how I solved it.
I added a code to my abstract testcase class
then I added a datasource with the name "dataSource" which allowed me to use it to insert my test data and create my test sqls using that data source.
The individual datasources datasource1 and datasource2 were correctly injected into my dao beans without any issue.
#Override
protected String[] getConfigLocations()
{
setAutowireMode(AUTOWIRE_BY_NAME);
setDependencyCheck(false);
return new String[] { "classpath:configuration/myappxxx-test-application-context.xml" };
}

Categories