Configuring components via components.xml
The components.xml
file is a bit more powerful than property settings. It lets you:
-
Configure components that have been installed automatically—including both built-in components, and application components that have been annotated with the @Name
annotation and picked up by Seam's deployment scanner.
-
Install classes with no @Name
annotation as Seam components—this is most useful for certain kinds of infrastructural components which can be installed multiple times different names (for example Seam-managed persistence contexts).
-
Install components that
do
have a @Name
annotation but are not installed by default because of an @Install
annotation that indicates the component should not be installed.
-
Override the scope of a component.
A components.xml
file may appear in one of three different places:
-
The WEB-INF
directory of a war
.
-
The META-INF
directory of a jar
.
-
Any directory of a jar
that contains classes with an @Name
annotation.
Usually, Seam components are installed when the deployment scanner discovers a class with a @Name
annotation sitting in an archive with a seam.properties
file or a META-INF/components.xml
file. (Unless the component has an @Install
annotation indicating it should not be installed by default.) The components.xml
file lets us handle special cases where we need to override the annotations.
For example, the following components.xml
file installs the JBoss Embeddable EJB3 container:
<components xmlns="https://jboss.com/products/seam/components"
xmlns:core="https://jboss.com/products/seam/core">
<core:ejb/>
</components>
This example does the same thing:
<components>
<component class="org.jboss.seam.core.Ejb"/>
</components>
This one installs and configures two different Seam-managed persistence contexts:
<components xmlns="https://jboss.com/products/seam/components"
xmlns:core="https://jboss.com/products/seam/core"
<core:managed-persistence-context name="customerDatabase"
persistence-unit-jndi-name="java:/customerEntityManagerFactory"/>
<core:managed-persistence-context name="accountingDatabase"
persistence-unit-jndi-name="java:/accountingEntityManagerFactory"/>
</components>
As does this one:
<components>
<component name="customerDatabase"
class="org.jboss.seam.core.ManagedPersistenceContext">
<property name="persistenceUnitJndiName">java:/customerEntityManagerFactory</property>
</component>
<component name="accountingDatabase"
class="org.jboss.seam.core.ManagedPersistenceContext">
<property name="persistenceUnitJndiName">java:/accountingEntityManagerFactory</property>
</component>
</components>
This example creates a session-scoped Seam-managed persistence context (this is not recommended in practice):
<components xmlns="https://jboss.com/products/seam/components"
xmlns:core="https://jboss.com/products/seam/core"
<core:managed-persistence-context name="productDatabase"
scope="session"
persistence-unit-jndi-name="java:/productEntityManagerFactory"/>
</components>
<components>
<component name="productDatabase"
scope="session"
class="org.jboss.seam.core.ManagedPersistenceContext">
<property name="persistenceUnitJndiName">java:/productEntityManagerFactory</property>
</component>
</components>
It is common to use the auto-create
option for infrastructural objects like persistence contexts, which saves you from having to explicitly specify create=true
when you use the @In
annotation.
<components xmlns="https://jboss.com/products/seam/components"
xmlns:core="https://jboss.com/products/seam/core"
<core:managed-persistence-context name="productDatabase"
auto-create="true"
persistence-unit-jndi-name="java:/productEntityManagerFactory"/>
</components>
<components>
<component name="productDatabase"
auto-create="true"
class="org.jboss.seam.core.ManagedPersistenceContext">
<property name="persistenceUnitJndiName">java:/productEntityManagerFactory</property>
</component>
</components>
The <factory>
declaration lets you specify a value or method binding expression that will be evaluated to initialize the value of a context variable when it is first referenced.
<components>
<factory name="contact" method="#{contactManager.loadContact}" scope="CONVERSATION"/>
</components>
You can create an "alias" (a second name) for a Seam component like so:
<components>
<factory name="user" value="#{actor}" scope="STATELESS"/>
</components>
You can even create an "alias" for a commonly used expression:
<components>
<factory name="contact" value="#{contactManager.contact}" scope="STATELESS"/>
</components>
It is especially common to see the use of auto-create="true"
with the <factory>
declaration:
<components>
<factory name="session" value="#{entityManager.delegate}" scope="STATELESS"
auto-create="true"/>
</components>
Sometimes we want to reuse the same components.xml
file with minor changes during both deployment and testing. Seam lets you place wildcards of the form @wildcard@
in the components.xml
file which can be replaced either by your Ant build script (at deployment time) or by providing a file named components.properties
in the classpath (at development time). You'll see this approach used in the Seam examples.