Friday, June 22, 2012

Using perf4j to time methods

Perf4j is a great way to instrument your code to find out how long your methods are taking to execute.  I wanted a way to annotate my method and not have to pollute the code with startTimer, endTimer stuff.
Enter Perf4j's annotation based approach, implemented with aspectj AOP framework. Perfect!

Add the following maven dependencies to your pom
      <dependency>  
       <groupId>org.perf4j</groupId>  
       <artifactId>perf4j</artifactId>  
       <version>0.9.16</version>  
     </dependency>  
     <dependency>  
      <groupId>org.aspectj</groupId>  
      <artifactId>aspectjrt</artifactId>  
      <version>1.6.7</version>  
     </dependency>  
     <dependency>  
       <groupId>aspectj</groupId>  
       <artifactId>aspectjweaver</artifactId>  
       <version>1.5.4</version>  
     </dependency>  
     <dependency>  
       <groupId>commons-jexl</groupId>  
       <artifactId>commons-jexl</artifactId>  
       <version>1.1</version>  
     </dependency>  

Create the aop.xml file in the main/resources/META-INF/ folder.
 <?xml version="1.0" encoding="UTF-8"?>  
 <aspectj>  
  <!--  
   We only want to weave in the log4j TimingAspect into the @Profiled classes.  
   Note that Perf4J provides TimingAspects for the most popular Java logging  
   frameworks and facades: log4j, java.util.logging, Apache Commons Logging  
   and SLF4J. The TimingAspect you specify here will depend on which logging  
   framework you wish to use in your code.  
  -->  
  <aspects>  
   <aspect name="org.perf4j.log4j.aop.TimingAspect"/>  
   <!-- if SLF4J/logback use org.perf4j.slf4j.aop.TimingAspect instead -->  
  </aspects>  
  <weaver options="-verbose -showWeaveInfo">  
   <!--  
    Here is where we specify the classes to be woven. You can specify package  
    names like com.company.project.*  
   -->  
   <include within="com.yourpackage.*"/>  
   <include within="org.perf4j.log4j.aop.*"/>  
  </weaver>  
 </aspectj>  

Add the following to your log4j file
 <!-- Perf4J appenders -->  
   <!--  
    This AsyncCoalescingStatisticsAppender groups StopWatch log messages  
    into GroupedTimingStatistics messages which it sends on the  
    file appender defined below  
   -->  
   <appender name="CoalescingStatistics"  
        class="org.perf4j.log4j.AsyncCoalescingStatisticsAppender">  
     <!--  
      The TimeSlice option is used to determine the time window for which  
      all received StopWatch logs are aggregated to create a single  
      GroupedTimingStatistics log. Here we set it to 10 seconds, overriding  
      the default of 30000 ms  
     -->  
     <param name="TimeSlice" value="600000"/>  
     <appender-ref ref="fileAppender"/>  
     <!--  
      Note how the GraphingStatisticsAppenders have been attached to the  
      CoalescingStatistics here.  
     -->  
     <appender-ref ref="graphExecutionTimes"/>  
     <appender-ref ref="graphExecutionTPS"/>  
   </appender>  
   <!-- This file appender is used to output aggregated performance statistics -->  
   <appender name="fileAppender" class="org.apache.log4j.FileAppender">  
     <param name="File" value="/logs/perfStats.log"/>  
     <layout class="org.apache.log4j.PatternLayout">  
       <param name="ConversionPattern" value="%m%n"/>  
     </layout>  
   </appender>  
   <!--  
    This first GraphingStatisticsAppender graphs Mean execution times for the  
    firstBlock and secondBlock tags  
   -->  
   <appender name="graphExecutionTimes"  
        class="org.perf4j.log4j.GraphingStatisticsAppender">  
     <!-- Possible GraphTypes are Mean, Min, Max, StdDev, Count and TPS -->  
     <param name="GraphType" value="Mean"/>  
     <!-- The tags of the timed execution blocks to graph are specified here -->  
     <param name="TagNamesToGraph" value="firstBlock,secondBlock"/>  
     <appender-ref ref="graphsFileAppender"/>  
   </appender>  
   <!--  
    This second GraphingStatisticsAppender graphs transactions per second  
    for the firstBlock and secondBlock tags  
   -->  
   <appender name="graphExecutionTPS"  
        class="org.perf4j.log4j.GraphingStatisticsAppender">  
     <param name="GraphType" value="TPS"/>  
     <param name="TagNamesToGraph" value="firstBlock,secondBlock"/>  
     <appender-ref ref="graphsFileAppender"/>  
   </appender>  
   <!--  
    This file appender is used to output the graph URLs generated  
    by the GraphingStatisticsAppenders  
   -->  
   <appender name="graphsFileAppender" class="org.apache.log4j.FileAppender">  
     <param name="File" value="perfGraphs.log"/>  
     <layout class="org.apache.log4j.PatternLayout">  
       <param name="ConversionPattern" value="%m%n"/>  
     </layout>  
   </appender>  
   <!-- Loggers -->  
   <!--  
    The Perf4J logger. Note that org.perf4j.TimingLogger is the value of the  
    org.perf4j.StopWatch.DEFAULT_LOGGER_NAME constant. Also, note that  
    additivity is set to false, which is usually what is desired - this means  
    that timing statements will only be sent to this logger and NOT to  
    upstream loggers.  
   -->  
   <logger name="org.perf4j.TimingLogger" additivity="false">  
     <level value="INFO"/>  
     <appender-ref ref="CoalescingStatistics"/>  
   </logger>  

