An approach to configurable parameters

It is annoying how much work you need to do just to get all the properties from the file mapped to a class catching all the exceptions and repeating many times the same keys thorough the configuration files. For example, normally I had before a class that has static String variables each one mapping a key in the property file and then I use those variables when loading the properties and validating, etc.

When you need to load some properties from a file to your application in order to have some configurable parameters normally you use an external file in case of having a Java SE application or a resource bundled in your Java package such as yourwar/META-INF/applicationProperties.xml.

I have write some dirty (ugly) code just to give you an idea of how that can be easier.

Supose the next scenario.
you have a applicationProperties.xml file
---

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">

<properties>
<comment>
The good thing of using the xml version of properties file is that
it is "easy" to see the whitespaces that normally endup at the end of
the strings and most of the times we forget to use value.trim() ...
and then some time is spent for that stupid bug
</comment>

<entry key="connectionString">jdbc:h2:file:c:\h2db\dbName</entry>
<entry key="user">sa</entry>
<entry key="password">saadmin</entry>
<entry key="poolSize">7</entry>
<entry key="timeoutMillis">7000</entry>
<entry key="retryInterval">3</entry>

</properties>

---

and the next class mapping your file properties
---

public class ConfigurableParameters {


   public String _connectionString;
   public String _user;
   public String _password;
   public Integer _poolSize;
   public Long _timeoutMillis;
   public Integer _retryInterval;
   
   private static ConfigurableParameters instance;
   public static ConfigurableParameters getInstance() {
      if (instance == null) {
         instance = new ConfigurableParameters();
      }
      return instance;
   }
}

---

You see, the only time where you repeated the keys are in the name of the variables of the class. Now, wouldn't it be nice to load all the properties like this ?

---

public static void main(String[] args) {
      boolean confSuccess = ConfigurationHelper.mapConfigurableProperties(
                           ConfigurationSource.FILE,
                           "applicationProperties.xml",
                           ConfigurableParameters.getInstance());
      if (!confSuccess) {
         System.out.println("Error loading configuration");
         return;
      }
      
      System.out.println(ConfigurableParameters.getInstance()._connectionString);
      System.out.println(ConfigurableParameters.getInstance()._user);
      System.out.println(ConfigurableParameters.getInstance()._password);
      System.out.println(ConfigurableParameters.getInstance()._poolSize);
      System.out.println(ConfigurableParameters.getInstance()._timeoutMillis);
      System.out.println(ConfigurableParameters.getInstance()._retryInterval);
   }

---

The reason I make that the function recognizes all the fields starting with an underscore is just to make it clear that it will expect that those fields have a key in the properties file.

Actually You can make the fields of ConfigurableParameters class to be private and just provide public getters, it will still set the parameters. Also you can load the properties from a bundle file resource of the packaged jar, just call the method with ConfigurationSource.RESOURCE, and your sourceAddress would be something like "/META-INF/applicationProperties.xml", depending where did you put the file.


The implementation for the ConfigurationHelper is here

---

public class ConfigurationHelper {


   public enum ConfigurationSource {
      RESOURCE, FILE
   }


   public static boolean mapConfigurableProperties(ConfigurationSource configurationSource, String sourceAddress, Object target) {


      if (configurationSource == null || sourceAddress == null || target == null )
         return false;
      
      try {
         Properties sourceProperties = 
            getSourceProperties(configurationSource, sourceAddress, target);


         if (sourceProperties.isEmpty())
            return false;


         for (Field f : target.getClass().getDeclaredFields()) {
            String fieldName = f.getName();
      
            if (!fieldName.startsWith("_"))
               continue;


            fieldName = fieldName.substring(1);


            if (!sourceProperties.containsKey(fieldName))
               continue;


            boolean originalAccesibleValue = f.isAccessible();


            f.setAccessible(true);
            f.set(target, getConvertedValueForType((String) sourceProperties.get(fieldName), f.getType()));
            f.setAccessible(originalAccesibleValue);
         }


      } catch (Exception e) {
         e.printStackTrace();
         return false;
      }
      return true;
   }


