New instructions for Spring/Hibernate DAO layer

As expected, the @Autowired annotation may be applied to "traditional" setter methods:

public class SimpleMovieLister { 
private MovieFinder movieFinder; 
@Autowired 
public void setMovieFinder(MovieFinder movieFinder) { 
this.movieFinder = movieFinder; 
} 
// ... 
} 

The annotation may also be applied to methods with arbitrary names and/or multiple arguments:

public class MovieRecommender { 
private MovieCatalog movieCatalog; 
private CustomerPreferenceDao customerPreferenceDao; 
@Autowired 
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) { 
this.movieCatalog = movieCatalog; 
this.customerPreferenceDao = customerPreferenceDao; 
} 
// ... 
} 

The @Autowired annotation may even be applied on constructors and fields:

public class MovieRecommender { 
@Autowired 
private MovieCatalog movieCatalog; 
private CustomerPreferenceDao customerPreferenceDao; 
@Autowired 
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) { 
this.customerPreferenceDao = customerPreferenceDao; 
} 
// ... 
} 

It is also possible to provide all beans of a particular type from the ApplicationContext? by adding the annotation to a field or method that expects an array of that type:

public class MovieRecommender { 
@Autowired 
private MovieCatalog[] movieCatalogs; 
// ... 
} 

The same applies for typed collections:

public class MovieRecommender { 
private Set<MovieCatalog> movieCatalogs; 
@Autowired 
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) { 
this.movieCatalogs = movieCatalogs; 
} 
// ... 
} 

Even typed Maps may be autowired as long as the expected key type is String. The Map values will contain all beans of the expected type, and the keys will contain the corresponding bean names:

public class MovieRecommender { 
private Map<String, MovieCatalog> movieCatalogs; 
@Autowired 
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) { 
this.movieCatalogs = movieCatalogs; 
} 
// ... 
} 

By default, the autowiring will fail whenever zero candidate beans are available; the default behavior is to treat annotated methods, constructors, and fields as indicating required dependencies. This behavior can be changed as demonstrated below.

public class SimpleMovieLister { 
private MovieFinder movieFinder; 
@Autowired(required=false) 
public void setMovieFinder(MovieFinder movieFinder) { 
this.movieFinder = movieFinder; 
} 
// ... 
} 

Note Only one annotated constructor per-class may be marked as required, but multiple non-required constructors can be annotated. In that case, each will be considered among the candidates and Spring will use the greediest constructor whose dependencies can be satisfied. Prefer the use of @Autowired's required attribute over the @Required annotation. The required attribute indicates that the property is not required for autowiring purposes, simply skipping it if it cannot be autowired. @Required, on the other hand, is stronger in that it enforces the property to have been set in any of the container's supported ways; if no value has been injected, a corresponding exception will be raised.

@Autowired may also be used for well-known "resolvable dependencies": the BeanFactory? interface, the ApplicationContext? interface, the ResourceLoader? interface, the ApplicationEventPublisher? interface and the MessageSource? interface. These interfaces (and their extended interfaces such as ConfigurableApplicationContext? or ResourcePatternResolver?) will be automatically resolved, with no special setup necessary.

public class MovieRecommender { 
@Autowired 
private ApplicationContext context; 
public MovieRecommender() { 
} 
// ... 
} 

Spring Annotations

Beginning with Spring 2.0, the @Repository annotation was introduced as a marker for any class that fulfills the role or stereotype of a repository (a.k.a. Data Access Object or DAO). Among the possibilities for leveraging such a marker is the automatic translation of exceptions. Spring 2.5 introduces further stereotype annotations: @Component, @Service and @Controller. @Component serves as a generic stereotype for any Spring-managed component; whereas, @Repository, @Service, and @Controller serve as specializations of @Component for more specific use cases (e.g., in the persistence, service, and presentation layers, respectively). What this means is that you can annotate your component classes with @Component, but by annotating them with @Repository, @Service, or @Controller instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. Of course, it is also possible that @Repository, @Service, and @Controller may carry additional semantics in future releases of the Spring Framework. Thus, if you are making a decision between using @Component or @Service for your service layer, @Service is clearly the better choice. Similarly, as stated above, @Repository is already supported as a marker for automatic exception translation in your persistence layer.

