users@jersey.java.net

Re: Injecting spring beans annotation based

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 19 Mar 2008 11:16:45 +0100

Martin Grotzke wrote:
> Hi,
>
> On Mon, 2008-03-17 at 14:45 +0100, Paul Sandoz wrote:
>> Why can't the registered Spring beans be injected into other things
>> using Spring-based mechanisms? I know that Guice has the @Injected
>> annotation, does Spring have a similar annotation? you can probably wire
>> things up in the app config but it is not as nice as an annotation.
> I think in spring 2.5 annotation-based DI has been improved
> significantly. Though, we're still using spring 2.0 and do not use
> spring annotations for wiring up beans, so I don't know what are all the
> possibilities provided (just having a look at the spring docs shows that
> e.g. the javax.annotation.Resource is supported).
>

OK. I thought Spring provides (or was going to provide) support for EE5.
Spring or WebBeans (preferably WebBeans) will be the way we support
EE5/EE6 stuff for Jersey so we don't have to implement it ourselves.


> Creating the @SpringBean to me seemed to be a nice way to keep resources
> out of the applicationContext.xml, but to be able to have them
> configured with services (spring beans).
>

Agreed.


> In tapestry5 (T5, [1]) we have the same situation - there are page
> classes that can use the standard @Inject annotation provided by T5,
> that can inject T5 configured beans/services or even spring beans
> (having the tapestry-spring integration on board).
> Resource classes then are the same level of abstraction compared to page
> classes and would also be able to inject service dependencies.
>
>
>> The Injectable interface was really designed for "constant" Java types
>> rather than application defined types (and minimal way of performing
>> injection of a fixed set of common stuff without depending on an IoC
>> container). So i think it best to see if there is Spring-way before
>> making changes around support of this interface.
> Alright. Though, it's really nice and easy and therefore was somehow an
> invitation to use / play with it ;)
>

Great, it was a really nice surprise to see you doing that :-) i am glad
it works for you.

If we cannot find an alternative Spring way that is acceptable and the
current approach starts to cause you pain we can look into changing the
injectable behvaiour to support what you require.

A question: Is Tapestry a bit like Wicket? Is it possible to merge
Tapestry and Jersey together is anyway? for example, i am thinking if
there is a connection to the basic-MVC stuff we put into Jersey, or if a
resource class can also be a page?

Paul.

>
> Cheers,
> Martin
>
>
> [1] http://tapestry.apache.org/tapestry5/
>
>
>> Paul.
>>
>> Martin Grotzke wrote:
>>> 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
>>>
>>>

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109