Thursday, May 27, 2010

Creating New Partition and File System in Linux

Creating a new partition and file system, a.k.a formatting in Windows world is very easy. We can do that in just few clicks (right click, format, and select the file system). Creating a new partition and file system in Linux, however, is not that easy. Here I'm gonna show you how to do it.

You need to run these steps as root.
1. Run 'fdisk '
Example:
# fdisk /dev/sdb
If you're creating a new partition in the first SATA/SCSI disk, the device name will be /dev/sda, if it's a second SATA/SCSI disk, it'll be /dev/sdb and so on. If the device is the first master IDE disk, it'll be /dev/hda and so on.
2. Choose n to add a new partition.
3. Choose e for extended or p for primary.
4. Accept the default values for first and last cylinder if you wish to partition the whole disk.
5. Choose w to write the table to disk.
If suppose you've created the first partition in the second SATA/SCSI disk, you should be able to see that /dev/sdb1 has been created in your file system.
6. The next step is to create a file system on that partition. The command is 'mkfs -t '
Example:
# mkfs -t ext4 /dev/sdb1
The here can be ext2, ext3, ext4, etc. The here should be /dev/sdb1 and NOT /dev/sdb.
7. The last step is to mount this partition. To do that, execute 'mount -t '
Example:
# mkdir -p /mnt/newdisk
# mount -t ext4 /mnt/newdisk
To see if your partition has been mounted successfully. Run 'mount' or 'cat /etc/mtab'.
To mount it permanently, you need to create a new entry in the /etc/fstab as shown below.
/dev/sdb1            /mnt/newdisk         ext4       acl,user_xattr        1 2
The value last second option 1 specifies whether or not the file system should be dumped. 1 means dump. 0 means don't dump.
The value last option 2 specifies the order in which fsck should check the file system at reboot. For root partition, it should be 1, other partitions should be 2.

Tuesday, May 25, 2010

AspectJ Load-Time Weaving

AspectJ has two weaving models, build-time and load-time. Here I'm gonna talk about binary load-time weaving. The good thing about it is that we can create a separate Java project and AspectJ project and weave them at runtime. This can be achieved thanks to JVMTI. Hence, it requires Java 5 and above.

Let's say we have a Java project called my-java-project.

HelloWorld.java
package myproject;

public class HelloWorld {
    
    public void sayHello(String message) {
        System.out.println(message);
    }
}

Main.java
package myproject;

public class Main {

    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.sayHello("Hello World");
    }
}

And an AspectJ project called my-aspectj-project.

