javakaffee

Just another weblog about (web) development technologies like spring, tapestry, jersey, jsf, hibernate and more

November 15, 2008

How to use spring-aop in jersey - added example resource class to the spring-annotations sample

Filed under: development, java, webdev, REST — martin.grotzke @ 8:40 pm

Yesterday I added another example resource to the spring-annotations sample that shows how to use spring-aop with jersey.


The example contains a resource class SpringAopResource that is created by spring (in this case via autodetection/classpath scanning). There’s an example SecurityAdvice defined with a pointcut matching methods annotated with a custom @Secure annotation. The resource method of the SpringAopResource of course is annotated with this annotation, so that the SecurityAdvice will be applied to this resource method. (The SecurityAdvice in our case does plain stupid logging, this should be changed of course :))


So that spring-aop can come into play our resource class needs to be proxied. This raises the question about subresources. Normally they would be created by the resource class, e.g. some UsersResource.getUserResource(String userId) would return some new UserResource(userId). At this point the UserResource could not be proxied by spring - simply impossible. For this we introduced the ResourceContext (I already blogged about this in the context of the initial jersey-spring integration), so that a resource class can fetch an instance of a subresource class from the IoC container.
This is demonstrated by the subresource locator SpringAopResource.getSubResource() which returns an instance of a SpringAopSubResource fetched from the ResourceContext.


The code is shown below - just too little to believe that this should be all :)


The configuration in applicationContext.xml for aspectj-annotation support, and the configuration of the advice bean.

<beans xmlns="..." etc.>
    ...
    <aop:aspectj-autoproxy/>
    <bean id="securityAdvice" class="com.sun.jersey.samples.springannotations.resources.aop.SecurityAdvice" />
    ...
</beans>


The @Secure annotation and the SecurityAdvice:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Secure {

}

@Aspect
public class SecurityAdvice {
    
    private static final Logger LOGGER = Logger.getLogger( SecurityAdvice.class.getName() );
    
    @Before( "@annotation(com.sun.jersey.samples.springannotations.resources.aop.Secure)" )
    public void check( JoinPoint jp ) {
        /* this might get some authentication/authorization info from the request 
         * and throw a WebApplicationException with a response with status 401 (unauthorized)
         * if the request is not authorized.
         */
        final Signature signature = jp.getSignature();
        LOGGER.info( "Authorized execution of " + signature.getDeclaringTypeName() + "." + signature.getName() );
    }
    
}


The resource and subresource classes:

@Path("/spring-aop")
@Component
@Scope("singleton")
public class SpringAopResource {
    
    @Context
    private ResourceContext _resourceContext;

    @Autowired
    private Item _item;

    @GET
    @Secure
    @Produces("application/xml")
    public Item getItem() {
        return _item;
    }
    
    @Path( "subresource" )
    public SpringAopSubResource getSubResource() {
        return _resourceContext.getResource( SpringAopSubResource.class );
    }
    
}


@Component
@Scope("prototype")
public class SpringAopSubResource {

    @Autowired
    @Qualifier("1")
    private Item2 _item;

    @GET
    @Secure
    @Produces("application/xml")
    public Item2 getItem() {
        return _item;
    }
    
}

That’s all. The Item and Item2 classes are just normal beans injected by spring.


You can pull the full example from subversion or browse it online.

August 31, 2008

Added new jersey sample spring-annotations - how to use jersey and spring/annotations

Filed under: development, java, webdev, REST — martin.grotzke @ 5:00 pm

After I have blogged about the jersey-spring integration (jersey-spring integration mostly complete, jersey-spring and changes now available in the jersey trunk / namespace com.sun.ws.rest renamed to com.sun.jersey) and Paul posted an update on the jersey-spring integration in his blog, I finally added a sample that shows how to use jersey and spring (using annotations provided/supported by spring >= 2.5: @Resource and @Autowired).


One resource class in this sample app also shows how users of spring < 2.5 (e.g. spring 2.0) can use annotation based autowiring, this is achieved using the @Autowire annotation provided by jersey-spring (which I already described in this posting).


This sample is especially useful as it will be up to date in the future: it will reflect configuration, namespace or other changes made in jersey, jersey-spring or even spring, so that there’s not the problem that there will be information that is out of date ;-)

August 28, 2008

Jersey and WADL generation - documented!

Filed under: development, java, webdev, REST — martin.grotzke @ 3:06 am

Puh, I just wrote a bunch of text that describes what I implemented related to wadl for jersey, so I just drop a line here. The generated WADL is really cool as it contains javadoc comments from resource classes, and even might include example xml snipplets - for some users of REST APIs xml is easier to read than xsd 8-)


The documentation is not yet complete but covers most of the features:

