Spring into Seam, Part 2: When stateless and stateful collide

Add stateful behavior to your Spring beans

1 2 3 4 5 Page 5
Page 5 of 5

Setting up a <seam:instance> declaration for a component may not seem so bad if you have to do it once, but having to retype the declaration each time you want to inject a given Seam component can be a drag, not to mention error-prone and non-transparent. That is why the <seam:instance> tag was designed to double as an alias tag. When used as a top-level element, the id attribute of <seam:instance> can be used to create an mediator bean. To the Spring container, this bean is just like any other Spring bean. Under the covers, the <seam:instance> element results in the creation of a SeamFactoryBean, which works just like any other Spring factory bean in that the underlying target object is resolved when the factory bean is injected. In this case, what is injected is a Seam component proxy. Listing 9 gives examples of how all of the references used in this article can be converted into aliases and injected into the application-scoped tournamentManager singleton bean without fearing scope impedance or thread-safety problems.

Listing 9. Defining and using aliases for component proxies

<bean id="tournamentSearchCriteriaTarget"
  class="org.open18.partner.business.TournamentSearchCriteria"
  scope="seam.CONVERSATION"/>

<seam:instance id="tournamentSearchCriteria" name="tournamentSearchCriteriaTarget" proxy="true"/>

<seam:instance id="currentUser" name="#{currentUser}" proxy="true"/>

<seam:instance id="selectedTournament" name="selectedTournament" proxy="true"/>

<bean id="tournamentManager"
  class="org.open18.partner.business.impl.TournamentManagerImpl"
  scope="seam.APPLICATION">
  <property name="tournamentSearchCriteria" ref="tournamentSearchCriteria"/>
  <property name="selectedTournament" ref="selectedTournament"/>
  <property name="currentUser" ref="currentUser"/>
</bean>

By setting up an alias, you are free to inject the component into the properties of other Spring beans using the <ref> tag, which is blissfully unaware that it is actually injecting a Seam component, possibly even one that is proxied. This usage pattern, in my opinion, is the best way to prevent errors and steer clear of scope impedance. I would even recommend creating a separate Spring configuration file to hold these alias definitions. Doing so will make it easy to perform functional tests on the Spring POJOs in the absence of the Spring container, since the main file will not have <seam:instance> references scattered all over the place. You can easily swap implementations of the referenced beans. It's sort of like a POXD (plain old XML document).

Stateful singletons

As an alternative to injecting a component proxy into the property of a Spring singleton, you can look up the Seam component from the Seam container and assign the result to a local variable. To avoid direct interaction with the Seam container, you add a static lookup method to the component class that reaches into the Seam container and grabs the component instance by name. Listing 10 shows the declaration of the static lookup method and an example of its use in the tournamentManager bean.

Listing 10. Looking up a Seam component using a stateful singleton

public class TournamentSearchCriteria {
    ...
    public static TournamentSearchCriteria instance() {
        return (TournamentSearchCriteria) Component.getInstance("tournamentSearchCriteria");
    }
}

public class TournamentManagerImpl implements TournamentManager {
    ...

    public List<Tournament> findTournaments() {
        TournamentSearchCriteria criteria = TournamentSearchCriteria.instance();
        ...
    }
}

The technique used here is known as a stateful singleton. Rather than the singleton being instantiated once and shared across the entire application, it is instantiated once and bound to the stateful scope. That means there is one instance in that particular scope, but there may be many instances across the whole application. For instance, if the stateful component is session-scoped, then there can be one instance per user session. The stateful singleton allows you to avoid the multi-threaded issues discussed earlier. In addition, since the result is assigned to a local variable, there is no chance of scope impedance. The only downside is that the static instance method relies on the Seam container being available, which can make testing more challenging. However, you can design the lookup so that it has a fallback in a test environment.

Learning to share

At this point in the series, you should have a good sense of how to inject Seam components into the Spring container and how to avoid scope impedance and thread-safety problems when mixing singletons and stateful components. The Seam component that is most frequently donated in this way is the Seam-managed persistence context. In such a case, Seam offers a tighter integration than what is possible with the <seam:instance> tag. In the third and final part of this series, you'll see how to allow Spring to benefit from Seam's automatic persistence context management and how it can dually benefit your development process.

Dan Allen is an independent software consultant, author, and open source advocate. After graduating from Cornell University with a degree in Materials Science and Engineering in 2000, Dan became captivated by the world of free and open source software, which is how he got his start in software development. He soon discovered the combination of Linux and the Java EE platform to be the ideal blend on which to build his professional career. In his search for a robust Web framework, Dan happened upon JBoss Seam, which was quickly granted this most coveted spot in his development toolbox. Excited about Seam, Dan decided to share his thoughts with the world. He is now the author of Seam in Action, published by Manning Publications, a project which he picked up immediately after completing his three-part series on Seam for IBM developerWorks. Dan is also a committer on the Seam project, an active participant in the Seam community, and a Java blogger. You can keep up with Dan's development experiences by subscribing to his blog at www.mojavelinux.com.

Learn more about this topic

1 2 3 4 5 Page 5
Page 5 of 5