Stripes

Support Spring's @Autowired annotation for marking fields/methods for dependency injection

Details

  • Type: Improvement Improvement
  • Status: Closed Closed
  • Priority: Trivial Trivial
  • Resolution: Duplicate
  • Affects Version/s: Release 1.4.3
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

It'd be nice if we could use the @Autowired annotation that was recently added in Spring 2.5 in place of the @SpringBean annotation. Dependency injection would then would be consistent with a spring-managed service tier.

Obviously this isn't a big deal and I've marked it as trivial.

  1. GuiceInterceptor.java
    07/Mar/08 8:51 AM
    1 kB
    Gregg Bolinger
  2. Spring25Interceptor.java
    12/Mar/08 8:59 PM
    4 kB
    Christian Nelson
  3. SpringInterceptor.java
    07/Mar/08 2:21 AM
    1 kB
    Christian Nelson

Activity

Hide
Levi Hoogenberg added a comment - 03/Mar/08 2:00 AM

Even better (IMO) would be to use a single annotation for Spring, Guice, etc. - @Resource (http://java.sun.com/javase/6/docs/api/javax/annotation/Resource.html), for instance.

Show
Levi Hoogenberg added a comment - 03/Mar/08 2:00 AM Even better (IMO) would be to use a single annotation for Spring, Guice, etc. - @Resource (http://java.sun.com/javase/6/docs/api/javax/annotation/Resource.html), for instance.
Hide
Christian Nelson added a comment - 03/Mar/08 4:16 PM

I don't really see the benefit to using @Resource. To me it's marginally better than @SpringBean in that it's a non-Spring annotation. And I don't see the benefit of having one annotation that works for either Spring or Guice. Especially since @Resource is somewhat overloaded in that it does different things in different environments.

My original point was that I see a benefit to using the same dependency-injection annotation(s) across all of the layers of an application. @Autowired in the service tier and @Resource in the web tier is no better than @Autowired (service) and @SpringBean (web), IMHO. @Autowired in both the web and services layers makes things just a little more consistent and clean.

Of course this is made a little more complicated because Spring has its own support for the standard @Resource annotation. Ideally, I would like to see Stripes' Spring support handle @Autowired (http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation), @Resource (http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-resource-annotation) and @Qualifier (http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-qualifier-annotation) exactly like Spring handles them.

I'm not sure what Guice support there is for Stripes, but my opinion is that any Stripes/Guice support should use the standard Guice annotations. Spring users stick with the annotations and behavior they're used to and Guice users stick to what they're used to.

Show
Christian Nelson added a comment - 03/Mar/08 4:16 PM I don't really see the benefit to using @Resource. To me it's marginally better than @SpringBean in that it's a non-Spring annotation. And I don't see the benefit of having one annotation that works for either Spring or Guice. Especially since @Resource is somewhat overloaded in that it does different things in different environments. My original point was that I see a benefit to using the same dependency-injection annotation(s) across all of the layers of an application. @Autowired in the service tier and @Resource in the web tier is no better than @Autowired (service) and @SpringBean (web), IMHO. @Autowired in both the web and services layers makes things just a little more consistent and clean. Of course this is made a little more complicated because Spring has its own support for the standard @Resource annotation. Ideally, I would like to see Stripes' Spring support handle @Autowired (http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation), @Resource (http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-resource-annotation) and @Qualifier (http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-qualifier-annotation) exactly like Spring handles them. I'm not sure what Guice support there is for Stripes, but my opinion is that any Stripes/Guice support should use the standard Guice annotations. Spring users stick with the annotations and behavior they're used to and Guice users stick to what they're used to.
Hide
Gregg Bolinger added a comment - 03/Mar/08 4:41 PM

I'd vote for @Resource however since it is already part of the JVM it would be difficult to customize it to work for Stripes purposes. I don't think using @Autowired is a good idea either because it is Spring specific. I think if Stripes were to add DI capabilities for multiple API's in a generic fashion the best thing to do is create its own annotation. Something like @Inject (I think Tim mentioned this in IRC).

Show
Gregg Bolinger added a comment - 03/Mar/08 4:41 PM I'd vote for @Resource however since it is already part of the JVM it would be difficult to customize it to work for Stripes purposes. I don't think using @Autowired is a good idea either because it is Spring specific. I think if Stripes were to add DI capabilities for multiple API's in a generic fashion the best thing to do is create its own annotation. Something like @Inject (I think Tim mentioned this in IRC).
Hide
Christian Nelson added a comment - 03/Mar/08 5:21 PM

No offense intended, but I disagree. And just for clarification, at no point was I suggesting that there be a single Stripes-specific generic dependency injection annotation which works across multiple DI frameworks.

Let's see if I can express why I think creating a unified Stripes-specific DI annotation is a bad idea...

Unless Stripes is aiming to be an IoC container (very doubtful), I think it should use the DI annotations and semantics of the DI frameworks providing IoC functionality. Adding yet another way to mark something for dependency injection just complicates the domain. Stripes is a great, lightweight MVC and should keep its focus on doing just that. Let the DI frameworks define the syntax and semantics since its their specialty.

Spring and Guice support are obviously very desirable and should be available. What does support mean exactly? In my mind, Spring "support" means "support integration between Stripes' actions and Spring managed beans (services) using Spring's syntax and semantics", it does not mean "integrate with Spring managed beans using a custom, non-Spring syntax." (Obviously the same sentence can be modified for Guice support).

As a developer, having a generic annotation doesn't really make my life easier, in fact it's adding some complexity in the form of another annotation for dependency injection.

Having a single Stripes-specific annotation isn't going to make implementation any easier. In fact, i think it will be more difficult because of the scenario where multiple DI framework are in play. I know it's a bad idea, but it does happen. For example, worked on a project where we were migrating from Guice to Spring and for some time, both were active. Being explicit about where a dependency comes from (Guice, Spring, etc) by using the native syntax of the DI framework makes this easier to handle. Even ignoring this corner case scenario, it's not going to be easier to implement a generic mechanism.

Lastly, using the generic annotation we lose the benefit of consistency throughout an application, from the web tier back through the services.

In the end, I think we should support Guice and Spring both, but support them using their native annotations.

Show
Christian Nelson added a comment - 03/Mar/08 5:21 PM No offense intended, but I disagree. And just for clarification, at no point was I suggesting that there be a single Stripes-specific generic dependency injection annotation which works across multiple DI frameworks. Let's see if I can express why I think creating a unified Stripes-specific DI annotation is a bad idea... Unless Stripes is aiming to be an IoC container (very doubtful), I think it should use the DI annotations and semantics of the DI frameworks providing IoC functionality. Adding yet another way to mark something for dependency injection just complicates the domain. Stripes is a great, lightweight MVC and should keep its focus on doing just that. Let the DI frameworks define the syntax and semantics since its their specialty. Spring and Guice support are obviously very desirable and should be available. What does support mean exactly? In my mind, Spring "support" means "support integration between Stripes' actions and Spring managed beans (services) using Spring's syntax and semantics", it does not mean "integrate with Spring managed beans using a custom, non-Spring syntax." (Obviously the same sentence can be modified for Guice support). As a developer, having a generic annotation doesn't really make my life easier, in fact it's adding some complexity in the form of another annotation for dependency injection. Having a single Stripes-specific annotation isn't going to make implementation any easier. In fact, i think it will be more difficult because of the scenario where multiple DI framework are in play. I know it's a bad idea, but it does happen. For example, worked on a project where we were migrating from Guice to Spring and for some time, both were active. Being explicit about where a dependency comes from (Guice, Spring, etc) by using the native syntax of the DI framework makes this easier to handle. Even ignoring this corner case scenario, it's not going to be easier to implement a generic mechanism. Lastly, using the generic annotation we lose the benefit of consistency throughout an application, from the web tier back through the services. In the end, I think we should support Guice and Spring both, but support them using their native annotations.
Hide
Gregg Bolinger added a comment - 03/Mar/08 5:39 PM

I don't get offended that easily. And I disagree with most of what you said. HA! So no offense.

I suppose my biggest problem with using DI API annotations (@Autowired, etc) is that you place a dependency on the 3rd party API and its progression, success, failure. Right now there is one reason why Stripes couldn't use @Autowired. @Autowired only takes a boolean required attribute. Stripes checks a method for an annotation. If it is @SpringBean it then looks for a value and if the value exists it tries to fine that bean in the Spring context and call that method to set the bean. If no value exists it tries to determine the bean name from the method name. Since @Autowired doesn't support the value string you are limited in how you can define your methods.

But what about the future? What if Stripes decides it needs/wants more options available during the injection? Worse yet, what if Spring changes the @Autowired definition? Example: Spring decides to include a value. But since it already has required it would have to look like this: @Autowired(bean="someBean", required=true|false). At this point, Stripes' API has to change. Its important that Stripes is not dependent on 3rd party API's in this regards. The same scenerio can be applied to Guice as well. Guice changes their annotations and Stripes is back in their code updating to support it.

And you can easily add support for multiple DI API's using a single Stripes specific annotation.

@Inject(lib="spring | guice")

Or something like that.

Show
Gregg Bolinger added a comment - 03/Mar/08 5:39 PM I don't get offended that easily. And I disagree with most of what you said. HA! So no offense. I suppose my biggest problem with using DI API annotations (@Autowired, etc) is that you place a dependency on the 3rd party API and its progression, success, failure. Right now there is one reason why Stripes couldn't use @Autowired. @Autowired only takes a boolean required attribute. Stripes checks a method for an annotation. If it is @SpringBean it then looks for a value and if the value exists it tries to fine that bean in the Spring context and call that method to set the bean. If no value exists it tries to determine the bean name from the method name. Since @Autowired doesn't support the value string you are limited in how you can define your methods. But what about the future? What if Stripes decides it needs/wants more options available during the injection? Worse yet, what if Spring changes the @Autowired definition? Example: Spring decides to include a value. But since it already has required it would have to look like this: @Autowired(bean="someBean", required=true|false). At this point, Stripes' API has to change. Its important that Stripes is not dependent on 3rd party API's in this regards. The same scenerio can be applied to Guice as well. Guice changes their annotations and Stripes is back in their code updating to support it. And you can easily add support for multiple DI API's using a single Stripes specific annotation. @Inject(lib="spring | guice") Or something like that.
Hide
Christian Nelson added a comment - 07/Mar/08 2:19 AM

Gregg, I'm getting the feeling we're not really talking about the same thing.

In my proposition, no core part of Stripes would be tied to Spring. I'm only talking about providing Spring integration for dependency injection using Spring's native annotations. Only people who wanted Spring support would use these annotations and would be required to depend on Spring (they would already have a dependency on Spring). If someone didn't want dependency injection, there would be no dependency on Spring.

The attached file (SpringInterceptor.java) is a complete Stripes SpringInterceptor implementation which allows for the use of Spring 2.5's @Autowired, @Qualifier, and the Java @Resource on Stripes action beans. It's wired up exactly like the SpringInterceptor which ships with Stripes. As far as I can tell, it is quite a bit smaller (lines of code) than the existing Spring integration and it provides the same exact syntax and semantics that Spring provides. If a user wants Spring support, it's hard to argue that they would want syntax and semantics of something other than Spring.

Note that in this code sample, no part of Stripes would have to change if Spring changes its annotations. And for the record, Spring has retained an almost perfect record of backwards compatibility since v1.0 many years ago. So I don't buy the "isolating stripes from changes in spring over time" argument.

I'm confident that I could create an equally simple GuiceInterceptor for those users who want Guice integration. And then, those who want Guice integration would be able to use the syntax and semantics of what they are used to.

"What if Stripes decides it needs/wants more options available during the injection?" Like what? What would Stripes want to add to its Spring Integration support that Spring itself does not provide? Better yet, how would Stripes be able to provide more dependency injection functionality than the underlying dependency injection container? If a user wanted something that Spring couldn't provide itself in terms of dependency injection, then the user would look for a different DI framework, not expect their lightweight MVC to augment.

Anyones else following this have an opinion?

Show
Christian Nelson added a comment - 07/Mar/08 2:19 AM Gregg, I'm getting the feeling we're not really talking about the same thing. In my proposition, no core part of Stripes would be tied to Spring. I'm only talking about providing Spring integration for dependency injection using Spring's native annotations. Only people who wanted Spring support would use these annotations and would be required to depend on Spring (they would already have a dependency on Spring). If someone didn't want dependency injection, there would be no dependency on Spring. The attached file (SpringInterceptor.java) is a complete Stripes SpringInterceptor implementation which allows for the use of Spring 2.5's @Autowired, @Qualifier, and the Java @Resource on Stripes action beans. It's wired up exactly like the SpringInterceptor which ships with Stripes. As far as I can tell, it is quite a bit smaller (lines of code) than the existing Spring integration and it provides the same exact syntax and semantics that Spring provides. If a user wants Spring support, it's hard to argue that they would want syntax and semantics of something other than Spring. Note that in this code sample, no part of Stripes would have to change if Spring changes its annotations. And for the record, Spring has retained an almost perfect record of backwards compatibility since v1.0 many years ago. So I don't buy the "isolating stripes from changes in spring over time" argument. I'm confident that I could create an equally simple GuiceInterceptor for those users who want Guice integration. And then, those who want Guice integration would be able to use the syntax and semantics of what they are used to. "What if Stripes decides it needs/wants more options available during the injection?" Like what? What would Stripes want to add to its Spring Integration support that Spring itself does not provide? Better yet, how would Stripes be able to provide more dependency injection functionality than the underlying dependency injection container? If a user wanted something that Spring couldn't provide itself in terms of dependency injection, then the user would look for a different DI framework, not expect their lightweight MVC to augment. Anyones else following this have an opinion?
Hide
Christian Nelson added a comment - 07/Mar/08 2:21 AM

Fully functional SpringInterceptor which allows for use of @Autowired, @Qualifier, and @Resource dependency injection in action beans.

Show
Christian Nelson added a comment - 07/Mar/08 2:21 AM Fully functional SpringInterceptor which allows for use of @Autowired, @Qualifier, and @Resource dependency injection in action beans.
Hide
Gregg Bolinger added a comment - 07/Mar/08 8:42 AM

Christian, I'm slowly coming around to this. I did write a GuiceInterceptor that was just as simple that did the exact same thing your SpringInterceptor is doing. I posted it to the mailing list so you make look for it.

With the GuiceInterceptor I wrote it required the use of 100% annotations. It did not allow for an AbstractModule implementation. Does the Spring interceptor you wrote expect the same thing? Does it require the use of annotations throughout or would it still use XML wired beans as well? For example, in my GuiceInterceptor this is expected in a Stripes ActionBean

@Inject
public void setSomething(Something something) { }

I'm assuming this would be required for Spring?

@Autowired
public void setSomething(Something something) { }

??

Show
Gregg Bolinger added a comment - 07/Mar/08 8:42 AM Christian, I'm slowly coming around to this. I did write a GuiceInterceptor that was just as simple that did the exact same thing your SpringInterceptor is doing. I posted it to the mailing list so you make look for it. With the GuiceInterceptor I wrote it required the use of 100% annotations. It did not allow for an AbstractModule implementation. Does the Spring interceptor you wrote expect the same thing? Does it require the use of annotations throughout or would it still use XML wired beans as well? For example, in my GuiceInterceptor this is expected in a Stripes ActionBean @Inject public void setSomething(Something something) { } I'm assuming this would be required for Spring? @Autowired public void setSomething(Something something) { } ??
Hide
Christian Nelson added a comment - 07/Mar/08 10:21 AM

The interceptor I wrote will lookup beans from the spring application context and find them regardless of how they were defined. For example, in my sample application where, I create spring beans via xml (ye ole fashioned way) as well as through spring's component-scan feature:

"Spring 2.5 introduces support component scanning: autodetecting annotated components in the classpath. Typically, such component classes will be annotated with stereotypes such as @Component, @Repository, @Service, @Controller. Depending on the application context configuration, such component classes will be autodetected and turned into Spring bean definitions, not requiring explicit configuration for each such bean. Annotation-driven bean configuration is discussed in Section 3.12.1, "@Component and further stereotype annotations"."

Once the beans are in the context it doesn't matter much how they got there. It could be through spring's JavaConfig, component-scan, xml, or any combination of those or any new mechanism that comes along.

@Autowired (etc) can be applied to fields or methods. It normally can be applied to constructors, but that won't work in this case since Stripes is doing the instantiation, not Spring.

Potential Caveats:
1) What I wrote will only work with Spring 2.5 and later. I don't see this as too big a deal because if a developer or organization is using Stripes, then they probably have a high-degree of technical freedom. Also, Spring 2.5.2 is out and has had time for stabilization and adoption. 2.5 is completely backwards with 2.0 so there's no (good) reason for developers not to upgrade.
2) While I think the injection process is already optimized, I think it's worth doing a little profiling to make sure action beans can be created and injected very quickly.