There’s still documentation missing that shows how to use the maven-wadl-plugin to generate the WADL without a running jersey app. Also some documentation should be written that describes, how the user can define and process his own javadoc tags and turn them to WADL.


Still s.th. to write, but the biggest part should be done - puh :-)

Tags: , , ,

May 18, 2008

Jersey DI - Use custom annotations for dependency injection in your resource classes

Filed under: development, java, webdev, REST — martin.grotzke @ 5:10 pm

In a previous posting I blogged about integration of spring into jersey (and IoC-containers in general), and showed, how the new Inject annotation can be used to inject dependencies from your custom ComponentProvider.

To support this Inject annotation, a feature was introduced into jersey, that allows you to define your own annotations and inject instances to fields annotated with this annotation (in your resource classes). For retrieving instances for the specific annotation you have to add an Injectable for your annotation to the WebApplication. The Injectable is then asked to resolve the value for some field annotated with the specific annotation.

The easiest thing is probably to give an example…

Register the Injectable for some annotation we now call MyAnnotation. This can be done e.g. in your custom ServletContainer, where you have access to the WebApplication:

import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.spi.container.WebApplication;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.sun.jersey.spi.resource.Injectable;

public class MyServletContainer extends ServletContainer {

    @Override
    protected void initiate( ResourceConfig rc, WebApplication wa ) {
        super.initiate( rc, wa );
        
        wa.addInjectable(new Injectable<MyAnnotation, String>() {
            @Override
            public String getInjectableValue(Object o, Field f, MyAnnotation a) {
                return "foo"; // can be retrieved from somewhere
            }

            @Override
            public Class<MyAnnotation> getAnnotationClass() {
                return MyAnnotation.class;
            }
        });
    }
    
    @Target({FIELD, PARAMETER, CONSTRUCTOR })
    @Retention(RUNTIME)
    @Documented
    public static @interface MyAnnotation {

    }

}

In your resource class, you can then annotate fields with MyAnnotation to get the value from the Injectable:

@Path("/")
public class MyResource {
        
    @MyAnnotation String injectedValue;
        
    @GET
    public String get() {
        return injectedValue;
    }                

}

The GET method returns “foo” in this case, but of course you want to retrieve this instance of String from somewhere else.

With this feature you can e.g. create some DAO annotation, annotate the fields in your resource classes referencing DAOs and retrieve instances for these DAOs from your custom ComponentProvider.

How to configure a custom ComponentProvider or your custom ServletContainer see my posting concerning the spring-integration or Paul Sandoz’ blog.

Tags: , , ,

April 28, 2008

jersey-spring and changes now available in the jersey trunk / namespace com.sun.ws.rest renamed to com.sun.jersey

Filed under: development, java, webdev, REST — martin.grotzke @ 11:57 pm

The jersey-spring integration that I described in my previous posting is now merged into the jersey trunk, as well as the changes that were made for better integration of spring and IoC-frameworks in general in the spring-integration branch.

One thing that was changed today is that the namespace of jersey is changed from com.sun.ws.rest to com.sun.jersey, this includes these changes in detail:

  • packages com.sun.ws.rest.api and com.sun.ws.rest.spi are renamed to com.sun.jersey.api and com.sun.jersey.spi
  • configuration namespace of properties/features com.sun.ws.rest.config is renamed to com.sun.jersey.config (e.g. com.sun.ws.rest.config.property.resourceConfigClass is now com.sun.jersey.config.property.resourceConfigClass)
  • the jersey-spring package com.sun.ws.rest.spring is renamed to com.sun.jersey.spring, e.g. the SpringServlet is now com.sun.jersey.spring.SpringServlet
  • the groupId of jersey and jersey-spring are changed from jersey to com.sun.jersey


If you want to use the spring-integration that I blogged about, remember to change the import section of your classes, web.xml and maven pom.xml accordingly.

April 21, 2008

jersey-spring integration mostly complete

Filed under: development, webdev, REST — martin.grotzke @ 1:48 am

Hi,

after jersey 0.7 was released on friday, I just finished writing tests for the spring-integration stuff.
The jersey-spring-integration is based on the SpringComponentProvider blogged by Paul Sandoz and adds some nice things like annotation based injection of IoC-container managed beans (useful for all IoC-frameworks) and annotation based autowiring support even for spring-2.0 users.
Some extensions were made to jersey itself, which are useful for integration of IoC-containers in general (like the mentioned annotation based injection of beans).

The jersey-spring-integration is developed in a separate branch and is going to be part of jersey release 0.8. If you want to use it before jersey 0.8 is there, you can checkout the branch, build jersey, then spring and use the built jars (and configure your web.xml accordingly as described below).