   private static Properties getSourceProperties(ConfigurationSource configurationSource, String sourceAddress, Object target) {
      Properties prop = new Properties();
      try {
         InputStream is = 
            configurationSource == ConfigurationSource.FILE ? 
               new FileInputStream(sourceAddress) : 
                  target.getClass().getResourceAsStream(sourceAddress);
               
         prop.loadFromXML(is);
         is.close();
      } catch (Exception e) {
         e.printStackTrace();
      }


      return prop;
   }


   private static Object getConvertedValueForType(String sourceValue, Class c) {
      Object convertedValue = null;
      if (c == String.class) {
         convertedValue = sourceValue;
      } 
      else if (c == Long.class) {
         convertedValue = new Long((String) sourceValue);
      }
      else if (c == Integer.class) {
         convertedValue = new Integer((String) sourceValue);
      } 
      else if (c == BigDecimal.class) {
         convertedValue = new BigDecimal((String) sourceValue);
      }


      return convertedValue;
   }


}

---

This all may seem out of the standard conventions and I just didn't think of another way of doing this. It is just an idea of how can you make the work of loading configurable properties easier.

Have fun trying it and please give me feedback about how you are doing it.

Easiest way to publish Java Web Services --how to

In a previous post I wrote about publishing a Web Service through an embeddable ejb3 implementation, which is good since @Stateless beans can have injected managed entityManagers, in some cases that is the way to go if you don't want to deploy your app in a full J2EE server or you need a more flexible environment.

Just days ago I found that the J2SE itself has an lightweight http server embedded into, and the API itself has an Endpoint class that allows you to publish a Web Service in a J2SE environment.

There is more than one way for doing this, but this is the more automatic I could found, the next is a working example. The JRE version I am using is 6 update 7, I am not sure since when it supports it

-----

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import javax.xml.ws.Endpoint;


@WebService
@SOAPBinding(style=Style.RPC) // without this it does not work automatically.

public class ASimpleTest {
public static class WebServiceTest {
public String callMe(String name) {
return "Hello "+name+" !";  
}
}
public static void main(String[] args) {
Endpoint.publish("http://localhost:8080/sayHello", 
new WebServiceTest());
// http://localhost:8080/sayHello?wsdl will be the 
// place for the wsdl generated on the fly

// remember to use the DNS address of your IP or 
// your IP itself if you want to expose so as to 
// be accessible not only from localhost or
// 127.0.0.1
}
}

----- 


Now you wonder how does this work ? Well, as you publish(...) it starts its embedded http server and binds the webservice automatically generated from the WebServiceTest class to the ip:port you've specified. The threading configuration should be quite ok for most cases.

Have fun trying it !

Run Java application as Windows Services

Sometimes you need to execute a java program as the machine starts without the needing to log-in. To achieve that you need to make a Windows Service.

For the purpose of this short how to, I will assume you have a folder with aRunnableJarFile.jar with maybe a lib folder and a configuration file for the java application, which is the usual way for packaging Java applications

One option, and the one I like the most is to use the open source project at Java Service Launcher, it gives you two important files. jsl.exe and jsl.ini. you normally put those files in the same folder as yourRunnableJarFile.jar.
You edit the jsl.ini file so as to tell jsl.exe how to launch your runnable jar ( e. g. cmdline= -jar aRunnableJarFile.jar ), you can also configure where the jvm is, where will be the working directory for your application as the service starts, where you'll redirect all the output or erroutput of the sevice to a file and things like that.
As you have the jsl.ini configured you can run your application with 'jsl.exe -debug' which will launch your java app rigth in the console so you can see if everything went ok with the jsl.ini, you can also run 'jsl.exe -install' and it will create a windows service pointing to that jsl.exe file.
As you start the windows service ( or normally configure it to automatically start ) it will launch the jsl.exe file wihch will run your java application. When you stop the windows service jsl will call System.exit() in you app, so any shutdown hooks that you configured will be called by default. It is really easy.

Another option is to create a exe wrapping your jar file. JSmooth is an open source project that does exactly that.
It has a graphic user interface that walks you though wizard-like steps to create an exe wrapper for your Java application and as you create the wrapper, you tell jsmooth that you want the wrapper to be a windows service.
It produces aRunnableFileWrappingYourJarFile.exe which you can run with an 'install' or 'remove' argument to install or remove the application as a windows service.