Spring Component autodetection

Spring provides the capability of automatically detecting 'stereotyped' classes and registering corresponding BeanDefinitions? with the ApplicationContext?. For example, the following two classes are eligible for such autodetection:

@Service 
public class SimpleMovieLister { 
private MovieFinder movieFinder; 
@Autowired 
public SimpleMovieLister(MovieFinder movieFinder) { 
this.movieFinder = movieFinder; 
} 
} 
@Repository 
public class JpaMovieFinder implements MovieFinder { 
// implementation elided for clarity 
} 

To autodetect these classes and register the corresponding beans requires the inclusion of the following element in XML where 'basePackage' would be a common parent package for the two classes (or alternatively a comma-separated list could be specified that included the parent package of each class).

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context-2.5.xsd"> 
<context:component-scan base-package="org.example"/> 
</beans> 

Furthermore, the AutowiredAnnotationBeanPostProcessor? and CommonAnnotationBeanPostProcessor? are both included implicitly when using the component-scan element. That means that the two components are autodetected and wired together - all without any bean configuration metadata provided in XML.

By default, classes annotated with @Component, @Repository, @Service, or @Controller (or classes annotated with a custom annotation that itself is annotated with @Component) are the only detected candidate components. However it is simple to modify and extend this behavior by applying custom filters. These can be added as either include-filter or exclude-filter sub-elements of the 'component-scan' element. Each filter element requires the 'type' and 'expression' attributes. Five filtering options exist as described below.

Filter typeExample expressionDescription
annotation org.example.SomeAnnotation? An annotation to be present at the type level in target components.
assignable org.example.SomeClass? A class (or interface) that the target components are assignable to (extend/implement).
aspectj org.example..*Service+ An AspectJ type expression to be matched by the target components.
regex org\.example\.Default.* A regex expression to be matched by the target components' class names.
custom org.example.MyCustomTypeFilter? A custom implementation of the org.springframework.core.type.TypeFilter? interface.

Find below an example of the XML configuration for ignoring all @Repository annotations and using "stub" repositories instead.

<beans ...> 
<context:component-scan base-package="org.example"> 
<context:include-filter type="regex" expression=".*Stub.*Repository"/> 
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 
</context:component-scan> 
</beans> 

Note
It is also possible to disable the default filters by providing use-default-filters="false" as an attribute of the <component-scan/> element. This will in effect disable automatic detection of classes annotated with @Component, @Repository, @Service, or @Controller.

Exception translation

We in Project.net right now do not have appropriate exception handling but this is going to change here is small part about implementation and exception handling in Spring. DAO throws the plain PersistenceException? exception class (which is unchecked, and so does not have to be declared or caught) but also IllegalArgumentException? and IllegalStateException?, which means that callers can only treat exceptions as generally fatal - unless they want to depend on JPA's own exception structure. Catching specific causes such as an optimistic locking failure is not possible without tying the caller to the implementation strategy. This tradeoff might be acceptable to applications that are strongly JPA-based and/or do not need any special exception treatment. However, Spring offers a solution allowing exception translation to be applied transparently through the @Repository annotation:

@Repository 
public class ProductDaoImpl implements ProductDao { 
// class body here... 
} 
<beans> 
<!-- Exception translation bean post processor --> 
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/> 
<bean id="myProductDao" class="product.ProductDaoImpl"/> 
</beans> 

The postprocessor will automatically look for all exception translators (implementations of the PersistenceExceptionTranslator? interface) and advise all beans marked with the @Repository annotation so that the discovered translators can intercept and apply the appropriate translation on the thrown exceptions. In summary: DAOs can be implemented based on the plain Java Persistence API and annotations, while still being able to benefit from Spring-managed transactions, dependency injection, and transparent exception conversion (if desired) to Spring's custom exception hierarchies.

