Help

Built with Seam

You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.

Here is some simple steps to handle a set of parameters for your seam project, using the ant file. Our goal was to create some multiple instances of the same seam application, named differently but running on the same JBoss server.

The application was generated using seam-gen, using the exploded ear mode; but the concept remains for other modes.

In this example, our main project name is ResourcesManager. We want to keep this as codename for development and demonstration purpose and market the application under the name FitnetManager.

In a more general way, we will parametrize for a new customer:

  • The application display-name
  • A specific datasource
  • A mailing configuration

Project-name

  • In build.properties:

Add two new entries to handle the display-name and the development codename

fitnetBranch=FitnetManager
project.trunk=ResourcesManager
  • In build.xml:

replace

<property name="project.name" value="ResourcesManager" />

by

<property name="project.name" value="${fitnetBranch}" />
<property name="project.trunk" value="ResourcesManager" />

In the target war, add in the filterset element:

<filter token="fitnetBranch" value="${project.name}" />

The @fitnetBranch@ parameter is now usable in all files in the WEB-INF directory

Same operation in the ear target. add these lines in copy todir=${ear.dir}/META-INF

<filterset>
	<filter token="fitnetBranch" value="${project.name}" />
</filterset>

You can now use the parameter in both WEB-INF and META-INF directories. Now, let's apply the parameter in the configuration files.

In META-INF/application.xml, replace all occurences of your project name using the parameter. The file should now look like this:

   <display-name>@fitnetBranch@</display-name>
   
   <module>
      <web>
         <web-uri>@fitnetBranch@.war</web-uri>
         <context-root>/@fitnetBranch@</context-root>
      </web>
   </module>
   
   <module>
      <ejb>@fitnetBranch@.jar</ejb>
   </module>
   
   <!-- Seam and EL -->
   <module>
       <ejb>jboss-seam.jar</ejb>
   </module>

Same thing in META-INF/jboss-app.xml:

<jboss-app>
   <loader-repository> 
      seam.jboss.org:loader=@fitnetBranch@
   </loader-repository> 
</jboss-app> 

And, voila! The @fitnetBranch@ parameter now controls the display name and the ear/jar/war filename, allowing to deploy multiple instances.

Specific Datasource

Our next goal is to create a specific datasource for every project instance, named after the instance. For the moment all the instances refers to a single datasource file named [yourtrunkname]-ds-prod.xml.

First, add the three parameters to build.properties and build.xml:

db.url=jdbc\:mysql\://localhost/databasename
db.username=databaseuser
db.password=databasepassword
<!-- database connection properties -->
<property name="db.url" value="${db.url}" />
<property name="db.username" value="${db.username}" />
<property name="db.password" value="${db.password}" />

In the target datasource

replace

		<copy todir="${deploy.dir}">
			<fileset dir="${basedir}/resources">
				<include name="${project.name}-${profile}-ds.xml" />
			</fileset>
		</copy>

by

		<copy todir="${deploy.dir}">
			<fileset dir="${basedir}/resources">
				<include name="${project.trunk}-${profile}-ds.xml" />				
			</fileset>
			<filterset>
				<!-- filters added for FitnetApplication-->
				<filter token="fitnetBranch" value="${project.name}" />
				<filter token="db.url" value="${db.url}" />				
				<filter token="db.username" value="${db.username}" />
				<filter token="db.password" value="${db.password}" />
			</filterset>
			<!-- rename -->
			<globmapper from="${project.trunk}-${profile}-ds.xml" to="${project.name}-${profile}-ds.xml"/>
		</copy>

As you can see, the Datasource file is renamed during the copy process, according to your new display-name, and the new attributes are applied.

Now we just have to change components.xml, persistence-dev.xml and persistence-prod.xml:

components.xml:

  <persistence:managed-persistence-context 
	name="entityManager" auto-create="true"	persistence-unit-jndi-name="java:/@fitnetBranch@EntityManagerFactory"/>

persistence-*.xml:

   <persistence-unit name="@fitnetBranch@">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/@fitnetBranch@Datasource</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="validate"/>
         <property name="hibernate.cache.use_query_cache" value="true"/>
         <property name="hibernate.jdbc.batch_size" value="20"/>
         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
         <property name="jboss.entity.manager.factory.jndi.name" value="java:/@fitnetBranch@EntityManagerFactory"/>
      </properties>
   </persistence-unit>

Same thing in resources/ResourceManager-*-ds.xml:

      <jndi-name>@fitnetBranch@Datasource</jndi-name>
      <connection-url>@db.url@</connection-url>
      <driver-class>com.mysql.jdbc.Driver</driver-class>
      <user-name>@db.username@</user-name>
      <password>@db.password@</password>

Now during deployment, a specific datasource with his own configuration will be generated. Multiple independant instances of the application can coexist on the server.

Mailing

We applied the same recipe to parametrize mail sending in the application:

build.properties:

mail.host=smtp-server
mail.port=25
mail.username=mail-login
mail.password=mail-password

build.xml:

	<!-- mailer properties -->
	<property name="mail.host" value="${mail.host}" />
	<property name="mail.port" value="${mail.port}" />
	<property name="mail.username" value="${mail.username}" />
	<property name="mail.password" value="${mail.password}" />
	<target name="war" depends="compile" description="Build the distribution .war file">
        (...)
		<copy todir="${war.dir}/WEB-INF">
                (...)
			<filterset>
                        (...)
				<filter token="fitnetBranch" value="${project.name}" />
				<filter token="mail.host" value="${mail.host}" />
				<filter token="mail.port" value="${mail.port}" />
				<filter token="mail.username" value="${mail.username}" />
				<filter token="mail.password" value="${mail.password}" />
			</filterset>
		</copy>
        (...)
        </target>

components.xml:

 <mail:mail-session host="@mail.host@" password="@mail.password@" port="@mail.port@" username="@mail.username@"/>

Conclusion

These three configuration elements represents today a customer profile to us but the same concept can be applied to handle lots of other configuration elements. Feel free to enhance or correct the present document; as I'm not a ant power-user, some steps above might be useless.