Matthias Wessendorf's Weblog

Using CDI Scopes with Spring 3

Advertisements

With the advent of Spring 3 the framework now supports the Java Injection standard (JSR 330). However, unfortunately, they do not support the scoping, which is introduced in Java EE 6,through the CDI specification (JSR 299).

Now the big difference between a JSF “managed bean” in Java EE 6 and Spring is that they basically use a different scoping (JavaEE vs. Spring)!

However, the remaining parts are exactly the same, in both worlds:

During our JAX 2010, Lars Röwekamp and I showed how enable the Spring Framework to understand the CDI scopes, such as @RequestScoped or @SessionScoped.

Before that, I spoke to Juergen Hoeller on the JAX conference, and he explained me the underlying mechanism and how something like that could be easily done!

The Spring Framework uses a ScopeMetadataResolver to resolve the SPRING-based scopes of the bean definitions. To actually enable the CDI scopes I “decorated” their default implementation, the AnnotationScopeMetadataResolver class:


public class CdiScopeMetadataResolver
extends AnnotationScopeMetadataResolver
{
 @Override
 public ScopeMetadata resolveScopeMetadata(BeanDefinition definition)
 {
 ScopeMetadata metadata = new ScopeMetadata();
 if (definition instanceof AnnotatedBeanDefinition)
 {
 AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
 Set<String> annotationTypes = annDef.getMetadata().getAnnotationTypes();

 if (annotationTypes.contains(
 javax.enterprise.context.RequestScoped.class.getName())
 )
 {
 metadata.setScopeName("request");
 }
 else if (annotationTypes.contains(
 javax.enterprise.context.SessionScoped.class.getName())
 )
 {
 metadata.setScopeName("session");
 }

...
//more...
//
 else
 {
 // do the regular Spring stuff..
 return super.resolveScopeMetadata(definition);
 }
 }
 return metadata;
 }
}

The CdiScopeMetadataResolver class scans the actual Spring beans and checks if the CDI
scope annotations are declared. If they are present we simply map them to their corresponding
Spring scopes!

So the trick is that you annotate them with CDI, but under the hood they are Spring scopes!

Now in your Spring configuration you simply enable it like:


...
 <context:component-scan
base-package="my.packages..."
scope-resolver="...CdiScopeMetadataResolver" />
...

Now you are able to define your Spring/JSF beans with 100% JavaEE-based annotations.

UPDATE: I published the code of this class to github.

Enjoy!

Advertisements