HelloWorldAspect.java
package myproject;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class HelloWorldAspect {

    @Around("execution(* myproject.HelloWorld.sayHello(..))")
    public Object aroundAspect(ProceedingJoinPoint joinPoint) {
        System.out.println("Before sayHello()");
        Object obj = null;
        try {
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("After sayHello()");
        return obj;
    }
}

Here we also need to add META-INF/aop.xml inside this AspectJ jar.

aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
    <aspects>
        <aspect name="myproject.HelloWorldAspect" />
    </aspects>
</aspectj>

To run, execute this from the commaand line.
java -javaagent:aspectjweaver-1.5.4.jar -cp my-aspectj-project-0.0.1-SNAPSHOT.jar:my-java-project-0.0.1-SNAPSHOT.jar:aspectjrt-1.6.7.jar myproject.Main

Monday, May 24, 2010

Mixin in Groovy and Java

Mixin is the ability to mix certain functionalities into other classes, i.e. to add new methods into other classes.

Because of the dynamic nature of Groovy, it's very straightforward to use mixin in Groovy. All we need to do is to call mixin in a class that we want to mix in as shown in the example below.

class Laughable {
    def laugh() {
        println "Hahaha"
    }
}

class Person {
}

Person.mixin(Laughable)

Person person = new Person()
person.laugh()

In Java, however, it's not that straightfoward to implement mixin. Luckily, we have AspectJ that can help to do that. Here I'm gonna show you how to use mixin using @AspectJ syntax.

Laughable.java
package myproject;

public interface Laughable {

    public void laugh();
}

LaughableImpl.java
package myproject;

public class LaughableImpl implements Laughable {

    @Override
    public void laugh() {
        System.out.println("Hahaha");
    }
}

Person.java
package myproject;

public class Person {
}

All we need here is to declare @DeclareMixin annotation.

LaughableAspect.java
package myproject;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareMixin;

@Aspect
public class LaughableAspect {

    @DeclareMixin("myproject.Person")
    public Laughable identifiable() {
        return new LaughableImpl();
    }
}


The ugly part here is that we need to typecast the person object into Laughable interface.
Main.java
package myproject;

public class Main {

    public static void main(String[] args) {
        Person person = new Person();
        Laughable laughable = (Laughable) person;
        laughable.laugh();
    }
}

Sunday, May 23, 2010

Create ISO Images on Linux

Creating ISO images on Linux is very straightforward. Unlike in Windows, you don't need any additional tool to install. You just need to type this in your terminal.

dd if=/dev/cdrom of=image.iso

Most Linux distros nowadays have a graphical utility to let you mount the ISO image. If you prefer to do it in command line, here is how to do it.

mkdir -p /mnt/myimage
mount -o loop -t iso9660 cd.iso /mnt/myimage

Friday, May 21, 2010

Escaping HTML String using Groovy

As all of you know, I use SyntaxHighlighter for formatting the source code. If let's say you have HTML or XML source, you need to escape it first in order for SyntaxHighlighter to display it correctly.

I created a small utility for that purpose. Make sure you include Apache commons-lang in your classpath.

import org.apache.commons.lang.StringEscapeUtils

validateArgs(this.args)

new File(this.args[0]).eachLine {
    println StringEscapeUtils.escapeHtml(it)
}

def validateArgs(def args) {
    if (args.size() != 1) {
        printUsage()
        System.exit(1)
    }

    if (!new File(args[0]).isFile()) {
        printUsage()
        System.exit(1)
    }
}

def printUsage() {
    println "Usage: HtmlEscape.groovy <file>"
}

Wednesday, May 19, 2010

AspectJ Inter-type Declaration

AspectJ is a very powerful AOP framework. It's most commonly used for logging, security, transaction, etc. Besides that, AspectJ has a powerful feature that allows you to add a method or a field to a class, or declare a type that implement an interface. I will show you how it can be done in AspectJ.

Here, we intend to add a new method, called sayBye(String message) into HelloWorld.
HelloWorld.java
package myproject;

public class HelloWorld {

    public void sayHello(String message) {
        System.out.println(message);
    }
}

We create a new interface called ByeWorld and make HelloWorld class to implement it.
ByeWorldAspect.aj
package myproject;

public aspect ByeWorldAspect {

    declare parents: HelloWorld implements ByeWorld;

    public void ByeWorld.sayBye(String message) {
        System.out.println(message);
    }

    before(ByeWorld byeWorld)
        : execution(* ByeWorld+.*(..))
            && !execution(* ByeWorld.*(..))
            && this(byeWorld) {
    }

    private static interface ByeWorld {
    }
}

Main.java
package myproject;

public class Main {

    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.sayHello("Hello World!");
        helloWorld.sayBye("Bye World!"); // There is no sayBye() in HelloWorld class!
    }
}

Make sure you add failOnError to true in the maven-compiler-plugin.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>myproject</groupId>
    <artifactId>aspectj-project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.7</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6<source>
                    <target>1.6</target>
                    <failOnError>false</failOnError>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <source>1.6</source>
                            <target>1.6</target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>myproject.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Although this feature is very powerful, my advice is not to overuse it because it can lead your code into an unmaintainable state. Remember, great power comes with great responsibility :)

Metro and Apache CXF Tutorial

Metro and Apache CXF are both popular web service frameworks. Both implement JAX-WS specification. Apache CXF uses Spring, so the configuration can be a bit complex, but it offers more features, such as JAX-RS as compared to Metro. Since Apache CXF is based on Spring, it has a lot of dependencies with other libraries. On the other hand, Metro is a lightweight web service framework. So, it can be a good choice if you prefer something simple and lightweight. Metro is the default web service implementation in GlassFish.

Let's build a typical hello world application.

HelloWorld.java
package myproject;

import javax.jws.WebService;

@WebService
public interface HelloWorld {

    String sayHello(String msg);
}

HelloWorldImpl.java
package myproject;

import javax.jws.WebService;

@WebService
public class HelloWorldImpl implements HelloWorld {

    @Override
    public String sayHello(String msg) {
        return msg;
    }
}

The beauty of JAX-WS specification is that you can switch to different implementations with minimal changes as shown below.

