Building Spring-Seam Hybrid Components For Web Applications
Spring and JBoss Seam frameworks provide different set of features for developing enterprise web applications. Spring is a JavaEE middleware framework, built on features like POJO Abstraction, Dependency Injection(DI) and Aspect Oriented Programming (AOP), which provides integration with frameworks like Hibernate, TopLink and iBatis. Seam is a web application framework that integrates technologies such as AJAX, Java Server Faces (JSF), Enterprise Java Beans (EJB3), Java Portlets and Business Process Management (BPM). Is it possible and does it make sense to use these two frameworks together in developing web applications? This topic was the main focus of a recent article and a java community forum discussion with emphasis on how the strengths of each of these frameworks can be used together to get best of both worlds.
Dan Allen recently wrote two articles about integrating Spring and Seam frameworks in web applications. In the first article, he explained how to build hybrid components that benefit from both Seam and Spring container functionality. He said that Seam unifies JSF, JPA, EJB 3 and other technologies but it doesn't support some of the features Spring offers out of the box, such as lightweight remoting, AOP declarations, framework template classes and resource injections. This is where building a Spring-Seam hybrid component, a managed object that benefits from functionality provided by both the Seam and Spring containers, comes into picture. Seam provides a module for integrating Spring Framework into the web application as well as share application components and low-level resources.
Using a sample web application, the author explained how to integrate Spring beans into a Seam application by using the ContextLoader
In part 2 of the article series, he talked about adding stateful behavior to Spring beans, which is still a challenge to accomplish when using Spring framework alone. Spring beans can be infused with "State" by registering a Seam custom scope handler that allows Spring beans to be stored in Seam contexts to make the temporary conversation (for implementing the redirect-after-post pattern), long-running conversation (for single-user page flows), and business process scopes to support interactions from multiple users over an extended period of time. This way, the Spring beans can be stateful without having to resort to the HTTP session.
The author discussed the scope issues and thread-safety problems at run-time when using Spring and Seam together. Spring injects dependencies once at creation time, whereas Seam performs injection dynamically, before every method invocation. This difference in the design philosophy of these two frameworks can lead to "scope impedance" paradox where a bean outlives its intended lifetime as a result of attaching itself to a longer-lived component. This situation occurs when using Spring's static dependency injection to wire components with different scopes. Seam offers a solution to help avoid both scope impedance and thread-safety problems. Instead of injecting a bean instance directly using a "ref" element, you inject a proxy using the seam:instance tag.
There has also been interesting discussion on this topic in the community forums. Rick Hightower gave an overview of Seam 2.0.1 features and led a discussion thread on using Seam and Spring together. Some of the questions that have been asked in the discussion are:
- If you are using Seam and Spring, and you had to live without one of them, which one would it be?
- Do you use Seam with or without EJB3?
- Do you use Seam with or without Spring?
- How good are the Seam generation tools?
- Is Seam the best way to write a JPA and JSF based application?
- Where do you think Spring and Seam overlap and when they do overlap which one is better?
We've choosen JBoss Seam
I must admit that maybe Spring gives you a bigger freedom but we've choosen the stack already (JSF, JPA with Hibernate) and the JBoss Seam framework suits this the best. I love the event/observer model in Seam, I really appreciate the custom Seam tags that solve many small but very common problems when using JSF. I like JBoss Seam scopes (although sometimes they are tricky and not so well documented, so it took as a little more time to fully understand how they work along with the Seam's DI). The security model in Seam is very nice and easy to use. Finally I really prefer annotations over XML configuration. Oh I've forgot about extended EL - it's great.
There are also some drawbacks. There is almost no AOP support, especially when you try to develop an application using POJO and deploy it into non JavaEE server like Tomcat (as we do with tinyPM). I miss the Spring's ease of externalizing configuration of all resources. I also sometimes have a filling that Seam is too bit tricky and Spring is more predictable, but this is just a matter of learning curve Seam have (especially before ver. 2.0 when the docs were not to helpful).
I think the RichFaces and A4J libraries are still very unstable and make JSF pages very heavy, so we're looking for ways to get rid of them from our preferred stack. But Seams remoting seems to be very promising in that. The rest we will just do using Prototype and Scriptaculous directly.
So generally Seam framework may be a very productive and light solution for JSF applications. We are currently using 2.0.1 version and it solves a lot of problems you may encounter when trying to do something more then just a PetStore or yet another Hello World app in JSF. Seam will be our framework of choice for the Java web apps for some time.
Re: We've choosen JBoss Seam
As with all things, there is always room for improvement. As you mentioned, the novelty of advanced scoping can make this powerful weapon difficult to wield at first. I spend a lot of time explaining Seam's scopes in Seam in Action and how best to use them. My feeling is that it is worth the effort because these scopes fit more naturally with the business cases being managed by the application.
The AOP support in Seam is intentionally restrictive as a commitment to simplicity. In essence, the AOP support models that of EJB 3, favoring the use of its predecessor if you are developing with session beans. While to some AspectJ and Spring AOP are incredibly powerful, their syntax can be daunting to a newcomer, perhaps requiring the skills of an advanced Java developer even in the maintenance phase of an application. Seam encourages you to develop stereotypes, which are annotations that describe the intended behavior of an object, implemented by an interceptor applied by way of the annotation. If you do need the power of AspectJ or Spring AOP, that is what you have the Spring-Seam integration for. Remember, your Spring beans can behave just like Seam components in all other ways.
As for your experience with RichFaces, I will agree that its strengths are overshadowed greatly by its weaknesses. My feeling is that it needs to enter a stabilization period because there is no question that it has cornered an innovative approach to the Ajax/JSF combination. However, if you have made up your mind to look elsewhere, I encourage you to try ICEFaces. In speaking with their developers, they seem committed to reducing bandwidth and have an eye towards the next generation user interfaces.
Re: We've choosen JBoss Seam
Spring + JSF
We provide quite a lot of the same benefits of Seam such as fine-grained scope management (including the ability to define Spring beans in these scopes), conversational JPA and Hibernate persistence options, a powerful security model through our integration with Spring Security 2, and a number of conveniences that make it easier to work with JSF constructs such as the DataModel. We provide all of this in a completely portable runtime without the need to swallow EJB3, and with the full power of Spring's AOP support available natively. I firmly believe that the Flow Definition Language, Web Flow's higher-order DSL for declaratively defining controller interactions, leads to a more productive development experience as it can serve as a complete replacement for the JSF managed bean model and navigation model and is fully dynamic and refreshable at runtime. In fact, it today provides a large portion of the features that many believe to be missing from JSF.
So if your answer to, "If you are using Seam and Spring, and you had to live without one of them, which one would it be?" is Spring, and you want to leverage the power of the JSF UI component model but are looking for a better development experience, I highly encourage you to check it out for yourself.
Spring Faces Lead
We're using both!
We created a internal framework that encapsulates much of Seam and Spring advanced funcionalities, freeing developers from learning more advanced features of each framework. This framework is in Java and Javscript, for easy use of Seam remoting.
Re: Spring + JSF
I'm very happy to see Spring embracing JSF and improving on it. I think what Seam proved, and what Spring Web Flow validated, is that the JSF life cycle is more extensible than most people gave it credit for at first. These projects have breathed life back into JSF, and frankly, I think it is worth saving.
I had a lot of pain when I first started using JSF and was almost ready to give up on it when Seam came around. While I am sure there are tons of innovative frameworks than can boast productivity in one area, nothing comes anywhere close to giving the full breathe of control as the two frameworks being discussed in this series. To adopt Seam, you definitely do not have to swallow EJB 3. In fact, all you need to make an application functional in Seam is a good old JavaBean with the @Name annotation and one XHTML-based Facelets template. Even the component descriptor is optional. Of course, there are 550 pages of Seam in Action + 150 more pages online worth of additional features to learn about.
One thing I think Seam does right, that perhaps even Spring Web Flow misses, is to honor the EntityManager/Hibernate Session as a first class object in the application. You can begin a conversation just by flipping a switch and that conversation stays on for as many requests as you make until you turn it off. All the while, the persistence context is right there with you (lazy load, no need to merge, application transaction). You don't need to take some prescribed path through the application and there is no Open Session in View hack. Granted, you can use constrained navigation with jPDL, but you will know when you are ready for that.
I could go on and on. But my theme is always the same. Don't let anyone tell you what to use, not even the framework (forced interfaces in Spring and EJB 3). Decide for yourself.