Thursday, December 22, 2011

CXF logging of inbound and outbound messages

Add the following snippet to beans.xml
<!-- Following logs all inbound and outbound messages -->
    <cxf:bus>
        <cxf:features>
            <cxf:logging />
        </cxf:features>
    </cxf:bus>

This will record all the inbound and outbound messages.

Note: I found an issue using the LoggingOutInterceptor explicitly.  On a SOAP Fault, the outgoing message would not be recorded if you used the LoggingOutInterceptor.  Using the logging feature on the bus fixed it, also, you will only have to define the logging once and it will work for all the services defined in the beans.xml.






Thursday, December 1, 2011

XML Parsing error

Sometimes while parsing an xml document, you might hit the following error:
[Fatal Error] :2:6: The processing instruction target matching "[xX][mM][lL]" is not allowed.

This cryptic error is because the xml-string has whitespace preceeding the <xml ..> tag.  Use trim() to get rid of the whitespace and off you go!



Wednesday, October 26, 2011

Properties file

Use case: Use the same property file across deployment environments.

I like the idea of using the same war/ear being deployed/promoted through the deployment life-cycle.  I have seen projects, where the properties are stored in files like dev.properties test.properties and the build tool decides which property file to choose for each build.  This means a different build per environment.

To achieve this it is very simple using Apache Commons Configuration


My properties file looks like:

environment=${sys:env}
#Properties that do not vary per environment
a.general.property=propertyValue 

#Properties that vary
dev.a.property=value
test.a.property=value2
prod.a.property=value3


The java code is as follows:

        String fName = "C:\\Users\\config.properties";
       
        CompositeConfiguration
compositeConfig = new CompositeConfiguration();
       
        try
        {
            //Load the properties file
            PropertiesConfiguration pc = new PropertiesConfiguration(configFile);
            //Get the environment name, usually passed in as a -D parameter
            String prefix = pc.getString("environment");
            log.info("prefix is " +prefix);
            //Filter the configuration with the environment prefix
            Configuration envConfig =  pc.subset(prefix);
           
            log.trace(ToStringBuilder.reflectionToString(envConfig));
            //Add the filtered configuration to the composite
            compositeConfig.addConfiguration(envConfig);
            //Add the complete configuration to the composite, so that we have access to the non-environment specific properties
            compositeConfig.addConfiguration(pc);
        } catch (ConfigurationException e)
        {
            log.error("Error while reading properties.", e);
        }
Now to access a property, you will need to call compositeConfig.getProperty("a.property");  
This will return the right value depending on which environment that the application is running at.

Note:
  1. You will need to have an environment variable env set.  For development it will be set as -Denv="dev" and so on...
  2. The first property environment=${sys:env} will automagically be replaced by the PropertiesConfiguration class, no special processing is necessary.








Monday, October 24, 2011

Spring LDAP Pool implementation

If you need to use a pool to hold your LDAP connections, then you will setup the ldap bean properties in your beans.xml like so:
 <bean id="contextSource"  
     class="org.springframework.ldap.pool.factory.PoolingContextSource">  
     <property name="contextSource" ref="contextSourceTarget" />  
     <property name="dirContextValidator" ref="dirContextValidator" />  
     <property name="testOnBorrow" value="true" />  
     <property name="testWhileIdle" value="true" />  
     <property name="timeBetweenEvictionRunsMillis" value="${ldapPool.timeBetweenEvictionRunsMillis}" />  
     <property name="minEvictableIdleTimeMillis" value="${ldapPool.minEvictableIdleTimeMillis}" />  
     <property name="maxActive" value="${ldapPool.maxActiveConnections}" />  
     <!-- Open up "minIdle" connections when first request comes in -->  
     <property name="minIdle" value="${ldapPool.initialPoolSize}" />  
     <!-- maxIdle: set this, or it uses the default of 8 -->  
     <property name="maxIdle" value="${ldapPool.maxActiveConnections}" />  
     <!-- Round robin -->  
     <property name="lifo" value="false" />  
   </bean>  
   <bean id="dirContextValidator" class="org.springframework.ldap.pool.validation.DefaultDirContextValidator" />  
   <bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource">  
     <property name="url" value="${ldapConfig.url}" />  
     <property name="base" value="${ldapConfig.base}" />  
     <property name="userDn" value="${ldapConfig.userDN}" />  
     <property name="password" value="${ldapConfig.password}" />  
     <property name="pooled" value="false" />  
   </bean>  
   <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">  
     <constructor-arg ref="contextSource" />  
   </bean>  
   <bean id="myDao" class="com....DAOImpl">  
     <property name="ldapTemplate" ref="ldapTemplate" />  
   </bean>  
This has been well defined in the spring ldap tutorials.

We had requirements to be able to open up a fixed number of connections to the ldap server on startup of the pool.  In other words pre-populate the pool with the connections.
Since the spring ldap pool is using the apache commons pool - in particular the GenericKeyedObjectPool, we came across the minIdle property.
"minIdle sets a target value for the minimum number of idle objects (per key) that should always be available. If this parameter is set to a positive number and timeBetweenEvictionRunsMillis > 0, each time the idle object eviction thread runs, it will try to create enough idle instances so that there will be minIdle idle instances available under each key. This parameter is also used by preparePool if true is provided as that method's populateImmediately parameter. The default setting for this parameter is 0."
Setting the minIdle property didn't seem to do anything.  It looked like the preparePool method was not being invoked.
So, the work around was to extend the org.springframework.ldap.pool.factory.PoolingContextSource and calling the preparePool method on the keyedObjectPool object.

Another issue we found was that the lifo property of the apache commons pool configuration was not supported.  Now since we had already extended the PoolingContextSource class, it was trivial to set the lifo property on the pool.

In case you have a pool of more than 8 active connections, you should set the maxIdle property.  If this is not set you will never see the pool size increase more than 8.  Also, you will see connections being closed and new ones being opened and put in the pool when the load (requests) increase more than 8.  (The implementation uses a default of 8)



Friday, October 21, 2011

CXF Rest service learnings

Things I learned while developing a CXF REST service


Use the @Encoded annotation to preserve characters like "+".  I had a situation where I needed to support the "+" character as an argument in a REST service. 

Below is a contrived example of what I mean:
@GET
public String getCustomer(@QueryParam("searchString") String searchString)
If you needed to pass a "+" to this method, it will get converted to a space character.  To over come this behavior use
@GET
public String getCustomer(@Encoded @QueryParam("searchString") String searchString)