For Apache CXF
cxf-myproject.xml (place this file in src/main/webapp/WEB-INF)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:soap="http://cxf.apache.org/bindings/soap"
    xsi:schemaLocation="
         http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxws
         http://cxf.apache.org/schemas/jaxws.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <jaxws:endpoint id="helloWorld" implementor="myproject.HelloWorldImpl"
        address="/helloWorld">
    </jaxws:endpoint>
</beans>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>webservices-project</display-name>
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/cxf-myproject.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

pom.xml
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-bundle</artifactId>
    <version>2.2.6</version>
</dependency>
<dependency>
    <groupId>org.apache.cxf</groupId>
    <artifactId>cxf-rt-frontend-jaxws</artifactId>
    <version>2.2.6</version>
</dependency>

For Metro (the sun-jaxws.xml is optional if you deploy it in GlassFish)
sun-jaxws.xml (place this file in src/main/webapp/WEB-INF)
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
    version="2.0">

    <endpoint name="helloWorld" implementation="myproject.HelloWorldImpl"
        url-pattern="/helloWorld" />
</endpoints>

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>webservices-project</display-name>
    <listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>MetroServlet</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MetroServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

pom.xml
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-rt</artifactId>
    <version>2.1.4</version>
</dependency>
<dependency>
    <groupId>org.jvnet</groupId>
    <artifactId>mimepull</artifactId>
    <version>1.3</version>
</dependency>

jaxws-rt depends on mimepull 1.2 and at this time of writing, mimepull 1.2 is not available in central repo, so I use mimepull 1.3 instead.

To run the sample application, just type 'mvn clean jetty:run'.

Wednesday, May 12, 2010

How to Export to HTML in soapUI Open Source Edition

soapUI Pro has a feature to export the test result in HTML format. The open source edition can only export the test result in XML and text. I wrote a small utility to export the test result in HTML format.

I make use of Groovy templating engine here. Feel to modify it according to your needs.

To run the script, you need to include the commons-lang in the classpath and place the report.template in the same directory as the RunSoapUiTest.groovy. Enjoy :)

RunSoapUiTest.groovy
import groovy.text.GStringTemplateEngine
import org.apache.commons.lang.StringEscapeUtils

final TEMPLATE_FILE = "report.template"

class TestSuite {
    def name
    def numTestCases
    def numFailures
    def testCases
}

class TestCase {
    def name
    def status
    def type
    def time
}

def createReport(def template, def testSuite, def outputFile) {
    def templateFile = new File(template)
    def outFile = new File(outputFile)
    if (outFile.exists()) {
        outFile.renameTo(new File(outFile.path + "." + new Date(outFile.lastModified()).format("yyyyMMdd-HHmmss")))
    }
    def binding = ["testSuite":testSuite]
    def t = new GStringTemplateEngine().createTemplate(templateFile).make(binding)
    def writer = new PrintWriter(outputFile)
    try {
        t.writeTo(writer)
    } finally {
        writer?.close()
    }
}

