Spring into Seam, Part 1: Build a Spring-Seam hybrid component

Which is better, Seam or Spring? Learn why you don't have to choose

1 2 3 4 5 6 Page 4
Page 4 of 6

Dressing up a Spring bean as a Seam component

Seam is able to decorate a Spring bean as a Seam component by nesting a <seam:component> inside the <bean> element that defines the Spring bean. This setup is different from the EL resolver approach mentioned earlier because it allows the Spring bean to become a first-class citizen in the Seam container. This gives you much more control over how the Spring bean behaves under the Seam runtime. Let's explore this integration by putting it into practice.

The Spring bean definition of tournamentManager is shown in Listing 6. This bean acts as the business interface to manage a collection of golf tournaments. The golf tournament data is maintained by a partner (hence the org.open18.parter package name) and exposed to the Open 18 application, a golf community portal, through a Web service endpoint. The focus of the sample Web application used in this article is on the back-end management of the tournament data. Notice that the tournamentManager bean has been promoted to a Seam component through the use of the <seam:component> tag.

Listing 6. Defining a Spring-Seam hybrid component

<bean id="tournamentManager" 
  class="org.open18.partner.business.impl.TournamentManagerImpl">
  <seam:component/>
</bean>

Seam derives the context variable name used to reference the Seam component from the Spring bean identifier, which may be supplied as either the id or name attribute of the <bean> element. If for some reason you do not want to use the ID of the Spring bean as the name of the Seam component, you can provide an alternative name using the name attribute of the <seam:component> tag, as in Listing 7.

Listing 7. Providing an alternate Seam component name

<bean id="tournamentManager" 
  class="org.open18.partner.business.impl.TournamentManagerImpl">
  <seam:component name="tournamentManagerSpring"/>
</bean>

By default, the Seam component is scoped to the ScopeType.STATELESS context. The stateless context is selected as the default Seam scope because, more times than not, the Spring bean is a singleton. Thus, there is no benefit in storing the bean in a real Seam scope, as it already lives for the duration of the container's lifetime. The stateless context is also used to step aside and let Spring manage the scope of the bean, if the bean happens not to be a singleton. Spring now supports custom scopes, such as the flow scope from Spring Web Flow. Use of the stateless context prevents Seam from interfering with Spring's plans for the bean and avoids the case where Seam is holding a stale reference to a bean.

Keep in mind, though, that by using the stateless context, Seam will request the bean from the Seam container every time the corresponding context variable is resolved. This same recurrent lookup would occur if the Spring bean were accessed through the EL resolver bridge. You do not need to be concerned about the added overhead unless the Spring bean is a prototype, in which case you should know that the bean will be instantiated on each lookup.

If you intend on making the Spring bean stateful (as opposed to a singleton), it's best to have it stored in a Seam scope. The Seam scope is supplied using the scope attribute on the <seam:component> tag. To store a Spring bean in a Seam scope, the Spring bean must also be assigned the Spring prototype scope.

To demonstrate this capability, let's define a search criteria bean, shown in Listing 8, that is used in conjunction with the tournamentManager bean to filter the collection of tournaments that are displayed in the user interface. The choice of the conversation scope ensures that the search criteria is held in memory for the duration of the user's interaction with the search form.

Listing 8. A conversation-scope Spring bean

<bean id="tournamentSearchCriteria" class="org.open18.partner.business.TournamentSearchCriteria" scope="prototype"> <seam:component scope="CONVERSATION"/>

</bean>

Each time a prototype bean is requested from the Spring container, Spring allocates a new instance. But, because the resolved bean is stored in a conversation-scoped context variable in this case, Seam only asks Spring to create an instance once per user conversation. It's an ideal marriage of the functionality from each container. In the next article in this series, you will learn about another way to scope the Spring bean to a Seam context using Spring's custom scoping mechanism, and you'll also study the dangers of scope impedance.

1 2 3 4 5 6 Page 4
Page 4 of 6