Stripes

SpringInterceptorSupport doesn't wire JPA @ PersistenceContext annotation

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Not a Bug
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

Spring interceptor uses SpringHelper#injectBeans method which has custom implementation of bean injection. This implementation ignores standard JPA annoation supported by Spring.

Using only Spring, this annotation works fine:

AutowireCapableBeanFactory beanFactory = springContext.getAutowireCapableBeanFactory();
beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);

and is implemented by Spring Post processor
PersistenceAnnotationBeanPostProcessor#private InjectionMetadata findPersistenceMetadata(final Class clazz)

@SpringBean seems to be duplicate responsibility of @java.annotation.Resource supported also by Spring. It provides capabiltiy of bean injection for private fields (BTW not very useful during unit tests)

Activity

Hide
Chris Herron added a comment - 25/Jan/09 8:59 AM

This is not a bug. @SpringBean doesn't promise anything more than retrieving a Spring bean by its name. Is purpose is to allow Stripes ActionBeans to be clients of Spring beans. Others have commented on @SpringBean not being able to handle Spring autowiring/component/security/transaction annotations - but to do this would be duplicating Spring's own capabilities.

I suggest that you create a DAO that is a Spring bean, place the @PersistenceContext annotation within that bean, and then use @SpringBean to retrieve that bean for use within your ActionBean.

There is also the SpringObjectFactory at stripes-stuff.org. This allows Stripes ActionBeans to become Spring Beans, however it is beta quality.

Show
Chris Herron added a comment - 25/Jan/09 8:59 AM This is not a bug. @SpringBean doesn't promise anything more than retrieving a Spring bean by its name. Is purpose is to allow Stripes ActionBeans to be clients of Spring beans. Others have commented on @SpringBean not being able to handle Spring autowiring/component/security/transaction annotations - but to do this would be duplicating Spring's own capabilities. I suggest that you create a DAO that is a Spring bean, place the @PersistenceContext annotation within that bean, and then use @SpringBean to retrieve that bean for use within your ActionBean. There is also the SpringObjectFactory at stripes-stuff.org. This allows Stripes ActionBeans to become Spring Beans, however it is beta quality.
Hide
Jarek Robakiewicz added a comment - 25/Jan/09 9:29 AM

Everything what you wrote is true but bug is not reported for @SpringBean which works as a expected but for SpringInterceptorSupport component

Documentation:
Base class for developing Interceptors with dependencies on Spring managed beans. Not to be confused with SpringInterceptor which injects Spring managed beans into ActionBeans. For example, you may wish to subclass this class in order to write an interceptor with access to Spring managed DAOs or security information.

So I have Spring manage DAOs and need access to them from Interceptor. I found SpringInterceptorSupport but it works much more like SpringBeanInterceptorSupport ...

And as a I mentiond before SpringBean seems to duplicate java.annotation.Resource annotation which allows me retrive bean by its name and inject into private field.

@"This is not a bug "
yes,It's not a bug; it's an undocumented feature!"
http://en.wikipedia.org/wiki/Undocumented_feature

thanks for quick response.

Show
Jarek Robakiewicz added a comment - 25/Jan/09 9:29 AM Everything what you wrote is true but bug is not reported for @SpringBean which works as a expected but for SpringInterceptorSupport component Documentation: Base class for developing Interceptors with dependencies on Spring managed beans. Not to be confused with SpringInterceptor which injects Spring managed beans into ActionBeans. For example, you may wish to subclass this class in order to write an interceptor with access to Spring managed DAOs or security information. So I have Spring manage DAOs and need access to them from Interceptor. I found SpringInterceptorSupport but it works much more like SpringBeanInterceptorSupport ... And as a I mentiond before SpringBean seems to duplicate java.annotation.Resource annotation which allows me retrive bean by its name and inject into private field. @"This is not a bug " yes,It's not a bug; it's an undocumented feature!" http://en.wikipedia.org/wiki/Undocumented_feature thanks for quick response.
Hide
Chris Herron added a comment - 26/Jan/09 8:33 AM