I'm heading off to Montana tomorrow and will be off the grid most of the next week. I'd be happy to document the code I wrote, adds some tests and error checking and send the updated version when I return.

Show
Christian Nelson added a comment - 07/Mar/08 10:21 AM The interceptor I wrote will lookup beans from the spring application context and find them regardless of how they were defined. For example, in my sample application where, I create spring beans via xml (ye ole fashioned way) as well as through spring's component-scan feature: "Spring 2.5 introduces support component scanning: autodetecting annotated components in the classpath. Typically, such component classes will be annotated with stereotypes such as @Component, @Repository, @Service, @Controller. Depending on the application context configuration, such component classes will be autodetected and turned into Spring bean definitions, not requiring explicit configuration for each such bean. Annotation-driven bean configuration is discussed in Section 3.12.1, "@Component and further stereotype annotations"." Once the beans are in the context it doesn't matter much how they got there. It could be through spring's JavaConfig, component-scan, xml, or any combination of those or any new mechanism that comes along. @Autowired (etc) can be applied to fields or methods. It normally can be applied to constructors, but that won't work in this case since Stripes is doing the instantiation, not Spring. Potential Caveats: 1) What I wrote will only work with Spring 2.5 and later. I don't see this as too big a deal because if a developer or organization is using Stripes, then they probably have a high-degree of technical freedom. Also, Spring 2.5.2 is out and has had time for stabilization and adoption. 2.5 is completely backwards with 2.0 so there's no (good) reason for developers not to upgrade. 2) While I think the injection process is already optimized, I think it's worth doing a little profiling to make sure action beans can be created and injected very quickly. I'm heading off to Montana tomorrow and will be off the grid most of the next week. I'd be happy to document the code I wrote, adds some tests and error checking and send the updated version when I return.
Hide
Gérald Quintana added a comment - 07/Mar/08 10:34 AM

