Technical Blog
Monday, April 2, 2012
Thursday, January 26, 2012
Monitoring EhCache with JMX and Spring
EhCache provides an easy way to manage your caches with JMX. EhCache ManagementService class is the API entry point. You can easily integrate it in your Spring configuration files.
Here is how to do it
<bean id="managementService" class="net.sf.ehcache.management.ManagementService"
init-method="init"
destroy-method="dispose">
<constructor-arg ref="cacheManager"/>
<constructor-arg ref="mbeanServer"/>
<constructor-arg index="2" value="true"/>
<constructor-arg index="3" value="true"/>
<constructor-arg index="4" value="true"/>
<constructor-arg index="5" value="true"/>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>
After doing this, you will have access to your caches configuration and operations
such as cache flushing. You will also have access to useful statistics. These statistics will give you
critical information on how to configure your caches for an optimal use. Cache flushing can be useful in production if for some reason we have to flush cache.
Following are some screen shots from my local machine using jconsole.
Labels:
Ehcache,
JMX,
Monitor Ehcache
Monday, December 19, 2011
Maven-shade-plugin better than maven-assembly plugin
Recently i was working on a project where we need to create am executable jar with all its dependencies. When i started working on it, i used maven assembly plugin to create jar with its dependencies but the challenge that i faced was it was overwriting files with same name. As an example it was overwriting spring.handlers and spring.schemas files in META-INF directory and application unable to find some namespaces.
Then i came across maven shade plugin. You can use the maven-shade-plugin to package all dependencies into one uber-jar. It can also be used to build an executable jar by specifying the main class.
I found this plugin particularly useful as it merges content of specific files instead of overwriting them. This is needed when there are resource files that are have the same name across the jars and the plugin tries to package all the resource files.
Sample configuration is:
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>${appClass}</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
Please use the latest version of plugin because older version has some problems that were fixed in latest version.
Sunday, December 18, 2011
Application Configuration in Spring
If you have worked on any Spring application, I am sure you have used PropertyPlaceholderConfigurer to inject settings from external sources (most likely properties files) into application context.
One simple example could be database connection URL, Username, Password, as it changes as we move from environment to environment.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:datamigration.properties"/>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
You can achieve same thing using context:property-placeholder as well
<context:property-placeholder location="classpath:application.properties"/>
Next Challenge that we normally have is to externalize the properties file from our application so that same application can propagate to different environment. This can be achieved using 2 properties file instead of one.
- one bundled with application and
- one local properties file which can be anywhere on classpath (e.g in Tomcat lib directory).If local properties file is not present application will still work fine because we have defined ignoreResourceNotFound to true (bean definition below), In such a case application will use the properties file bundled with application.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath:datamigration.properties</value>
<value>classpath:datamigration-local.properties</value>
</list>
</property>
</bean>
Having a local property file is a good trick for web applications, but i recently faced a scenario where i was working on a standalone data migration application which creates a jar and i had to externalize the property file to override properties. I didn't want to hardcode the property file name as well, so i used the following bean definition which did the trick for me.
<bean id="placeholderProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="true"/>
<property name="locations">
<list>
<value>classpath:datamigration.properties</value>
<value>file:${config}</value>
</list>
</property>
</bean>
If you examine the above definition and try to apply to overridden property file logic here, you will notice that,
Now next question is how to pass the property file location to application? If you check above bean definition there is another property that i am setting for System properties mode, which is used to override/set any property.
- I am planning to pick overridden property file from file location instead of classpath location.
- Overridden property file location is not hard coded in application.
Now if i run my application like
java -Dconfig=C:\\Temp\\datamigration-local.properties -jar target\datamigration-1.0.0-SNAPSHOT.jar datamigration.xml migrateCollegeData
This will do the trick because config location will be passed as parameter and all overridden properties can be mentioned there.
Hope this helps. Comments/Thoughts/Feedback???
Saturday, October 22, 2011
Adding SCM Revision number in manifest file using maven plugin (buildnumber-maven-plugin)
One of the requirement in my project was to create an entry of last SCM Revision number in web app manifest file every time a release build is done. We achieved the same using buildnumber-maven-plugin. Following are the steps to use buildnumber-maven-plugin.
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<getRevisionOnlyOnce>true</getRevisionOnlyOnce>
<useLastCommittedRevision>true</useLastCommittedRevision>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<manifest>
<addDefaultImplementationEntries>true
</addDefaultImplementationEntries>
</manifest>
<archive>
<manifestEntries>
<SVN-Revision>${buildNumber}</SVN-Revision>
<BuildScmBranch>${buildScmBranch}</BuildScmBranch>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
</plugin>
Result: You will see following entries in war Manifest file
BuildScmBranch: This will have a value populated if you are building from tag or branch
SVN-Revision: 9596
Note: Configuration options are easy and self explanatory. Also we decide to use this with maven-war-plugin. Same can be achieved for jar as well.
- Add build number plugin in your pluginManagement section of parent pom (if you have parent child maven modules)
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
<getRevisionOnlyOnce>true</getRevisionOnlyOnce>
<useLastCommittedRevision>true</useLastCommittedRevision>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<manifest>
<addDefaultImplementationEntries>true
</addDefaultImplementationEntries>
</manifest>
<archive>
<manifestEntries>
<SVN-Revision>${buildNumber}</SVN-Revision>
<BuildScmBranch>${buildScmBranch}</BuildScmBranch>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
- Use the plugin in child project where you are assembling web app (We used it only for the profile that does release build)
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
</plugin>
Result: You will see following entries in war Manifest file
BuildScmBranch: This will have a value populated if you are building from tag or branch
SVN-Revision: 9596
Note: Configuration options are easy and self explanatory. Also we decide to use this with maven-war-plugin. Same can be achieved for jar as well.
JAX-WS - Request and Response Logging
One of the things people want to do while developing Web Services is to look at what the client is sending and receiving. To monitor soap traffic, there are some GUI tools like TCP Monitor and WSMonitor. These monitors are implemented with a 'man in the middle' approach where-in, the monitor listens to a port (Client send requests to this port) and forwards it to another port (Server listens to this port). Since these tools use port forwarding, you need to change your Web Service client to send request to the port where the monitor listens (Especially, if you are using static clients generated by wsimport, the default endpoint address taken from the wsdl needs to be overidden by setting ENDPOINT_ADDRESS_PROPERTY on the proxy).
In JAX-WS, you can monitor the request and response messages without changing the client. When you invoke the Web Service, just pass the system property com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true, it prints out the request and response message.
In one of Spring based project we were using couple of SOAP based webservices. We controlled logging of messages using a spring bean which is backed by a Spring property to enable/disable logging.
<bean id="sysProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" value="#{@systemProperties}"/>
<property name="targetMethod" value="putAll"/>
<property name="arguments">
<util:properties>
<prop key="com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump">${soap.request.logging.enabled}</prop>
</util:properties>
</property>
</bean>
Externalize log4j - Log4jConfigurer
In one of Spring based project we wanted to externalize log4j file and wanted to control log4j location and refresh interval using spring property file,
Reason: Spring property files has good layering ability and by externalizing log4j, application redeployment is not required if log4j needs to be changed.
This can be achieved pretty easily in Spring. by creating a bean
<bean id="log4jInitialization"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.util.Log4jConfigurer"/>
<property name="targetMethod" value="initLogging"/>
<property name="arguments">
<list>
<value>${log4j.config.location}</value>
<value>${log4j.refresh.interval}</value>
</list>
</property>
</bean>
Now when application context will be initialized, log4j will be configured. Location and refresh interval will be controlled via spring property.
Spring has Log4jConfigListener as well, which can be configured in web.xml but spring property place holders can not be used in web.xml. Hence i didn't use it.
Note: Above setup assumes an expanded WAR file, both for loading the configuration file and for writing the log files.
Reason: Spring property files has good layering ability and by externalizing log4j, application redeployment is not required if log4j needs to be changed.
This can be achieved pretty easily in Spring. by creating a bean
<bean id="log4jInitialization"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass"
value="org.springframework.util.Log4jConfigurer"/>
<property name="targetMethod" value="initLogging"/>
<property name="arguments">
<list>
<value>${log4j.config.location}</value>
<value>${log4j.refresh.interval}</value>
</list>
</property>
</bean>
Now when application context will be initialized, log4j will be configured. Location and refresh interval will be controlled via spring property.
Spring has Log4jConfigListener as well, which can be configured in web.xml but spring property place holders can not be used in web.xml. Hence i didn't use it.
Note: Above setup assumes an expanded WAR file, both for loading the configuration file and for writing the log files.
Subscribe to:
Posts (Atom)