SpringInterceptorSupport is documented at the bottom of the following page:
http://stripesframework.org/display/stripes/Spring+with+Stripes

If @SpringBean, SpringInterceptor or SpringBeanInterceptor do not work as documented, then that may be a bug.

Regarding @PersistenceContext, or @java.annotation.Resource, as I mentioned above, the @SpringBean annotation implementation does not promise anything more than fetching a named bean from a Spring context. There are no undocumented capabilities in SpringHelper that do anything beyond this.

Yes, by definition the @SpringBean feature is doing dependency injection, but that fact does not obligate it to provide all of the bells and whistles that the popular dependency injection frameworks provide. Any similarity to other frameworks living or dead is purely coincidental.

You should note that in Stripes 1.6, SpringInterceptor and SpringInterceptorSupport will be deprecated. @SpringBean will still be supported, but it will be implemented using the new ObjectFactory interface (see SpringInjectionFactory on the trunk in subversion).

Show
Chris Herron added a comment - 26/Jan/09 8:33 AM SpringInterceptorSupport is documented at the bottom of the following page: http://stripesframework.org/display/stripes/Spring+with+Stripes If @SpringBean, SpringInterceptor or SpringBeanInterceptor do not work as documented, then that may be a bug. Regarding @PersistenceContext, or @java.annotation.Resource, as I mentioned above, the @SpringBean annotation implementation does not promise anything more than fetching a named bean from a Spring context. There are no undocumented capabilities in SpringHelper that do anything beyond this. Yes, by definition the @SpringBean feature is doing dependency injection, but that fact does not obligate it to provide all of the bells and whistles that the popular dependency injection frameworks provide. Any similarity to other frameworks living or dead is purely coincidental. You should note that in Stripes 1.6, SpringInterceptor and SpringInterceptorSupport will be deprecated. @SpringBean will still be supported, but it will be implemented using the new ObjectFactory interface (see SpringInjectionFactory on the trunk in subversion).
Hide
Frederic Daoud added a comment - 27/Jan/09 7:08 AM

Do we agree that this issue should be closed as 'not a bug'?

Show
Frederic Daoud added a comment - 27/Jan/09 7:08 AM Do we agree that this issue should be closed as 'not a bug'?
Hide
Jarek Robakiewicz added a comment - 28/Jan/09 11:58 AM

We can close this bug if you explain me how can I use Spring and JPA annotation together with SpringSupportIntereptor.
@PersistenceContext(unitName = "entityManagerFactory")
private EntityManager entityManager;

Base on Chris explanation I need wrap this code into the another class (DAO) and this class can be injected.

My point is that SpringSupportIntereptor doesn't deliver what it promise: integration with Spring. It gives me only support for Stripes annotation which limit Spring functionality. This 2 line of codes give me what I need

AutowireCapableBeanFactory beanFactory = springContext.getAutowireCapableBeanFactory();
beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);

but to figure out this I spent 2 hours so I wrote this report to share this problem with other developers.

Your explenation that SpringSupportIntereptor will be deprecated and you introduce new factory based on the @SpringBean doesn't sound like a good idea. It means that I cannot used latest features of Spring because of your custom implementation of StripesUtils.injectBeans method. This solution will be always out of date and for sure it is not what I understand as a integration with Spring

Show
Jarek Robakiewicz added a comment - 28/Jan/09 11:58 AM We can close this bug if you explain me how can I use Spring and JPA annotation together with SpringSupportIntereptor. @PersistenceContext(unitName = "entityManagerFactory") private EntityManager entityManager; Base on Chris explanation I need wrap this code into the another class (DAO) and this class can be injected. My point is that SpringSupportIntereptor doesn't deliver what it promise: integration with Spring. It gives me only support for Stripes annotation which limit Spring functionality. This 2 line of codes give me what I need AutowireCapableBeanFactory beanFactory = springContext.getAutowireCapableBeanFactory(); beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false); but to figure out this I spent 2 hours so I wrote this report to share this problem with other developers. Your explenation that SpringSupportIntereptor will be deprecated and you introduce new factory based on the @SpringBean doesn't sound like a good idea. It means that I cannot used latest features of Spring because of your custom implementation of StripesUtils.injectBeans method. This solution will be always out of date and for sure it is not what I understand as a integration with Spring
Hide
Chris Herron added a comment - 28/Jan/09 1:17 PM