So what does the jersey-spring-integration provide?

  • Integration of spring-2.0 or spring-2.5 with jersey (what else 8-))
  • jersey resources can be managed by spring (pulled from spring’s bean-factory)
  • jersey resources can use spring managed beans via the @Inject annotation that is now provided by jersey (also useful for integration of other IoC-containers)
  • jersey resources can be marked with the @Autowire annotation (that is provided by the jersey-spring-integration), such resources then are created by spring and dependencies injected accordingly
  • jersey resources can use annotation based configuration that comes with spring-2.5
  • jersey now provides an AnnotationInjectable, that can be provided for some annotation, so that the injectable is asked for an instance of a class if a field of some resource is annotated with the specified annotation
  • jersey now provides a ResourceContext, that can be used to get an instance of some subresource from the IoC-container and therfore can use features like e.g. AOP provided by the IoC-container also for subresources

Integration of spring with jersey

After you built both jersey and jersey-spring from the spring-integration branch and configured them as dependencies for your project, you only have to register the SpringServlet in your web.xml (I’m asuming that you have spring already configured therein):

<servlet>
    <servlet-name>Jersey Spring</servlet-name>
    <servlet-class>com.sun.ws.rest.spring.SpringServlet</servlet-class>
    <init-param>
        <param-name>com.sun.ws.rest.config.property.resourceConfigClass</param-name>
        <param-value>com.sun.ws.rest.api.core.PackagesResourceConfig</param-value>
    </init-param>
    <init-param>
        <param-name>com.sun.ws.rest.config.property.packages</param-name>
        <param-value>your.resource.package</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>Jersey Spring</servlet-name>
    <url-pattern>/api/*</url-pattern>
</servlet-mapping>

Use resources managed by spring

If you want to get your resource created by spring you simply have to define it in your applicationContext.xml. Only bear in mind, that the scope in your applicationContext.xml matches the scope of your resource class (jersey-Singleton == spring-singleton, jersey-PerRequest == spring-prototype).


For example you might have this resource:

@Path( "springifiedsingleton" )
@Singleton
public class SpringifiedSingletonRootResource {

    private String _value;

    public SpringifiedSingletonRootResource String value ) {
        _value = value;
    }
    
    @GET
    @ProduceMime("text/plain")
    public String getValue() {
        return _value;
    }
    
}

Define the resource in your applicationContext.xml:

<bean id="singletonRootResource" class="spring.examples.SpringifiedSingletonRootResource"
    scope="singleton">
    <constructor-arg value="foo" />
</bean>

That’s it, now your resources will be provided by spring.


If you don’t want to define each new resource in your applicationContext, but simply want to use your existing spring managed beans/services, you can use the following approach using the @Inject annotation.

@Inject spring managed beans/services into your resources

The @Inject annotation is now provided by jersey and is useful for integration of several IoC-containers, not only for spring. A field that is annotated with @Inject is initialized with an instance (of the fields type), that is pulled from the ComponentProvider, and in this case from spring.


Just to have an example:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ProduceMime;

import com.sun.ws.rest.spi.resource.Inject;
import com.sun.ws.rest.spi.resource.Singleton;

@Path( "injectingsingleton" )
@Singleton
public class InjectingSingletonRootResource {

    @Inject
    private SomeService _someService;
    
    @GET
    @ProduceMime("text/plain")
    public String getValue() {
        return _someService.getSomething();
    }
    
}

Your applicationContext.xml now only has to contain the bean definition for your SomeService


The instance of SomeService is retrieved from spring by its type, so if there are more than one bean definitions for SomeService the injection is not going to work. If this would be a requirement we should use another annotation that allows to set the bean-name (like e.g. @Resource).

Use @Autowire to autowire your resources with spring-2.0

If you want to get your resource class autowired, you can annotate it with @Autowire, which is provided by the jersey-spring-integration package. Resource classes annotated with @Autowire are created by spring (also spring BeanPostProcessors are applied). The @Autowire also allows to specify the AutowireMode (one of AUTODETECT, BY_NAME, BY_TYPE, CONSTRUCTOR, see AutowireCapableBeanFactory) and whether to perform a dependency check for objects (which is not applicable to autowiring a constructor, thus ignored there).


The example is really simple:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ProduceMime;

import com.sun.ws.rest.spi.resource.Inject;
import com.sun.ws.rest.spi.resource.Singleton;
import com.sun.ws.rest.spring.annotations.Autowire;

@Path( "injectingsingleton" )
@Singleton
@Autowire
public class AutowiringSingletonRootResource {

    @Inject
    private SomeService _someService;
    
    @GET
    @ProduceMime("text/plain")
    public String getValue() {
        return _someService.getSomething();
    }
    
}

Your applicationContext.xml still has to contain the bean definition for your SomeService. As this AutowiringSingletonRootResource is created by spring it can make use of all spring features, but you don’t have to define each resource in your applicationContext.xml.

Retrieve your subresources from the ResourceContext

If you have your root resource classes created by spring, you’re perhaps happy that you can use features provided by spring like AOP, transaction-handling or caching. But what to do when your root resource must return some sub-resource (sub-resource locator), but this sub-resource shall also be created by spring? Until now the sub-resource was created using new() and therefore it could not be created by spring and therefore was not proxied - no AOP, transaction-handling or caching…


This can now be achieved using the ResourceContext, that can be used to retrieve an instance of some sub-resource:

import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;

import spring.examples.UserService.User;

import com.sun.ws.rest.api.NotFoundException;
import com.sun.ws.rest.api.core.ResourceContext;
import com.sun.ws.rest.spi.resource.Inject;
import com.sun.ws.rest.spi.resource.Singleton;

@Path( "users" )
@Singleton
public class UsersResource {

    private final UserService _userService;
    
    @Context
    private ResourceContext _resourceContext;
    
    public UsersResource( UserService userService ) {
        _userService = userService;
    }
    
    @Path( "{username}" )
    public UserResource getValue( @PathParam( "username" ) String username ) {
        final User user = _userService.findByUsername( username );
        if ( user == null ) {
            throw new NotFoundException( "User " + username + " not found!" );
        }
        final UserResource result = _resourceContext.getResource( UserResource.class );
        result.setUser( user );
        return result;
    }
    
}

In this example, I asume that both the UsersResource and the UserResource are defined in your applicationContext.xml (and the UserService of course also) and therefore created by spring, the ResourceContext is injected by jersey.

Using spring-2.5 features

Just to mention, it’s also possible to use annotation driven bean configuration as it came with spring-2.5. This is an example for a resource class, also notice that both scopes must match:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.ProduceMime;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import com.sun.ws.rest.spi.resource.PerRequest;

@Path( "injectingsingleton" )
@PerRequest
@Component
@Scope( "prototype" )
public class AnnotatedPerRequestResource {

    @Autowired
    private SomeService _someService;
    
    @GET
    @ProduceMime("text/plain")
    public String getValue() {
        return _someService.getSomething();
    }
    
}

That spring discovers this resource class, the applicationContext.xml must contain the , as it’s described in the spring documentation.

March 8, 2008

Jersey is fun - exploring RESTful webservices - subtitle: @Springify your resources

Filed under: development, java, webdev, REST — martin.grotzke @ 6:14 am

Hi,

my last post is nearly years ago and of course I wanted to write about this and that. But right now I had so much fun that I have to share this.

Fun with… jersey, the reference implementation of the upcoming jsr311 that specifies how to build RESTful web services in java.

Now I was just playing around with jersey and had a look at the sources and found out how easy it is to define an annotation and inject spring beans based on this annotation. The spring integration itself is described here, it shows a SpringServlet that loads beans based on the class from springs application context.

Now the part that made me happy:

First you define an annotation @SpringBean:


@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface SpringBean {

}

Then, in your SpringServlet you implement a base SpringInjectable for springified beans (of course you can make this public, but’s it’s not that important, just for conveniance…):


    private static abstract class SpringInjectable<V> extends Injectable<SpringBean, V> {
        public Class<SpringBean> getAnnotationClass() {
            return SpringBean.class;
        }
    }

and finally register the spring beans that you want to publish to your resource classes within a method like this (still in the SpringServlet):


    protected void initiate(ResourceConfig rc, WebApplication wa) {
        // get spring's applicationContext
        ApplicationContext springContext = WebApplicationContextUtils.
                getRequiredWebApplicationContext(getServletContext());
        // register your spring beans - this is new
        addInjectables( wa, springContext, SpringService1.class, SpringService2.class ); 
        // now let jersey do the rest
        wa.initiate(rc, new SpringComponentProvider(springContext));
    }

    private void addInjectables( WebApplication wa, final ApplicationContext springContext, Class<?> ... injectables ) {
        for ( final Class<?> injectable : injectables ) {
            wa.addInjectable( injectable, new SpringInjectable() {

                @Override
                public Object getInjectableValue( Annotation a ) {
                    return springContext.getBean( getBeanName( injectable, springContext ) );
                }
                
            });
            
        }
    }

After this rather heavy setup phase you can start to inject your spring beans using the @SpringBean annotation:


public class SomeResource {

    private @SpringBean SomeService _service;

    ...

}

Fairly easy, isn’t it? Just define an annotation and define how to resolve beans to that - really straightforward!

Of course, you’re right, the shortcoming here is that you must define (know) which spring beans shall be provided to your resources - consider this to be a security feature ;)

Finally, it was playing around, looking here and there, exploring, and finding out how easy things are - really nice!

And not to forget - jersey 0.6 was released today, as you may also read here.

Now I’m going back to jersey,
cheers,
Martin

Powered by WordPress