users@jersey.java.net

Injecting spring beans annotation based

From: Martin Grotzke <martin.grotzke_at_javakaffee.de>
Date: Sat, 08 Mar 2008 04:32:22 +0100

Hi,

I'm just playing around with jersey - it's very much fun! - and found
the Injectable interface when I had a look into the the ServletContainer
class. There is shown how HttpServletRequest etc. are made injectable,
very nice and very easy!

It's as easy to do this with spring beans - once one has the
SpringServlet configured ([1]). Just define an annotation @SpringBean:

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

}

then, in your SpringServlet implement a base SpringInjectable for
springified beans:

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

and finally register the spring beans you want to publish to your
resources 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 ) );
                }
                
            });
            
        }
    }

This is very easy, just define an annotation and bind your source to it
- really straightforward!

Though, I really like inversion of control with the idea behind, that a
class declares it's dependencies e.g. in a constructor, and these are
the things where you have to know how this stuff works and what it does
require, well...

There's one shortcoming here - one has to know the classes that shall be
made available to resources / for injection. It would be also nice to
have some injectable provider that would be asked if there's an unknown
type. Do you think this is desired?

Cheers,
Martin


[1] http://blogs.sun.com/sandoz/entry/integrating_jersey_and_spring_take