Add the @Profiled annotation to your code and off you go!
A file called perfStats.log is created with the stats.  There are parameters that can be tuned and graph based appenders that you can use as well.  For more details please check out perf4j Developer Guide

Update: 

If you are deploying to tomcat; to enable load time weaving; you will need to add 
-javaagent:<location_of_aspectjweaver.jar> to JAVA_OPTIONS.  

Thursday, June 14, 2012

JAXB schema validation

Say you have defined an xsd, which has certain restrictions in elements.  You would expect that marshaling the instance will execute the restrictions that are defined in the schema. These restrictions could be like pattern matches, length restriction, etc.  Well, it doesn't enforce those restrictions.
In order to get these restrictions enforced, do the following

 public static void validateJAXBObject(@SuppressWarnings("rawtypes") Class jaxbClass, Object instance) throws JAXBException, SAXException  
   {  
     JAXBContext jaxbContext = getContext(jaxbClass);  
     Marshaller marshaller = jaxbContext.createMarshaller();  
     SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);  
     Schema schema = factory.newSchema(jaxbClass.getResource(<xsd_file>));  
     marshaller.setSchema(schema);  
     marshaller.marshal(instance, new StringWriter());  
   }  

Thursday, May 31, 2012

Generating the @XmlRootElement for JAXB objects


Make sure you have a jaxb binding file which looks like
 <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0" xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">  
 <jaxb:globalBindings>  
 <xjc:simple/>  
 </jaxb:globalBindings>  
 </jaxb:bindings>   


In your xsd define your element like:
 <xs:complexType name="FenceDefinition">  
 ..  
 </xs:complexType>  
 <xs:element name="artifact" type="FenceDefinition"/>  
 
Run the xjc compiler: 
 xjc -p <package-name> -xmlschema -d <gen-directory> -verbose -b jaxb.binding -extension <xsd-file>   

Wednesday, April 4, 2012

Connecting to a https URL which has a self signed certificate

In scenarios where a REST resource (or any URL) is only accessible via https and has a self signed certificate, you wont be able to connect using a regular http connection.  You will see the following exception.

javax.net.ssl.SSLHandshakeException: ...

So to get around this, grab the certificate using your browser. You can connect to the URL and based on the browser you should be able to download the certificate locally.  
Use the keytool command to convert the .crt file to a .jks file using the following command.
 $ keytool -import -file ngle_test.crt -alias server -keystore ngle_test-1.jks  
 Enter keystore password:  
 Re-enter new password:  
 Trust this certificate? [no]: yes  
 Certificate was added to keystore  
