Sunday, March 26, 2006

New version of tapestry-spring

I've built out a new and improved version of tapestry-spring yesterday and today. This is a tiny module that properly initializes Tapestry to allow Spring beans to be injected into Tapestry pages.

This one works first off! I now run an integration test to prove this; it starts up a Jetty instance and injects a Spring bean into a Tapestry page.

More importantly, this version addresses the prototype issue. Using the standard @InjectObject annotation messes up when the bean being injected is not a singleton. Non-singleton Spring beans, aka prototypes, must be re-acquired from the BeanFactory in order to get the correct, new version.

There's now an @InjectSpring annotation that does that; reading the property will, beneath the covers, always go back to the BeanFactory to obtain a fresh copy. No caching at any layer, no problems.

I just realized that I forgot to update the documentation; that will come shortly.

I also bumped the version number up to 0.1.2 to celebrate the fact that this code works. But it is still alpha quality!

I did some trickery (I believe) so that the non-annotation classes are compiled for JDK 1.3, and the annotation classes are compiled for JDK 1.5. Took a bit of a struggle with Maven, but it works. If you aren't using annotations, you need to use a bit of XML:

<inject property="myProperty" type="spring" object="mySpringBean"/>

13 comments:

  1. Why isn't it possible to keep using object="spring:userManager"? It seems like it should just be a matter of parsing the string instead of needing a new attribute.

    ReplyDelete
  2. Well, @InsertObject is geared towards objects obtained from HiveMind. HiveMind objects (that is, services and configurations) do their lifecycle on the inside, so it makes sense to only obtain them once. Spring beans have a different lifecycle, so a different kind of property injection is a good solution, and one that doesn't keep you waiting for release 4.0.1.

    ReplyDelete
  3. Anonymous9:42 AM

    Thanks Howard!

    ReplyDelete
  4. Anonymous6:43 PM

    hi, howard:

    at the last line, you use:

    <inject property="myProperty" type="spring" object="mySpringBean"/>

    why not:

    <inject property="myProperty" object="spring:mySpringBean"/>

    ReplyDelete
  5. liigo -- please re-read the posting. There's a whole lifecycle issue with Spring that makes it not (always) work well with @InjectObject. Thus the need for @InjectSpring.

    ReplyDelete
  6. Anonymous8:55 AM

    It is working well for me, very easy to integrate... set up the spring context via the listener in web.xml, add tapestry-spring .jar to WEB_INF/lib and start using the new annotation. Its not that I don't like hivemind, but when I am trying to add a web interface to a springified app, it just seems like a whole lot of extra work and duplicated configuration to inject service objects via hivemind

    ReplyDelete
  7. If you have an investment in Spring, or are using the many great Spring libraries, then use Spring! This is a keen demonstration of the power of open source and POJOs ... it all just works together no muss, no fuss.

    ReplyDelete
  8. No! What you do is define a HiveMind service that is the factory for the ASO, and you inject dependencies into that factory, which can then pass the dependencies to the ASO. HiveMind proxies are serializable (even if the underlying service implementation is not).

    ReplyDelete
  9. Anonymous8:49 AM

    Do you know of a way to access HiveMind services from Spring? For exmple, I often want access to tapestry.services.External to generate external URLs.

    ReplyDelete
  10. Guys, what version of spring-tapestry do I specify in my pom dependency to get the @injectSpring annotation? I am using 5.0.18 and it does not seem to contain this annotation. TIA.

    ReplyDelete
  11. Mahesh -- this is an old posting for Tapestry 4. Tapestry 5 has Spring compatibility built right in, via the tapestry-spring module.

    ReplyDelete
  12. Hi Howard - does that mean, in T5, I can use @Inject for non-singleton spring beans?

    Because I read the documentation:
    http://tapestry.apache.org/tapestry5/tapestry-spring/

    And it says (I quote):
    For the moment, you should consider the non-singleton beans to be not-injectable. Instead, inject the WebApplicationContext service and obtain the non-singleton beans as needed.

    ReplyDelete
  13. I ran some tests, with a prototype and a session bean - and it looks like the documentation is correct. @Inject appears to cache and WebApplicationContext works correctly.

    ReplyDelete

Please note that this is not a support forum for Tapestry. Requests for help will be deleted. Please subscribe to the Tapestry user mailing list if you are in need of support, or contact me directly for professional (for pay) support.

Spammers: Don't bother. I delete your comments and it's a waste of time for both of us. 垃圾邮件发送者:不要打扰。我删除您的评论和它的时间对我们双方的浪费