I think there are 2 things under the current Spring bean injection:
1) The resolution/creation/providing of the bean/dependency
2) The injection of the bean/dependency in the action

The part 1) depends on annotation (and property type?):
@SpringBean, @AutoWired... --> Spring bean provider
@Inject --> Guice bean provider
@EJB --> EJBean provider
@PersistenceContext --> Entity manager provider
...

This part 1) could be customizable and extensible.

The part 2) is common to all bean providers and could be share across

Show
Gérald Quintana added a comment - 07/Mar/08 10:34 AM I think there are 2 things under the current Spring bean injection: 1) The resolution/creation/providing of the bean/dependency 2) The injection of the bean/dependency in the action The part 1) depends on annotation (and property type?): @SpringBean, @AutoWired... --> Spring bean provider @Inject --> Guice bean provider @EJB --> EJBean provider @PersistenceContext --> Entity manager provider ... This part 1) could be customizable and extensible. The part 2) is common to all bean providers and could be share across
Hide
Christian Nelson added a comment - 12/Mar/08 8:59 PM

I've touched up my Spring 2.5 Interceptor by adding documentation and an example. I've also renamed it to Spring25Interceptor and replicated the same logging as the existing SpringInterceptor. See Spring25Interceptor.java.

Interestingly, I found this comment on Spring's AutowireCapableBeanFactory, the heart of my interceptor implementation:

"Integration code for other frameworks can leverage this interface to wire and populate existing bean instances that Spring does not control the lifecycle of. This is particularly useful for WebWork Actions and Tapestry Page objects, for example."

Show
Christian Nelson added a comment - 12/Mar/08 8:59 PM I've touched up my Spring 2.5 Interceptor by adding documentation and an example. I've also renamed it to Spring25Interceptor and replicated the same logging as the existing SpringInterceptor. See Spring25Interceptor.java. Interestingly, I found this comment on Spring's AutowireCapableBeanFactory, the heart of my interceptor implementation: "Integration code for other frameworks can leverage this interface to wire and populate existing bean instances that Spring does not control the lifecycle of. This is particularly useful for WebWork Actions and Tapestry Page objects, for example."
Hide
Chris Herron added a comment - 08/Dec/08 9:43 AM

Stripes 1.5.1 is going to have an ObjectFactory facility which would allow us to make ActionBeans actual Spring beans.
I have built a SpringObjectFactory - its available at the Stripes Stuff project (http://www.stripes-stuff.org/). My goal was to be able to use Spring transactions and security - I did not focus on autowiring, but it should work.

BTW I think that Patrick Lightbody has a Guice ObjectFactory in the works also.

Show
Chris Herron added a comment - 08/Dec/08 9:43 AM Stripes 1.5.1 is going to have an ObjectFactory facility which would allow us to make ActionBeans actual Spring beans. I have built a SpringObjectFactory - its available at the Stripes Stuff project (http://www.stripes-stuff.org/). My goal was to be able to use Spring transactions and security - I did not focus on autowiring, but it should work. BTW I think that Patrick Lightbody has a Guice ObjectFactory in the works also.
Hide
Ben Gunter added a comment - 19/Dec/08 9:59 PM

As Chris pointed out, release 1.5.1 will provide facilities to accomplish this sort of thing. I'm closing as a duplicate of STS-614.

Show
Ben Gunter added a comment - 19/Dec/08 9:59 PM As Chris pointed out, release 1.5.1 will provide facilities to accomplish this sort of thing. I'm closing as a duplicate of STS-614.

People

Vote (1)
Watch (1)

Dates

  • Created:
    02/Mar/08 10:53 PM
    Updated:
    04/Jan/11 3:03 PM
    Resolved:
    19/Dec/08 9:59 PM