Once you have the certificate in the .jks format, you can 2 choices.  You can upload the certificate to the default cacerts file that is packaged with the jre or in cases where this is not feasible, load the certificate in the java code.
I'm using apache http client.  The resource is also using basic-auth.
 final DefaultHttpClient httpclient = new DefaultHttpClient();  
 try  
 {  
  final KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());  
  trustStore.load(RestfulClient.class.getResourceAsStream("/ngle_test1.jks"),<certificate_password>.toCharArray());  
  final SSLSocketFactory socketFactory = new SSLSocketFactory("TLS", null, null, trustStore, null, null,  
   SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //Doesn't check if the hostname on the certificate matches the host in the https URL  
  final Scheme sch = new Scheme("https", 8080, socketFactory);  
  httpclient.getConnectionManager().getSchemeRegistry().register(sch);  
  // Basic Auth Start  
  final HttpHost targetHost = new HttpHost(<HTTPSurlHost>, <HTTPSurlPort>, "https");  
  httpclient.getCredentialsProvider().setCredentials(  
   new AuthScope(<HTTPSurlHost>, <HTTPSurlPort>)),  
   new UsernamePasswordCredentials(<basicAuthUsername>, <basicAuthPassword>));  
  // Create AuthCache instance  
  final AuthCache authCache = new BasicAuthCache();  
  // Generate BASIC scheme object and add it to the localauth cache  
  final BasicScheme basicAuth = new BasicScheme();  
  authCache.put(targetHost, basicAuth);  
  // Add AuthCache to the execution context  
  final BasicHttpContext localcontext = new BasicHttpContext();  
  localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);  
  // Basic Auth End  
  final HttpGet httpget = new HttpGet(ngleURL);  
  final HttpResponse response = httpclient.execute(targetHost, httpget, localcontext);  
  final HttpEntity entity = response.getEntity();  
  final String result = EntityUtils.toString(entity);  
  EntityUtils.consume(entity);  
 }  
 catch (Exception e)  
 {  
  LOG.error(e.getMessage());  
 }  
 finally  
 {  
  // When HttpClient instance is no longer needed,  
  // shut down the connection manager to ensure  
  // immediate deallocation of all system resources  
  httpclient.getConnectionManager().shutdown();  
 }  

Monday, March 19, 2012

How to change the responseType in a cxf RESTful service

Say you have the following as a RESTservice
 @Path("/loc")  
 @GET  
 @Consumes  
 @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })  
 public String getLocation(...)   
 {  
     ..  
  }  
This method produces XML or JSON based on the Accept Header that is passed in.
If you had to figure out a way to override the Accept Header value and always generate JSON, how would you do it?
CXF interceptors allows you to achieve this elegantly.
Register a OutInterceptor in your beans.xml
 public class CustomOutInterceptor extends AbstractPhaseInterceptor<Message>  
 {  
 public CustomOutInterceptor()  
 {  
  super(Phase.PRE_STREAM);  
 }  
 public void handleMessage(final Message message) throws Fault  
 {  
   final List<MediaType> mediaTypeL = new ArrayList<MediaType>();  
   //Return JSON always  
   mediaTypeL.add(MediaType.APPLICATION_JSON_TYPE);  
   message.getExchange().put(Message.ACCEPT_CONTENT_TYPE, mediaTypeL);  
 }  
 }  

Tuesday, January 17, 2012

Create sample web app project in Eclipse using m2eclipse

Make sure you have m2eclipse installed from the update site http://m2eclipse.sonatype.org/sites/m2e
Key here is to also install the m2e-extras which allows for WTP integration.
Install m2e-extras from http://m2eclipse.sonatype.org/sites/m2e-extras

In Eclipse
    File -- New -- Other -- Maven -- Maven Project -- Next

In the New Maven Project dialog select
Group Id: org.apache.maven.archetypes
Artifact Id: maven-archetype-webapp

Provide a GroupId and ArtifactId for your project and thats all there is to it.

Wednesday, January 4, 2012

A way to test REST resource

While looking around for an easy way to test REST APIs, I stumbled across rest-assured
This is a very simple and elegant way to test your code.

Add the following to your pom.xml
 <dependency>  
     <groupId>com.jayway.restassured</groupId>  
     <artifactId>rest-assured</artifactId>  
     <version>1.5</version>  
     <scope>test</scope>  
 </dependency>  

Your test will look something like ..
 public void testInvalidInputInvalidDelayTol()  
 {  
  with().  
   parameters(.....).  
  expect().  
   statusCode(400).  
   body(  
    equalToIgnoringWhiteSpace("....")  
   ).  
  when().  
   with().authentication().preemptive().basic("username", "password").  
   get("/network-adapter/network");  
 }  


Rest-assured supports various response formats like json, xml.  Explore the rest-assured wiki to learn more.