0

I work on a Java EE application with Spring and JPA (EclispeLink). We developed a user-friendly interface for administrating the database tables. As I know more about Spring and Transactions now, I decided to refactor my code to add better transaction management. The question is how to best deal with generic DAOs, generic services and Spring transactions?

Our current solution was:

  • A generic BasicDAO which deals with all common database actions (find, create, update, delete...)
  • A DaoFactory which contains a map of implementations of BasicDao for all entity types (which only need basic database actions) and which gets the entitymanager injected by spring to pass it to the daos
  • A generic BasicService which offers the common services (actually directly linked to the dao methods)
  • A ServiceFactory which contains a map of implementations of BasicService for all entity types, which gets the daoFactory injected and passes it to the services. It has a method "getService(Class T)" to provide the right service to the controllers.
  • Controllers corresponding to the right entity types which delegate their requests to a generic controller which handles the request parameters using reflection and retrieves the right service from the service factory's map to call the update/create/remove method.

Problem is that, when I add the @Transactionnal annotations on the generic Service and my serviceFactory creates the typed services in its map, these services don't seem to have active transactions running.

1) Is it normal, due to the genericity and the fact that only spring-managed services can have transactions?

2) What is the best solution to solve my problem:

  • Create managed typed services only implementing the generic service and inject them directly in my serviceFactory?
  • Remove the service layer for these basic services? (but maybe I'll get the same problem with transactions on my dao generic layer...)
  • Other suggestions?

I read some questions related to these points on the web but couldn't find examples which went as far into genericity as here, so I hope somebody can advise me... Thanks in advance!

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Coralie
  • 107
  • 3
  • 17
  • you can't inherit annotations ... – NimChimpsky Jun 12 '13 at 12:45
  • It's actually not about inheritance... it's about instantiation of the generic type (example : IService projectService = new BasicService()// The projectService cannot deal with transactions which are specified in BasicService because it's not a managed entity...) – Coralie Jun 12 '13 at 12:58
  • don't instantiate your service like that then – NimChimpsky Jun 12 '13 at 12:59
  • I have similar issue se this http://stackoverflow.com/questions/16774962/spring-and-manually-created-daos-how-to-refactor-to-enable-haspermisions-on-such – Josef Prochazka Jun 12 '13 at 13:03

1 Answers1

1

For basic gets you don't need a service layer.

A service layer is for dealing with multiple aggregate roots - ie complex logic invloving multiple different entities.

My implementation of a generic repository looks like this :

public class DomainRepository<T> {

    @Resource(name = "sessionFactory")
    protected SessionFactory sessionFactory;

 public DomainRepository(Class genericType) {
        this.genericType = genericType;
    }

 @Transactional(readOnly = true)
    public T get(final long id) {
        return (T) sessionFactory.getCurrentSession().get(genericType, id);
    }

@Transactional(readOnly = true)
    public <T> List<T> getFieldEquals(String fieldName, Object value) {
        final Session session = sessionFactory.getCurrentSession();
        final Criteria crit = session.createCriteria(genericType).
                add(Restrictions.eq(fieldName, value));
        return crit.list();
    }
//and so on ..

with different types instantiated by spring :

<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
        <constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>

and can be referenced like so :

@Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;

And can also be extended manually for complex entities.

NimChimpsky
  • 46,453
  • 60
  • 198
  • 311