def getTestSuite(def testResultDir) {
    def testSuite = new TestSuite()
    testSuite.numTestCases = 0
    testSuite.numFailures = 0
    testSuite.testCases = []
   
    def dir = new File(testResultDir)
    dir.eachFile { file ->
        if (file.name.endsWith(".txt")) {
            def splitStr = file.name.split('-')
            testSuite.name = splitStr[0]
            testSuite.numTestCases += 1
            testSuite.numFailures += (splitStr[splitStr.size()-1].startsWith("OK")) ? 0 : 1
           
            def testCase = new TestCase()
            testCase.name = ''
            testCase.type = '
'
           
            (1..splitStr.size()-3).each {
                testCase.name += splitStr[it] + ' '
            }
            testCase.status = (splitStr[splitStr.size()-1].startsWith("OK")) ? 'Success' : 'Failure'
            def content = false
            file.eachLine { line ->
                if (line.startsWith('Time Taken')) {
                    testCase.time = line.split(':')[1].trim()
                } else if (line.contains('- Request -')) {
                    content = true
                }   
               
                if (content) {
                    testCase.type += StringEscapeUtils.escapeHtml(line) + '\n
'
                }
            }
            testCase.type += '
' testSuite.testCases += testCase } } return testSuite } def printUsage() { println "Usage: groovy RunSoapUiTest.groovy <test_suite_name> <soapUI_project> <test_results_dir> [host:port]" } def validateArgs(def args) { if (args.size() >= 3 && args.size() <= 4) { if (!new File(args[1]).isFile()) { return false } if (!new File(args[2]).isDirectory()) { return false } } return true } def cleanUp(def dir) { new File(dir).eachFile { file -> if (file.name.endsWith(".xml") || file.name.endsWith(".txt")) { file.delete() } } } if (System.env['SOAPUI_HOME'] == null) { println "Please set the SOAPUI_HOME environment variable" System.exit(1) } println "SOAPUI_HOME=${System.env['SOAPUI_HOME']}" if (!validateArgs(this.args)) { printUsage() System.exit(1) } def testSuiteName = args[0] def soapUiProject = args[1] def testResultsDir = args[2] def host = (args.size() == 4) ? "-h" + args[3] : "" def cmd = "\"${System.env['SOAPUI_HOME'] + File.separator + "bin" + File.separator + "testrunner"}\" " + "${host} -s\"${testSuiteName}\" -a -j -f \"${testResultsDir}\" -I \"${soapUiProject}\"" println "Command=${cmd}" cmd.execute().waitForProcessOutput(System.out, System.err) def testSuite = getTestSuite(testResultsDir) createReport(TEMPLATE_FILE, testSuite, testResultsDir + File.separator + testSuiteName + "_TestReport-" + Calendar.getInstance().format("yyyyMMdd") + ".html") cleanUp(testResultsDir) println "***** Done *****"

report.template
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html xmlns:stringutils="xalan://com.eviware.soapui.support.StringUtils" xmlns:lxslt="http://xml.apache.org/xslt">
<head>
<META http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>soapUI Test Results</title>
<style type="text/css">
body {
font:normal 68% verdana,arial,helvetica;
color:#000000;
}
table tr td, table tr th {
font-size: 68%;
}
table.details tr th{
font-weight: bold;
text-align:left;
background:#a6caf0;
}
table.details tr td{
background:#eeeee0;
}

p {
line-height:1.5em;
margin-top:0.5em; margin-bottom:1.0em;
}
h1 {
margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
}
h2 {
margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
}
h3 {
margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
}
h4 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
h5 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
h6 {
margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
}
.Error {
font-weight:bold; color:red;
}
.Failure {
font-weight:bold; color:purple;
}
.Properties {
text-align:right;
}
</style>
</head>
<body>
<a name="top"></a>
<h1>soapUI Test Results</h1>
<hr size="1">
<h2>Summary of ${testSuite.name}</h2>
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="details">
<tr valign="top">
<th>TestCases</th><th>Failures</th><th>Success Rate (%)</th>
</tr>
<tr valign="top" class="Failure">
<td>${testSuite.numTestCases}</td><td>${testSuite.numFailures}</td><td>${((testSuite.numTestCases - testSuite.numFailures) / testSuite.numTestCases) * 100}</td>

</tr>
</table>
<table width="95%" border="0">
<tr>
<td style="text-align: justify;">
Note: <i>failures</i> are anticipated and checked for with assertions while <i>errors</i> are unanticipated.
</td>
</tr>
</table>
<p></p>
<hr align="left" width="95%" size="1">
<h3>${testSuite.name}</h3>
<table width="95%" cellspacing="2" cellpadding="5" border="0" class="details">
<tr valign="top">
<th>TestCase</th><th>Status</th><th width="80%">Type</th><th nowrap>Time (s)</th>
</tr>
<% testSuite.testCases.each { testCase -> %>
<tr valign="top" class="${testCase.status == 'Failure' ? 'Error' : ''}">
<td>${testCase.name}</td><td>${testCase.status}</td><td>${testCase.type}</td><td>${testCase.time}</td>
</tr>
<% } %>
</table>
<p></p>
<a href="#top">Back to top</a>
</body>
</html>

How to Copy Dependencies and Automatically Add the Classpath into Manifest File

One thing that I like from NetBeans project for desktop applications is that it can include all the dependencies in dist/lib and include those dependencies in the MANIFEST.MF's classpath, so that we can just do java -jar or double click on the JAR. As a Maven user, I can achieve similar objective by adding few lines in my pom.xml.

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <configuration>
            <archive>
                <manifest>
                    <mainClass>myproject.Main</mainClass>
                    <addClasspath>true</addClasspath>
                    <classpathPrefix>lib/</classpathPrefix>
                </manifest>
                <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
            </archive>
        </configuration>
    </plugin>
    <plugin>
        <groupid>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
            <execution>
                <id>copy-dependencies</id>
                <phase>package</phase>
                <goals>
                    <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                    <outputDirectory>${project.build.directory}/lib</outputDirectory>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

The maven-dependency plugin is used to copy the dependencies in the target/lib. The maven-jar-plugin is used to create a MANIFEST.MF file and automatically add the classpath as well as mainClass. You need to make sure that an empty MANIFEST.MF is present in the src/main/resources/META-INF.

How to Include All the Dependencies into a Single JAR using Maven

A lot of times, we need to create a single JAR file with all the dependencies into a single JAR. The advantage of this approach is to make it easier to distribute the JAR. This approach has one problem, though, that is when we need to update some of the dependencies inside that JAR, we need to unjar the JAR first, update the dependencies and jar it back. Nevertheless, this approach is commonly used for desktop applications to create an executable JAR. Below is how to package the dependencies into a single JAR using Maven.

Add these lines in pom.xml.
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>jar-with-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

We use Maven Assembly plugin here. We can include the 'single' goal from maven-assembly-plugin into the 'package' phase. So rather than typing 'mvn assembly:assembly', we can just type 'mvn package' and all the dependencies will be inside a single JAR.

To build an executable JAR, we need an additional step to include the Main-Class in the MANIFEST.MF. All we need to do is to add these lines in the pom.xml as shown below.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <configuration>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <archive>
                <manifest>
                    <mainClass>myproject.Main</mainClass>
                </manifest>
            </archive>
            <id>jar-with-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Tuesday, May 11, 2010

AspectJ and @AspectJ without Spring using Maven

AspectJ offers two syntaxes. The first one is with the AspectJ syntax, another programming language. The second one is the @Aspect, which is set of annotations. With @AspectJ, our plain Java IDE will work just fine. There is no need to install AspectJ plugin or anything of that sort. For those obvious reasons, my preference is to use @AspectJ, the only catch is that it needs to run on Java 5 and above.

Here is a brief introduction how to setup AspectJ and @AspectJ without Spring using Maven.

Using AspectJ

LoggingAspect.aj
package myproject;

public aspect LoggingAspect {

    pointcut logging() : execution(* HelloWorld.sayHello(..));

    Object around() : logging() {
        System.out.println("Before " + thisJoinPointStaticPart.getSignature());
        Object ret = proceed();
        System.out.println("After " + thisJoinPointStaticPart.getSignature());

        return ret;
    }
}
The thisJoinPointStaticPart is one of the variables available in AspectJ.

or

Using @AspectJ

LoggingAspect.java
package myproject;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LoggingAspect {

    @Pointcut("execution(* HelloWorld.sayHello(..))")
    public void logging() {}

    @Around("logging()")
    public Object logging(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        System.out.println("Before " + thisJoinPoint.getSignature());
        Object ret = thisJoinPoint.proceed();
        System.out.println("After " + thisJoinPoint.getSignature());

        return ret;
    }
}
Unlike the AspectJ syntax, we need to include ProceedingJoinPoint argument to get something similar to thisJoinPointStaticPart in AspectJ syntax.

The Maven project requires Maven AspectJ plugin.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>myproject</groupId>
<artifactId>aspectj-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainclass>myproject.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

HelloWorld.java
package myproject;

public class HelloWorld {

    public void sayHello(String message) {
        System.out.println(message);
    }
}

Main.java
package myproject;

public class Main {

    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.sayHello("Hello World!");
        helloWorld.sayHello("Bye World!");
    }
}

To run, just execute 'mvn clean package exec:java'.

Monday, May 10, 2010

Slotted Aloha Simulation

Slotted Aloha is an improvement over the original Aloha, which introduced discrete timeslot. Below is the Slotted Aloha simulation that I wrote. I didn't consider any retransmission or backoff in this simulation.

The maximum throughput for Slotted Aloha is 36%. This can be computed using S = Ge^-G. With this simulation, you will roughly get your around 36% of maximum throughput. Due to the lack of randomness in generating the exponential random variable, you may not get exactly 36% for the maximum throughput. But I hope this code can give you a head start :)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define DEF_NUM_ALLOCATED 1000;
#define SIM_DURATION 1000
#define SLOT_SIZE 1.0
#define G_MAX 6.0
#define G_STEP 0.1
#define RAND_UNIFORM (double) random() / (double) RAND_MAX

/*
 *==============================================================================
 * Global variables
 *==============================================================================
 */
int s_evt_n_elements = 0;
int s_evt_n_allocated = 0;
struct slot_event *s_evt_list = NULL;

int p_evt_n_elements = 0;
int p_evt_n_allocated = 0;
struct packet_event *p_evt_list = NULL;

double p_error = 0.0;
int p_error_flag = 0;

/*
 *==============================================================================
 * Structures and their functions
 *==============================================================================
 */
struct slot_event
{
    double time;
    int num_packets;
};

struct packet_event
{
    double time;
};

int slot_event_add(struct slot_event);
int packet_event_add(struct packet_event);

/*
 *==============================================================================
 * Simulation functions
 *==============================================================================
 */
void run_simulation(double);
double calc_exp_random_var(double);
double get_max_packet_evt_time();
void init_slot_event_list();
void check_for_collisions();
int calc_successful_tx();
void clear_all();

/*
 *==============================================================================
 * Utility functions
 *==============================================================================
 */
int validate_args(int, char **);
void print_usage();

/*
 * Slotted Aloha Simulation.
 */
int main(int argc, char **argv)
{
    int n;
    double g, s;

    if (validate_args(argc, argv) == 0)
    {
        print_usage();
        return 1;
    }
    
    if (argc == 2)
    {
        p_error_flag = 1;
        p_error = atof(argv[1]);
    }
    
    for (g = 0.1; g <= G_MAX; g += G_STEP)
    {
        clear_all();
        run_simulation(g);
        init_slot_event_list();
        check_for_collisions();
        n = calc_successful_tx();
        s = (double) n / (double) s_evt_n_elements;
        printf("%lf,%lf\n", g, s);
    }
    free(s_evt_list);
    free(p_evt_list);
    
    return (EXIT_SUCCESS);
}

int slot_event_add(struct slot_event evt)
{
    if (s_evt_n_elements == s_evt_n_allocated)
    {
        if (s_evt_n_allocated == 0)
        {
            s_evt_n_allocated = DEF_NUM_ALLOCATED;
        }
        else
        {
            s_evt_n_allocated *= 2;
        }

        void *tmp = realloc(s_evt_list, (s_evt_n_allocated *
            sizeof(struct slot_event)));
        if (!tmp)
        {
            fprintf(stderr, "ERROR: Couldn't realloc memory\n");
            return (-1);
        }
        s_evt_list = (struct slot_event*) tmp;
    }
    s_evt_list[s_evt_n_elements] = evt;
    s_evt_n_elements++;

    return s_evt_n_elements;
}

int packet_event_add(struct packet_event evt)
{
    if (p_evt_n_elements == p_evt_n_allocated)
    {
        if (p_evt_n_allocated == 0)
        {
            p_evt_n_allocated = DEF_NUM_ALLOCATED;
        }
        else
        {
            p_evt_n_allocated *= 2;
        }

        void *tmp = realloc(p_evt_list, (p_evt_n_allocated *
            sizeof(struct packet_event)));
        if (!tmp)
        {
            fprintf(stderr, "ERROR: Couldn't realloc memory\n");
            return (-1);
        }
        p_evt_list = (struct packet_event*) tmp;
    }
    p_evt_list[p_evt_n_elements] = evt;
    p_evt_n_elements++;

    return p_evt_n_elements;
}

/*
 * Run the simulation.
 */
void run_simulation(double lambda)
{
    int i;
    struct packet_event p_evt;
    double evt_time = 0.0;
    for (i = 0; i < SIM_DURATION; i++)
    {
        if (p_evt_n_elements > 0)
        {
            evt_time = p_evt_list[p_evt_n_elements-1].time;
        }
        p_evt.time = evt_time + calc_exp_random_var(lambda);
        packet_event_add(p_evt);
    }
}

/*
 * Calculate the exponential random variable based on a given lambda.
 */
double calc_exp_random_var(double lambda)
{
    return (-log(RAND_UNIFORM) / lambda);
}

/*
 * Get the max packet event time.
 */
double get_max_packet_evt_time()
{
    int i;
    double max_evt_time = p_evt_list[0].time;
    for (i = 1; i < p_evt_n_elements; i++)
    {
        if (p_evt_list[i].time > max_evt_time)
        {
            max_evt_time = p_evt_list[i].time;
        }
    }
    return max_evt_time;
}

/*
 * Initialize the slot event list.
 */
void init_slot_event_list()
{
    double slot_time;
    struct slot_event s_evt;
    double max_evt_time = get_max_packet_evt_time();
    for (slot_time = SLOT_SIZE; slot_time <= max_evt_time + SLOT_SIZE;
            slot_time += SLOT_SIZE)
    {
        s_evt.time = slot_time;
        s_evt.num_packets = 0;
        slot_event_add(s_evt);
    }
}

/*
 * Check for collisions.
 */
void check_for_collisions()
{
    int i, j;
    for (i = 0; i < s_evt_n_elements; i++)
    {
        for (j = 0; j < p_evt_n_elements; j++)
        {
            if (p_evt_list[j].time <= s_evt_list[i].time &&
                p_evt_list[j].time > (s_evt_list[i].time - SLOT_SIZE))
            {
                s_evt_list[i].num_packets += 1;
            }
        }
    }
}

/*
 * Calculate the sucessful transmission.
 */
int calc_successful_tx()
{
    int n = 0;
    int i;
    for (i = 0; i < s_evt_n_elements; i++)
    {
        if (s_evt_list[i].num_packets == 1)
        {
            if (p_error_flag == 1)
            {
                if (RAND_UNIFORM > p_error)
                {
                    ++n;
                }
            }
            else
            {
                ++n;
            }
        }
    }
    return n;
}

/*
 * Clear all the list.
 */
void clear_all()
{
    s_evt_list = NULL;
    p_evt_list = NULL;
    s_evt_n_elements = 0;
    p_evt_n_elements = 0;
    s_evt_n_allocated = 0;
    p_evt_n_allocated = 0;
}

/*
 * Validate arguments.
 */
int validate_args(int argc, char **argv)
{
    if (argc > 2)
    {
        return 0;
    }
    return 1;
}

/*
 * Print usage.
 */
void print_usage()
{
    fprintf(stderr, "Usage: slottedaloha [Perror]\n");
}

Classpath Builder

In Java world, we all are very familiar with classpath. If let's say we have a lot of JAR files scattered around in many different sub-directories, listing down all of them by hand can be very tedious.

Below is the script that can help you to automate that. You can do something like this.

java -cp `groovy ClassPathBuilder.groovy absolute auto jars` myproject.Main

def validateArgs() {
    if (this.args.size() != 3) {
        printUsage()
        System.exit(0)
    }

    if (this.args[0] != 'absolute' && this.args[0] != 'relative' &&
           this.args[1] != 'unix' && this.args[1] != 'windows' && this.args[1] != 'auto') {
        printUsage()
        System.exit(0)
    }

    if (!(new File(this.args[2]).isDirectory())) {
        println "${this.args[2]} is not a directory"
        System.exit(0)
    }
}

def printUsage() {
    println "Usage: groovy ClassPathBuilder.groovy [absolute|relative] [unix|windows|auto] [dir]"
}

def getJars(def file) {
    def jars = []
    file.eachFileRecurse { 
        if (it.name.toLowerCase().endsWith(".jar")) { 
            jars += it 
        }
    }
    return jars
}

validateArgs()
def dir = new File(this.args[2])
def jars = getJars(dir)
def option1 = this.args[0]
def option2 = this.args[1]
def pathSeparator = (option2 == 'unix') ? ":" : (option2 == 'windows') ? ";" : File.pathSeparator
def result = ''
if (option1 == 'absolute') {
    result = jars.collect { file -> file.getPath() }.join(pathSeparator)
} else {
    result = jars.collect { file -> file.getPath().substring(dir.getPath().size()+1) }.join(pathSeparator)
}

if (option2 == 'unix') {
    println result.replaceAll('\\\\', '/')
} else if (option2 == 'windows') {
    println result.replaceAll('/', '\\\\')
} else {
    println result
}

Write a Scheduler using Quartz

A lot of times, as a developer, we need to run a task in a scheduled manner. In Linux/UNIX, we have cron job. In Windows, we have Scheduled Task. But if let's say we work in an environment where we have no luxury to use any of them, as a Java developer, we can easily write a scheduler using Quartz.

Quartz has two main components, Trigger and Job. To use cron-like trigger, we can use org.quartz.CronTrigger.

MyTrigger.java
package myproject;

import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

public class MyTrigger {

    public void task(String cronExpression, String[] commands) throws SchedulerException {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();

        JobDetail jobDetail = new JobDetail("myJobDetail", "myJobDetailGroup",
                MyJob.class);
        JobDataMap jobDataMap = jobDetail.getJobDataMap();
        jobDataMap.put("commands", commands);
        jobDetail.setJobDataMap(jobDataMap);

        CronTrigger cronTrigger = new CronTrigger("myTrigger", "myTriggerGroup");

        try {
            CronExpression cexp = new CronExpression(cronExpression);
            cronTrigger.setCronExpression(cexp);
        } catch (Exception e) {
            e.printStackTrace();
        }
        scheduler.scheduleJob(jobDetail, cronTrigger);

        scheduler.start();
    }

    public static void main(String[] args) {
        if (!validateArgs(args)) {
            printUsage();
            System.exit(1);
        }

        String cronExpression = args[0];
        String[] commands = new String[args.length-1];
        for (int i = 0; i < args.length-1; i++) {
            commands[i] = args[i+1];
        }

        try {
            MyTrigger trigger = new MyTrigger();
            trigger.task(cronExpression, commands);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static boolean validateArgs(String[] args) {
        if (args.length < 2) {
            return false;
        }
        return true;
    }

    private static void printUsage() {
        System.out.println("Usage: java MyTrigger [cron_exp] [command1] [command2] ...");
    }
}
The jobDataMap in the code above is used to pass the data from the Trigger to a Job. In this example, the data being passed is a list of commands to be executed. MyJob.java
package myproject;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class MyJob implements Job {

    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("MyJob - executing its job at "
                + new Date() + " by " + context.getTrigger().getName());
        String[] commands = (String[]) context.getMergedJobDataMap().get("commands");
        ProcessBuilder pb = new ProcessBuilder(commands);
        try {
            Process p = pb.start();
            StreamGobbler outputStreamGobbler = new StreamGobbler(p.getInputStream());
            StreamGobbler errorStreamGobbler = new StreamGobbler(p.getErrorStream());

            outputStreamGobbler.start();
            errorStreamGobbler.start();

            p.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
To retrieve the jobDataMap from the Trigger, we can call context.getMergedJobDataMap(). StreamGobbler.java
package myproject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class StreamGobbler extends Thread {

    private InputStream is;

    public StreamGobbler(InputStream is) {
        this.is = is;
    }

    @Override
    public void run() {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(is));
            String line = "";
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

soapUI with Groovy

I've been doing a lot of stuff with soapUI recently and one interesting problem that I came accross is that I need to fire the first request which does insertion and get the response, which contains a transaction number. Afterwards, I need to fire the second request which does a query using that transaction number.

Although, this problem can be solved manually, it's not a very elegant solution. Luckily, we can solve this quite easily with soapUI Groovy scripting feature.

def groovyUtils = new com.eviware.soapui.support.GroovyUtils(context)

// Run the first request and get the response
def firstResponse = testRunner.runTestStepByName("Test Case 1")
def holder = groovyUtils.getXmlHolder(firstResponse.responseContent)
def txnNumber = holder["//NS1:InsertionResponse/NS1:TransactionNumber"]

// Modify the second request using the first response
def secondRequest = testRunner.testCase.getTestStepByName("Test Case 2")
def property = secondRequest.getProperty("request")
holder = groovyUtils.getXmlHolder(property.value)
holder.put("//NS1:QueryRequest/NS1:TransactionNumber", txnNumber)
property.setValue(holder.prettyXml)

// Run the second request and get the response
def secondResponse = testRunner.runTestStepByName("Test Case 2")
holder = groovyUtils.getXmlHolder(secondResponse.responseContent)

How to Find a Class in any JAR Files

Two (in)famous exceptions in Java are NullPointerException and ClassNotFoundException. Those exceptions are actually quite easy to resolve. In most cases, the ClassNotFoundException occurs due to missing JAR file in a classpath.

I wrote a Groovy script to find a class in any JAR files so that you can easily find whether a particular file exists in any JAR file(s).

Enjoy :)

if (!validateArgs(this.args)) {
    System.exit(1)   
}

def dir = new File(this.args[0])
def entry = this.args[1]
dir.eachFileRecurse { jarFile ->
    if (jarFile.name.toLowerCase().endsWith('.jar')) {
        def jar = new java.util.jar.JarFile(jarFile)
        jar.entries().each { jarEntry ->
            if (jarEntry.name.toLowerCase().contains(entry.toLowerCase())) {
                println "${jarFile.absolutePath}: ${jarEntry.name}"
            }
        }
    }
}

def validateArgs(def args) {
    if (args.size() != 2) {
        printUsage()
        return false
    }
   
    def dir = new File(args[0])
    if (!dir.isDirectory()) {
        printUsage()
        return false
    }
    return true
}

def printUsage() {
    println "Usage: groovy ClassFinder.groovy [directory_to_search] [jar_entry]"
}