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 3
Page 3 of 6

Spring-Seam hybrid components

There is a certain amount of magic behavior that Spring adds to its beans, in the form of BeanPostProcessors. If you register a Spring framework class that relies on functionality provided by a postprocessor directly as a Seam component, you take on the burden of emulating the work done by the Spring container. It would be better to let Spring do the necessary prep work and then have Seam come along and consume the final product.

That perfectly describes the behavior of a Spring-Seam hybrid component. Seam provides an XML tag that is used in a Spring bean definition to augment the Spring bean so that it can be treated as a first-class Seam component. Like other Seam components, the hybrid is given a name, registered with the Seam container, and wrapped with Seam interceptors when instantiated. Let's see how Seam permits you to weave this functionality into the definition of a Spring bean.

Preparing Spring to give away beans

To get started with creating Spring-Seam hybrid components, there are two requirements your application must meet. You must first include the Seam IoC integration library, jboss-seam-ioc.jar, on your classpath. Next, as illustrated in Listing 5, you must register the Seam XML namespace in the Spring configuration file in order to use custom tags from the Seam namespace (e.g., <seam:component>). Note that we are now dealing with Spring namespaces that are used in the Spring configuration file, not the Seam namespaces that were shown earlier.

Listing 5. Registering the Seam XML namespace

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:seam="http://jboss.com/products/seam/spring-seam" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd



> <!-- bean definitions --> </bean>

XML Schema and type-safe configuration

One of the most anticipated features of Spring 2.0 was the introduction of custom XML namespace support. XML Schema-based configuration allows for the use of domain-specific tags (e.g., <jee:jndi-lookup>) instead of the generic and more verbose <bean> tags. Seam made a similar move from generic <component> tags to schema-based component declarations (e.g., <core:manager>). The custom tags offer a sort of "type-safe" XML that simplifies the definition, makes it easier to read, and limits the available property names and property types to what the underlying class supports.

Unfortunately, to a newcomer, the XSD declarations at the top of the XML file are downright daunting. Normally, I prefer to do without such XML-hell. However, in this case, the benefits outweigh the negatives because any XSD-aware tool can immediately provide code completion of XML tags without any knowledge of the framework. That sure beats waiting for a vendor to create a tool!

The custom tags in the seam namespace do more than just reduce keystrokes and provide implicit validation of property names. The key feature of using custom tags in a Spring configuration file is the bean creation hook captured by an implementation of Spring's NamespaceHandler class. This implementation is bound to a particular XML namespace prefix. The NamespaceHandler parses the XML elements that it matches, either to produce a Spring bean, decorate an existing bean, or register functionality with the Spring container.

Seam supplies a NamespaceHandler implementation to process tags in the Spring configuration file that use the Seam namespace. One such tag, <seam:component>, is used to decorate a Spring bean as a SpringComponent, the formal class name of a Spring-Seam hybrid. This component is then offered as an authentic Seam component to the Seam container. Seam uses the SpringComponent as a wrapper that tunnels through to the Spring container to locate the underlying Spring bean instance. The NamespaceHandler can also handle the <seam:instance> and <seam:configure-scopes> tags, which are addressed in Part 2 of this series.

An important point to keep in mind: If you are not using Seam to start Spring (although I cannot think of why you would resist doing so) and you plan to use Spring-Seam hybrid components, you have to be certain that the SeamListener declaration appears before the ContextLoaderListener in the web.xml descriptor. This ordering is necessary so that the Seam container is active and ready to handle the callbacks from its custom NamespaceHandler when the Spring configuration file is processed. However, you may still encounter other unrelated reference problems during startup. Therefore, I strongly urge you to use Seam to start the Spring container.

Let's see how to incorporate the <seam:component> tag into a Spring bean definition.

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