Although I didn't see something similar to jsl.exe, there are lots of programs like jsmoth but mostly commercial.

Hope you can find useful this post and any problems you have I'll do my best to help you

P.D.: please forgive my bad English

Easy WebServices in Java (not the common way)

Where we are working now we needed to have a fast way to create WebServices and I didn't want to deal/manage J2EE containers (packaging/deployment ...) so I tried what OpenEJB  has to offer.

OpenEJB is an embedable and ligthweight implementation of EJB3, can be used as a standalone server also. In popular words, OpenEJB  is a way in which you can have everything that is available in the EJB3 container, but 'outside' the container (well, not really).
Consider the next step by step tutorial for creating a webservice.
  • Create a sampleproject
  • Download  openejb-3.0.zip from http://openejb.apache.org/download.html and unpack it
  • Add to the classpath of your sampleproject every .jar file that's in unpacked/lib
  • Create a META-INF folder inside your src directory and create a file inside that folder called ejb-jar.xml and just put in it this stringr "<ejb-jar/>" (without quotes)
  • Create now the interface that defines the contract of your webservice and anotate it with
     @WebService(targetNamespace="http://yourcompany.com/wsdl")
     public interface TestWs { ... }
  • Create the class that implements your interface and anotate it like this:
     @Stateless
     @WebService(portName = "TestPort",
         serviceName = "TestWsService",
         targetNamespace = "http://yourcompany.com/wsdl",
         endpointInterface = "full.qualified.name.of.your.interface.TestWs")
     public class TestImpl { ... }
  • To start the Webservice you need to do this:
   pubilc static void main(String[] args) {
      Properties properties = new Properties();        
      properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
      "org.apache.openejb.client.LocalInitialContextFactory");
      properties.setProperty("openejb.embedded.remotable", "true");
      new InitialContext(properties); // here the magic starts ....
   }

Taran !, after this steps what you have is a stateless bean exposed as a webservice in this location: http://localhost:4204/TestImpl?wsdl
You can use apache axis2 if you want to generate a Java client for it or just use a dynamic proxy like this:


   // this code can be placed rigth after InitialContext call, or 
   // can be in another program or in another thread in the same program
   // Of course, the program that made the call to InitContext need to be
   // alive for the EJB3 services to be exposed
   URL serviceUrl = new URL("http://localhost:4204/TestImpl?wsdl");
   Service testService = Service.create(serviceUrl, null);

   TestWs testWs = testService.getPort(TestWs.class);
   // test the methods you've implemented ...


You would be wondering how does it works ?

Well, as you request the initial context, openejb automatically searchs for clases in your classpath containing ejb3-related anotations, it automaticaly exposes them as it founds, more or less as it happens when you deploy an application as a .ear in any aplication server, but simpler and with great flexibility due to its embedable architecture.

UPDATE 10 / 29  / 2008
By default openejb serves only to localhost request, if you want to use the exposed webservice from other computers add the next properties to InitialContext(prop)
prop.setProperty("httpejbd.bind", "0.0.0.0");
prop.setProperty("ejbd.bind", "0.0.0.0");
and if you want to change the default port in use, change the next properties:
httpejbd.port, ejbd.bind
Suppose your machine has more than one IP and you want that openejb answers only to requests comming from only one of the IPs in the server, then put the desired IP instead of 0.0.0.0

Java builds made easy with FatJar

This plug-in allows you to deploy your working eclipse 'project' in one single jar with just one easy step. It finds all the dependencies your project currently depends on --Jars, External-Jars, User-Libraries, System-Libraries, Classes-Folders and Project-Exports are taken into account.

In the export wizard you can also select the main class for the jar being exported.

As far as I have used, it performs very well, though the project is still in beta stage. It works joining all the dependency clases and resources into one single jar, very handy for some situations where you develop some swing interfaces, or simple demons or small things like that. Give it a try to FatJar Eclipse Plug-in, it really worth !

Of course, this is not a replacement for tools such Ant or Maven, because this is a complete different approach for buildings. Do not use it for very big projects, but for small to medium sized applications I think will give you a lot less headaches than dealing with formal building tools, saving you time and effort while providing what you just need: a working Jar :)