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

Add stateful behavior to your Spring beans

1 2 3 4 5 Page 2
Page 2 of 5

To distinguish Seam scopes from scopes provided by other frameworks, the scope name is prefixed with a namespace, which, by default, is seam. Putting that together, you create a conversation-scoped component by using the value seam.CONVERSATION in the scope attribute. You can customize the namespace prefix that is used by supplying an override to the prefix attribute of the <seam:configure-scopes> declaration, as shown in Listing 2.

Listing 2. Overriding the default scope namespace

<seam:configure-scopes prefix="org.jboss.seam.ScopeType"/>

In this case, the value of the scope attribute would become org.jboss.seam.ScopeType.CONVERSATION, which happens to be the fully qualified name of the enum constant for the conversation scope.

In the first part of this series, you were introduced to a golf tournament tracker application, which is used to manage a database of golf tournaments that is made available to partners through a Web service. The read and write operations for the Tournament entity are handled by the tournamentManager bean, a classic singleton Spring bean. It's not very interesting in our pursuit of state. However, one of the beauties of tying Spring and Seam together is that stateless Spring beans, such as tournamentManager, can be infused with state through the use of other stateful beans. To see how this is done, let's start by creating a search criteria bean that is stored in Seam's conversation scope. The definition of this bean is shown in Listing 3. For now, we're sticking with the default namespace prefix for the scope name.

Listing 3. Definition of a stateful Spring bean

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

When working within the context of a long-running conversation in Seam, the tournamentSearchCriteria bean is instantiated once, the first time it is used, and remains available for the duration of the conversation. Keeping this bean in scope is important so that the search criteria entered by the user is not lost between requests. There are several ways to start a long-running conversation in Seam. Since tournamentManager is already a Seam-Spring hybrid component, the easiest way might be to add Seam's @Begin(join = true) annotation to the search method.

When declaring Spring-Seam hybrids using the scope attribute, you do lose some flexibility over the configuration of the component. While setting the scope is in, what is out is the ability to set the auto-create flag, provide an explicit class, supply a custom context variable name, and disable Seam interceptors. Fortunately, there are other ways to configure some of these settings, which you'll see in a moment. But remember that the idea here is to use the <bean> tag without any additional interference, aside from the value of the scope attribute. This approach is just a shorthand for the more formal <seam:component> declaration, which gives you the extra power if you need it, including the ability to specify the Seam scope.

The auto-create flag is set to false by default for components configured using the scope attribute. However, this setting can be controlled globally using the default-auto-create attribute on the <seam:configure-scopes> tag, as shown in Listing 4. For the duration of the article, I will assume the use of this setting so that Spring initializes the bean for Seam when it is requested.

Listing 4. Setting the auto-create flag globally

<seam:configure-scopes default-auto-create="true"/>

Listing 5 illustrates the only way to disable intercept for components configured using the scope attribute: by adding Seam's @BypassInterceptors annotation on the class.

Listing 5. Disabling interceptors on a Spring-Seam hybrid component

@BypassInterceptors
public class TournamentManagerImpl implements TournamentManager {
    ...
}

Now that you have your Seam-scope Spring bean defined, you are going to want to start using it in other beans.

1 2 3 4 5 Page 2
Page 2 of 5