How to launch the hosted mode with Jonas and Maven

GWT uses an embedded Jetty server. It is used at the beginning of the development of an application. During the prototype phase.
Personally, I used it for about a year, until we got the need to use JMS.
And since Jetty is not a Java EE server – it does not implement the JMS API – it was time to say goodbye to Jetty and use the application server that is used in production : Jonas.
There is not much info about the configuration to use in order to launch the hosted mode with a server different from Jetty. I found that the official website of the gwt-maven-plugin lacks information in that area.

I spent a few hours finding out the correct configuration for that. So here is how to do it :
1) Start Jonas
2) Deploy the application (EAR or WAR)
3) Run the goal gwt:run

And the configuration for the gwt-maven-plugin plugin is the following :


<plugins>
  <plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>gwt-maven-plugin</artifactId>		
					
	<!-- Old configuration, to run the hosted mode with JETTY. -->
	<!-- 
		<configuration>
		<runTarget>identify.html</runTarget>
		<hostedWebapp>${project.build.directory}/${project.build.finalName}</hostedWebapp>
		<modules>
			<module>${project.groupId}.foo.bla.MainApplication</module>
			<module>${project.groupId}.foo.bla.SecondEntry</module>
		</modules>
		<copyWebapp>true</copyWebapp>										
		<extraJvmArgs>-XX:MaxPermSize=512M  -Xms512M -Xmx1024M </extraJvmArgs>
	</configuration>
	 -->
	
	<!-- New configuration, to run the hosted mode with JONAS -->
	<configuration>					
		<modules>
			<module>${project.groupId}.foo.bla.MainApplication</module>
			<module>${project.groupId}.foo.bla.SecondEntry</module>
		</modules>					
		<extraJvmArgs>-XX:MaxPermSize=512M  -Xms512M -Xmx1024M </extraJvmArgs>
		
		<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory> 
		<runTarget>http://localhost:9000/app-context/main.html</runTarget> 
		<copyWebapp>false</copyWebapp> 
		<!--  do not start JETTY -->
		<noServer>true</noServer>
		<!-- the folder where the exploded WAR is located, inside Jonas -->
		 <!--  Constant path if jonas.development=false in conf/jonas.properties --> 					
		<hostedWebapp>${env.JONAS_BASE}\work\webapps\jonas\ear\myapp-ear-SNAPSHOT.ear\${project.build.finalName}.war</hostedWebapp>
		<bindAddress>localhost</bindAddress>   <!--  other possible value : 0.0.0.0 -->
		<logLevel>INFO</logLevel> 
		<style>OBF</style> 			
	</configuration>
	<executions>
		<execution>
			<id>gwtcompile</id>
			<phase>prepare-package</phase>
			<goals>
				<goal>compile</goal>
			</goals>
		</execution>
	</executions>
   </plugin>
...
</plugins>			

Line 35 is the most important : it specifies the path where the exploded war is deployed in Jonas.
That configuration could work with another application server of course.

Read a properties file external to a webapp

Externalizing part of the configuration of a webapp in a .properties file that is located outside of that webapp (outside the WAR, the EAR …) is a frequent requirement and I initially thought that the PropertyPlaceholderConfigurer class, provided by the Spring framework and which is an implementation of the BeanFactoryPostProcessor interface, would help me to get the values of the properties defined in that external file.
The properties are pulled into the application context definition file.
The typical sample code used to achieve this is the following :


<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">
      <list>
          <value>file:d:/temp/toto/myFile.properties</value>  
      </list>
     </property
</bean>

<bean id="smtpserverurl" class="com.vendor.SomeSmtpServer">  
    <property name="URL" value="${smtpserver.url}"/>  
</bean>  

or :

<context:property-placeholder location="file:d:/temp/toto/myFile.properties" />

<bean id="smtpserverurl" class="com.vendor.SomeSmtpServer">  
    <property name="URL" value="${smtpserver.url}"/>  
</bean>  

And the properties file :


smtpserver.url=smtp.gmail.com

It is a good solution as long as you do not need dynamic reloading of the properties, i.e. without the need for restarting the application whenever the properties values are changed.
So I find out that in that case the Apache Commons Configuration is a good alternative because it supports dynamic reloading of the properties.
And it is as easy to use as this :


package com.celinio.readprops;
import java.io.File;
import java.util.Iterator;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.log4j.Logger;

/**
 * This class reads properties that are stored in a file outside the webapp
 * @author Celinio Fernandes
 *
 */
public class ReadExternalPropertiesUtil {
		
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(ReadExternalPropertiesUtil.class);

	private static final String PROPERTIES_FILE = "config.properties";
	private static final String ENV_VAR = "PROPERTIES_APP";
	public static String propertiesFolder;
	public static PropertiesConfiguration propertiesConfig  = null;
...

FileChangedReloadingStrategy strategy  = null;
strategy  = new FileChangedReloadingStrategy();
strategy.setRefreshDelay(reloadInterval);
propertiesConfig.setReloadingStrategy(strategy);
propertiesConfig.setDelimiterParsingDisabled(true);

...

Line 23 : the path is given as an environment variable.

It works great. The only problem that I met was when I tested the reload interval (the delay period before the configuration file’s last modification date is checked again, to avoid permanent disc access on successive property lookups), it did not work : if i set the reload interval to 30 seconds for instance and if i modify the properties several times during that delay period, the new property values are still displayed. I would have expected to get the old values again, until the delay period expired.
The source code for this sample webapp is available at http://code.google.com/p/celinio/source/browse/#svn%2Ftrunk%2Fpropreloadable