Many classes/interfaces with general project template - spring

I am looking for a general project template to build a web applications with the following technologies: JSF2, Spring3 and Hibernate4
I found an article that proposes a template but I hesitated beacause for each table in my database I need 5 classes/interfaces:
2 interfaces (dao + service)
2 classes for implementations
1 bean
so is it normal? can someone help with a better architecture?

I would build the architecture on top of the Spring Data JPA module. That would leave you with one class for the entity and one interface (under normal circumstances) for the repository.
For more information take a look at the Spring docs.
Shortened Example:
Spring config:
<!-- Directory to scan for repository classes -->
<jpa:repositories
base-package="x.y.z.repositories" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="true" />
<property name="database" value="HSQL" />
</bean>
</property>
</bean>
Entity:
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#NotNull
private String name;
}
Repository:
public interface ProductRepository extends CrudRepository<Product, Long> {
public List<Product> findByName(String name);
}
In order to use the repository, you simply need to inject it:
#Autowired
private ProductRepository productRepository;

If you include CGLib as a dependency, you can get rid of the interfaces. You won't need them unless you have different implementations of your services from the beginning. Only introduce them if they're really necessary (1:1 Service:ServiceImpl is an anti pattern if you ask me).
Hibernates/JPAs EntityManager is already a generic CRUD DAO, so you don't have to create a DAO for every entity. Introduce them as soon as they are necessary and use EntityManager within your service until then.
Disclaimer: This is a lean approach to Java EE, very close to what Adam Bien recommends in his book Java EE Patterns. We adapted this for spring and it works fine so far.
Great question by the way, java folks often forget to ask themselfs "do we really need this?".

Related

LazyInitializationException and #Transactional not working