The only promises made are documented on the Stripes website (Spring section already linked above), and in the JavaDoc:
http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/integration/spring/package-summary.html

Nowhere does Stripes promise to elevate ActionBeans to be full Spring-managed beans, or to support Spring features such as autowiring. So, its unfair to call this a bug when the code behaves as designed, and as documented.

By adding a call to AutowireCapableBeanFactory.autowireBeanProperties, Spring @Autowired and @PersistenceContext annotations could be used within Stripes ActionBeans. This would make Stripes ActionBeans seem more like actual Spring beans, yet they would not be, because the ActionBean itself would not be wrapped in a Spring proxy. This would mean that cross-cutting Spring services such as annotation driven transactions would not work within Stripes ActionBeans. In short, implementing this would lead to more confusion, and further requests for increased Spring assimilation. I sympathize with heavy Spring users who want to do this, but don't believe it should be up to Stripes to go this far.

The new ObjectFactory interface in Stripes 1.5.1 will actually provide an easy way for Jarek to implement his AutowireCapableBeanFactory.autowireBeanProperties call without having to change any Stripes classes. He would just implement his own ObjectFactory - which could be similar to the SpringInjectionFactory on the trunk destined for Stripes 1.6.

To wrap this all up:

  • SpringSupportIntereptor works as designed and documented
  • Three different workarounds have been suggested in this comments thread (StripesStuff's SpringObjectFactory, delegation to a Spring Bean DAO, user-provided ObjectFactory)
  • The implicit feature request is debatably beyond the scope of Stripes' manifesto

@Freddy, in my opinion this could be closed as "not a bug" or changed to be a feature request.

Show
Chris Herron added a comment - 28/Jan/09 1:17 PM The only promises made are documented on the Stripes website (Spring section already linked above), and in the JavaDoc: http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/integration/spring/package-summary.html Nowhere does Stripes promise to elevate ActionBeans to be full Spring-managed beans, or to support Spring features such as autowiring. So, its unfair to call this a bug when the code behaves as designed, and as documented. By adding a call to AutowireCapableBeanFactory.autowireBeanProperties, Spring @Autowired and @PersistenceContext annotations could be used within Stripes ActionBeans. This would make Stripes ActionBeans seem more like actual Spring beans, yet they would not be, because the ActionBean itself would not be wrapped in a Spring proxy. This would mean that cross-cutting Spring services such as annotation driven transactions would not work within Stripes ActionBeans. In short, implementing this would lead to more confusion, and further requests for increased Spring assimilation. I sympathize with heavy Spring users who want to do this, but don't believe it should be up to Stripes to go this far. The new ObjectFactory interface in Stripes 1.5.1 will actually provide an easy way for Jarek to implement his AutowireCapableBeanFactory.autowireBeanProperties call without having to change any Stripes classes. He would just implement his own ObjectFactory - which could be similar to the SpringInjectionFactory on the trunk destined for Stripes 1.6. To wrap this all up:
  • SpringSupportIntereptor works as designed and documented
  • Three different workarounds have been suggested in this comments thread (StripesStuff's SpringObjectFactory, delegation to a Spring Bean DAO, user-provided ObjectFactory)
  • The implicit feature request is debatably beyond the scope of Stripes' manifesto
@Freddy, in my opinion this could be closed as "not a bug" or changed to be a feature request.

People

Vote (0)
Watch (1)

Dates

  • Created:
    25/Jan/09 8:24 AM
    Updated:
    09/Feb/09 8:59 PM
    Resolved:
    09/Feb/09 8:59 PM