Migration of existing Hibernate DAOs to annotated

Migration of existing services is fairly easy process to perform. We will start from DAO layer. All modifications we need to perform are located in implementation classes. So all interfaces stay as before. Here is one sample hos classes should look like before and after migration. Before:

public class PnProjectSpaceMetaPropDAOImpl extends AbstractHibernateDAO<PnProjectSpaceMetaProp, Integer> implements IPnProjectSpaceMetaPropDAO {
// class body here... 
}

and this is after migration:

@Transactional
@Repository
public class PnProjectSpaceMetaPropDAOImpl extends AbstractHibernateAnnotatedDAO<PnProjectSpaceMetaProp, Integer> implements IPnProjectSpaceMetaPropDAO {
// class body here... 
}

So there are three things we need to do here:
1. Add annotation @Transactional
2. Add annotation @Repository
3. Change AbstractHibernateDAO to AbstractHibernateAnnotatedDAO.
4. Find appropriate mapping for existing DAO in businessContext-dao.xml and delete it from there.

Please note that AbstractHibernateAnnotatedDAO is new class with exactly the same functionality as AbstractHibernateDAO just annotation based.

Writting new Hibernate DAOs

Writting new DAOs is now easier then before. You need to write one interface for methods in DAO you want to expose and after that you need to write class which will implement that interface with some constraints which are described in previous section for migration. We can avoid usage of interface too but then we do not have freedom to change implementation of the DAO class. Over interface we have applied loosely coupling between them and implementation can be changed when appropirate. Here are the rules for writting new DAO interface:

1. Interface should extend net.project.hibernate.dao.IDAO interface

Rules for the DAO class:
1. Extends AbstractHibernateAnnotatedDAO class
2. Implements appropriate new interface (which extends net.project.hibernate.dao.IDAO)
3. Has annotation @Repository
4. Has annotation @Transactional

Package structure is the same as before. All new interface should be placed in same packege as main DAO interface IDAO and all implementation class are placed one in subpackage impl.

Migration of existing Spring services to annotated Migration of existing services is also fairly simple. Here are the steps you need to perform in order to make existing service class ready for annotated usage:

1. Find appropriate service implementation class and add @Service annotation in the following way:

@Service(value = "pnProjectSpaceMetaPropService")
public class PnProjectSpaceMetaPropServiceImpl implements IPnProjectSpaceMetaPropService {
// class body here... 
}

Value in the @Service annotation is the name of this service and it is unique. Spring context refers to this name allways in your code. This name should be exactly the same as specified in net.project.hibernate.service.impl.ServiceFactoryImpl? class. This class you do not need to change at all. Everything remains the same.

2. Remove String service from XML mappings in bussinessContext-service.xml file.

Writting new Spring services

Writting new Spring services is almost the same as before with that difference that we do not longer need to change any XML configuration file. All necessary changes are made in source code. Here are the things you need to do for every service you create:
1. Create interface for appropriate service where you will define your methods you want to call.
2. Create class which implements this interface.
3. Class must have @Service annotation specified before code.
4. Add abstract method for getting this service to net.project.hibernate.service.ServiceFactory? class.
5. Implement this abstract method in net.project.hibernate.service.impl.ServiceFactoryImpl? class.

Note
This is very important. Name you defined in @Service annotation must be exactly the same as the name of the service in net.project.hibernate.service.impl.ServiceFactoryImpl? class. otherwise Spring will not be able to find this service.

Note
If we apply completely Spring based approach then classes ServiceFactory? and ServiceFactoryImpl? should be removed, but right now we can not remove them because application is not ready to use Spring autowireing so we must have one central space where all those services will be singletons. In a lots of places in application we have returning new class instances as a result, those new classes are not autowired and they do not have references to all appropriate Spring beans, so because of than this is a must. This way until we move entire business logic to Spring services we avoid big code refactoring.