I'm using Spring 3.2.9 with multilayered architecture design broken down to 3 modules web, service, repository. In repository i defined a generic DAO class which i inherit by other entity specific DAO classes.
The problem is that when i try to lazy fetch collection of my entity from service layer, I always get LazyInitializationException. I have tried putting #Transactional on my service class, but It appears to not work. I can only avoid exception if I initialize all lazy collections right away in the DAO class method (and only if i annotate DAO class with #Transactional), but I want to fetch those collections only when they are needed in bussiness logic, and not all in advance.
Strange thing is that #Transactional works only in DAO layer, but not in Service layer, where it should be used. I found a couple of ways to work around this issue, but I am interested to really underestend and solve this issue, and not only make make code work.
repository MODULE:
#Repository
public abstract class GenericDao<T> {
protected Class<T> entityClass;
#PersistenceContext
protected EntityManager entityManager;
.........
public T findById(long id) {
T entity = entityManager.find(entityClass, id);
if (entity == null) {
throw new EntityNotFoundException(entityClass.getSimpleName(), id);
}
return entity;
}
}
My service class in service MODULE:
#Service
public class UserServiceImpl implements UserService {
private UserDao userDao;
#SuppressWarnings("SpringJavaAutowiringInspection")
#Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
#Transactional(readOnly = true)
#Override
public UserDto getUserById(long id) {
User user = userDao.findById(id);
return new UserDto(user);
}
The DTO constructor tries to access user.getTeams() and then exception occurs. Instead of that, collection should be fetched with additional query to DB.
CONFIGURATION:
repository configuration:
......some other configurations like datasource...
<!--EntityManagerFactory-->
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="${hibernate_dialect}"/>
<entry key="hibernate.hbm2ddl.auto" value="${hibernate_Hbm2ddlAuto}"/>
<entry key="hibernate.show_sql" value="${hibernate_showSql}"/>
<entry key="hibernate.format_sql" value="${hibernate_formatSql}"/>
</map>
</property>
</bean>
persistence.xml:
<persistence-unit name="persistenceUnit">
...other classes..
<class>com.example.entity.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
</properties>
</persistence-unit>
service configuration:
<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/>
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
It looks like #OneToMany association between the user and his or her teams which is lazy loaded. When you assign them to Dto it is still proxy not real collection. Put a break point there and see it in debug mode. Keep in mind any request (get a team or its size make it alive). One way is to fetch them in query, but
entityManager.find(entityClass, id)
doesn't have option for it. You may use
Hibernate.initialize(user.getTeams())
Found the answer after few days of headache.
I had to move:
<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/>
<tx:annotation-driven/>
from repositoryConfiguration.xml to dispatcher-servlet.xml since that is the parent Spring context.
Thanks for the help.

EntityManager.flush() not flushing (JPA2 (OpenJPA), EJB3, Spring3, Websphere 7)

I'm facing a problem in my project: entityManager.flush() is not doing anything, and the flushing is only being done right before commit, when exiting the EJB.
My project runs on WebSphere 7.
I'm using JPA2 through OpenJPA.
I'm using Spring for Autowiring.
I'm using Container Managed Transactions.
Relevant code snippets below
persistence.xml
<persistence-unit name="persistenceUnit" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<properties>
<property name="openjpa.TransactionMode" value="managed" />
<property name="openjpa.ConnectionFactoryMode" value="managed" />
<property name="openjpa.DynamicEnhancementAgent" value="true" />
<property name="openjpa.jdbc.DBDictionary" value="StoreCharsAsNumbers=false" />
<property name="openjpa.Log" value="SQL=TRACE"/>
</properties>
</persistence-unit>
applicationContext.xml
<!-- Configure a JPA vendor adapter -->
<bean id="openJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
</bean>
<!-- Entity Manager -->
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/myappDS"/>
</bean>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter" ref="openJpaVendorAdapter" />
</bean>
EJB3 Bean
#Stateless(name="JPABaseEntityServiceBean")
#Configurable
public class JPABaseEntityServiceBean implements JPABaseEntityService {
Logger logger = LoggerFactory.getLogger(JPABaseEntityServiceBean.class);
#Autowired
JPABaseEntityDao jpaBaseEntityDao;
public JPABaseEntity persist(JPABaseEntity jpaBaseEntity) {
return jpaBaseEntityDao.persist(jpaBaseEntity);
}
DAO:
#Repository
public class JPABaseEntityDao implements BaseEntityDao {
#PersistenceContext
transient EntityManager entityManager;
public JPABaseEntity persist(JPABaseEntity jpaBaseEntity) {
Date now = new Date();
jpaBaseEntity.setCreatedBy(TO_DO_ME);
jpaBaseEntity.setUpdatedBy(TO_DO_ME);
jpaBaseEntity.setUpdatedOn(now);
jpaBaseEntity.setCreatedOn(now);
entityManager.persist(jpaBaseEntity);
entityManager.flush();
return jpaBaseEntity;
}
The "INSERT" is being done only when leaving the EJB, meaning the entityManager.flush() inside the DAO is not working
Ok, resolved in a way
Seems like the problem was that the Entity Manager was not getting the Transaction from WebSphere (probably because the Entity Manager was being injected by Spring, I haven't investigated that deeply)
So what I did is make Spring control the transaction in the EntityManager:
1. added <tx:annotation-driven/> and <tx:jta-transaction-manager/> to applicationContext.xml
2. annotated the DAO methods with #Transactional
The overall transaction is still handled by the EJB, meaning it's still using CMT and JTA from WebSphere
I had a ton of problems in the way because of dependency hell (the one that got me the most was hibernate-core including JBoss's javax.transaction implementation, grr), but other than that everything seems to be working smoothly

Issue with #Transactional annotations in Spring JPA

I have a doubt related to transactions within transactions. For background, I have a School entity object which has Set of Students entity object mapped to it. I am using Spring Data JPA which is taking care of all the crud operations. I have a SchoolManagementService class which has #Transactional(readonly=true) set at the class level and for all updating methods I am using #Transactional over them.
In my SchoolManagementService class I have a method deleteStudents(List) which I have marked as #Transactional. In this method I am calling StudentsRepository.delete(studentId) again and again. I want to make sure if any delete fails then the transaction should rollback for that checked exception. I am trying to test this with my spring junit test case (I am not using default rollback=true or#rollback(true) because I want this to be rollbacked because of some runtime exception I encounter at the repository delete method.
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
#ContextConfiguration(locations = {"classpath:PPLRepository-context.xml"})
public class TestClass{
#Test
#Transactional
public void testDeleteStudents(){
StudentManagementService.delete(randomList)
}
with this testcase it is deleting all the records but the last one. Ideally it should rollback and none of of entries should be deleted.
Here is my sprin settings file with TransactionMangaer configs
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init"
destroy-method="close">
<property name="forceShutdown" value="true" />
<property name="startupTransactionService" value="true" />
<property name="transactionTimeout" value="1000" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" />
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
<property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" />
</bean>
<!-- EntityManager Factory that brings together the persistence unit, datasource, and JPA Vendor -->
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="PPL_GMR">
<property name="dataSource" ref="PPL_GMRDS"></property>
<property name="persistenceUnitName" value="PPL_GMR"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/PPL-persistence.xml"/>
<property name="jpaVendorAdapter" ref="PPL_GMRJPAVendorAdapter"/>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.transaction.manager_lookup_class" value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"/>
<entry key="hibernate.connection.release_mode" value="on_close"/>
<entry key="hibernate.default_schema" value="${PPL.schema}"/>
</map>
</property>
</bean>
Can someone suggest where my understanding of transactions is wrong? Whatever I have read from the APIs I got this impression that if some method is #Transactional at the service layer and if it calls several #Transactional methods of Spring Data JPA repositories then if I encounter any Runtime exception then all the transactions should be rolled back.
I even tried to simple create a testcase method as below:
#Test
#Transactional
public void testDeleteStudents(){
StudentRepository.delete(1);
StudentRepository.delete(2);// 2 id is not present so I will get a runtime exception.
}
Inspite of keeping #Rollback(true/false) on this method, this method deletes id 1 Student from the database. I thought that #Transactional at this testcase method will create a new transaction here and all the transactional delete methods from the StudentRepository will run in same transaction. And no student data will be committed until and unless no runtime exception is thrown.
Please help me understand transactions better as I am new to this. i am using Spring Data JPA with Oracle database.
Thanks in advance.
I think that the default behaviour is (even thought you don't have it on the test class)
#TransactionConfiguration(defaultRollback = true)
so it will perform rollback when your test ends. Therefore there is no synchronization of hibernate session with the database and no queries SQL are issued to the database.
You have two posibilities. Either specify
#TransactionConfiguration(defaultRollback = false)
or inject entity manager into your test and call
#PersistenceContext
protected EntityManager em;
/**
* Simulates new transaction (empties Entity Manager cache).
*/
public void simulateNewTransaction() {
em.flush();
em.clear();
}
This will force hibernate to send all queries to the database. Please note that this will solve your problem with deleting non existing entity, but it doesn't behave exactly like new transaction, e.g. when you have missing foreign key it doesn't throw anything (this is predictable.
You can use this for checking the contents of entity returned by em.find(class, id) and check you relational mapping without the need to commit the transaction.

What's the link between #Transactional and cascading?

There seems to be a link between the presence of the #Transactional annotation on a Spring JUnit test and cascading when persisting/merging a JPA2 entity.
I don't have the configuration at hand for the moment, but maybe this rings a bell to somebody in here ?
Assume a simple case of JPA entities on three levels: Entity A references an entity of class B and that instance of class B references an instance of class C.
A -> B -> C
Class A does cascading ALL to B. And B does cascading ALL to C. And Class C has an event listener method annotated with #PrePersist and #PreUpdate. It logs a message to prove the cascading made it to there.
Now, modify entity C in some way and ask the entity manager to merge or persist the instance of A. Logically entity C will eventually be persisted or merged also. Because of cascading has been set to ALL from class A to B to C.
When the Spring unit test is not annotated with #Transactional, the log message from the event listener method of class C prints its message. OK.
But when it is annotated with #Transactional, no message at all is printed. And indeed, nothing has been committed to the database for class C. Only for class A. Hence, I conclude the cascading didn't make it from A to C.
Removing the annotation fixes the problem.
Anybody any clue? :-) Logically I would think transactions and cascading are two totally separated matters.
A typical test case configuration:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/test-beans.xml")
#TransactionConfiguration
#Transactional
public class MyUnitTest {
...
#Test
public void testSomething() {}
...
}
An extract of the Spring xml configuration file - nothing fancy there I think ...
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="com.foo.bar" />
<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="/META-INF/persistence.xml"/>
<property name="persistenceUnitName" value="bar" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Extract from persistence.xml
<persistence-unit name="bar" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/bar" />
<property name="hibernate.connection.username" value="bar" />
<property name="hibernate.connection.password" value="pwd" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
Libraries
Spring 3.0.6 ORM/CONTEXT/TEST
Hibernate 3.6.7.Final
JUnit 4.9
JPA2
Found it ! An improper entity manager usage was turning bad when transactions were enabled. It wasn't related to the persistence but was done right before it. Causing the persistence to fail in some way.
I implemented a Query result iterator for which an EntityManager was required. I thought I could create it from the EntityManagerFactory of the jpaTemplate.
final EntityManager em = jpaTemplate.getEntityManagerFactory().createEntityManager();
return new QueryIterator<T>(em.createQuery("FROM Foo"));
Obviously not. It seems the EntityManager has to be obtained in a different way. As described underneath.
jpaTemplate.execute(new JpaCallback() {
#Override
public Object doInJpa(final EntityManager em) throws PersistenceException {
return new QueryIterator<T>(em.createQuery("FROM Foo"));
}
});
Now it all works ok. As it is supposed to be, regardless of transactions being present or not. :-)

DataSourceTransactionManager and test for active transaction

I have a simple app that use org.springframework.jdbc.datasource.DataSourceTransactionManager to manage the transactions.
My spring config is as follow:
<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
I have annotated the method with #Transactional and print out the TransactionSynchronizationManager.isActualTransactionActive()
But the out put is false. What have i done wrong ?
Edit: i forgot to say that i test that with SpringJUnit4ClassRunner.class. I included the TransactionalTestExecutionListener.class and this will not work. Now it worked after i extend the class with AbstractTransactionalJUnit4SpringContextTests
I think you forgot to add the below to your cfg file. this is required when you are using annotations. Have you added this?
<tx:annotation-driven/>
Here is the namespace
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
Did you use the required annotations on your test class?
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:/spring-....xml")
#TestExecutionListeners({TransactionalTestExecutionListener.class, DependencyInjectionTestExecutionListener.class})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
#Transactional(readOnly = false)
public class MyTest {
...
}
I'm not sure whether the last two are really necessary, I want my test cases to have an active transaction that's why I need those. The first three should be enough in order to get transactional proxies for your annotated beans.
I had the same problem, you should use this instead:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

Resources