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

Add stateful behavior to your Spring beans

1 2 3 4 5 Page 4
Page 4 of 5

If you know how bijection works, you may decide to make the switch to using the @In annotation on the properties of the class rather than using a <ref> element in the bean definition (if you don't mind using Seam annotations in your Spring beans). The @In annotation injects dependencies before every method call and clears them when the call is complete. That definitely gets you out of the scope impedance predicament. However, injecting stateful components using bijection is only safe for synchronized components.

Seam serializes access to session and conversation-scoped components automatically, and request-scoped components are naturally thread-safe, since they only service the incoming request thread. However, Seam does not serialize access to application-scoped components, because that would cause an incredible bottleneck in the application. Thus, using @In on application-scoped Spring-Seam hybrid components (or regular Seam components, for that matter) is only appropriate for injecting other application-scoped components. Otherwise, you are going to once again be allowing multiple requests to access the same injected references simultaneously.

I may have scared you by mentioning the potential to create a security hole, especially since it can be such an easy trap to fall into. Fortunately, Seam offers an elegant safety net to help you 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, as in Listing 8.

Listing 8. Injecting a component proxy

<bean id="tournamentManager"
  class="org.open18.partner.business.impl.TournamentManagerImpl"
  scope="seam.APPLICATION">
  <property name="tournament">
    <seam:instance name="selectedTournament" proxy="true"/>
  </property>
  <property name="tournamentSearchCriteria">
    <seam:instance name="tournamentSearchCriteria" proxy="true"/>
  </property>
  <property name="currentUser">
    <seam:instance name="currentUser" proxy="true" scope="SESSION"/>
  </property>
</bean>
Seam's <seam:instance> versus Spring's <aop:scoped-proxy>
If you are familiar with Seam 2.0 custom scopes, you may recognize that the <seam:instance> tag serves the same purpose as the <aop:scoped-proxy> tag. The <aop:scoped-proxy> was also developed to counteract scope impedance for Spring's native scopes. However, this built-in Spring tag is not compatible with Spring-Seam hybrid components. When a hybrid component is being injected, you must use <seam:instance> in place of <aop:scoped-proxy> to elicit this behavior.

Each time the proxy is referenced, it consults the Seam container to ensure it has the proper component instance, and not a stale one from a previous request or from another simultaneous request. Even though the properties on the wider-scoped components still remain unaffected when narrower scopes end, the narrow-scoped instance can now be garbage collected, because the wider-scoped component does not hold a direct reference to it. The proxy acts as a weak reference, which is perfect for avoiding scope impedance. In this way, you are effectively infusing state into stateless objects.

Remember, if you don't want to worry at all about this proxy business, you can simply use bijection annotations, as long as the target bean is also a stateful component. The scope impedance arises when using Spring's static dependency injection to wire components in different scopes. Thread safety is violated when you inject stateful components into singletons without using a proxy.

Now that we are on the topic of the <seam:instance> tag, you will be interested to know that it can also be used to inject native Seam components into Spring beans. Let's look at how Spring can benefit from already existing Seam components.

Donating Seam components to the Spring container

All we have done so far is take, take, take. It's time to start giving back to Spring. After all, if Spring components are useful to Seam, then the opposite is likely true as well. The <seam:instance> tag works for any Seam component, not just Spring-Seam hybrids. But here is the real kicker. The <seam:instance> tag can also be used to inject the result of an expression language (EL) value expression into the property of a Spring bean! That makes the possibilities of what Seam can contribute to Spring beans virtually limitless.

You can think of the <seam:instance> tag as an alternative to the @In annotation from bijection, particularly when the proxy attribute is set to true. The name attribute can either be a context variable name or a value expression. The scope attribute narrows the search for the context variable to a single scope. If the scope attribute is excluded, then a hierarchical context search will be performed. (Note that in this case, the scope is being interpreted by Seam to perform a lookup, so we don't use the scope prefix discussed earlier). If the create attribute is specified, and its value is true, a new instance of the component will be created if one does not exist. If this value is not used, or if it is false, a new instance will not be allocated if a value hasn't already been assigned to the context variable. Recall that value expressions imply that the create flag is true, regardless. The proxy attribute is the key to preventing scope impedance, but do keep in mind that it adds an extra bit of overhead.

1 2 3 4 5 Page 4
Page 4 of 5