Category Archives: Java

ShrinkWrap together with Maven

I have lately been looking a bit into the JBoss Shrinkwrap project, which is a simple framework for building archives such as JARs, WARs and EARs with Java code through a straightforward API. You can assemble a simple JAR with a single line of Java code:

JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "myJar.jar")
       .addClasses(MyClass.class, MyOtherClass.class)
       .addAsResource("my_application.properties");

With ShrinkWrap you basically have the option to skip the entire build process if you want to. What if you would want to integrate ShrinkWrap with your existing Maven based project? I found myself in a situation where I had a somewhat small web application project setup with Maven, with a single pom.xml which specified war packaging. Due to some external factors I suddenly found myself with a demand of being able to support one of my Spring beans as an EJB. One of the application servers the application should run on demanded that my application was packaged as an ear with the EJB in an own jar with the ejb-jar.xml descriptor file. In this case it would be too much of a trouble to refactor the Spring bean/EJB into an own module with ejb packaging, and then to assemble an ear through the maven-ear-plugin. I also wanted to remain independent of the application server, and wanted to be able to deploy the application as a war artifact on another application server if I wanted to. So I thought I could use ShrinkWrap to help me out.

Add a ShrinkWrap packaging to Maven
I will now describe what I needed to do to add “ShrinkWrap awareness” to my Maven build. I tried to keep this example as simple as possible, therefore I have omitted “unnecessary” configuration, error handling, reusability aspects etc. This example shows you how to build a simple custom EJB jar file with Maven and ShrinkWrap, e.g. together with the build of a war module. First, I obviously had to add the maven dependencies:

<dependency>
   <groupId>org.jboss.shrinkwrap</groupId>
   <artifactId>shrinkwrap-api</artifactId>
   <version>1.0.0-alpha-12</version>
   <scope>compile</scope>
</dependency>
<dependency>
   <groupId>org.jboss.shrinkwrap</groupId>
   <artifactId>shrinkwrap-impl-base</artifactId>
   <version>1.0.0-alpha-12</version>
   <scope>provided</scope>
</dependency>

I added the api dependency with compile scope as I only need it when building my application. I then added the exec-maven-plugin which basically allows me to execute Java main classes in my Maven build process:

<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>exec-maven-plugin</artifactId>
      <version>1.1.1</version>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>java</goal>
          </goals>
          <configuration>
            <mainClass>se.diabol.example.MyPackager</mainClass>
            <arguments>
              <argument>${project.build.directory}</argument>
            </arguments>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Notice that I specified the package execution phase, which tells Maven to execute the plugin at the package phase of the build process. The plugin will execute the se.diabol.example.MyPackager class with the project build directory as an argument.

Let’s take a look at the se.diabol.example.MyPackager class and the comments on the end of the rows:

public class MyPackager{
   public static void main(final String args[]){
      String buildDir = args[0];          // The build directory, passed as an argument from the exec-maven-plugin
      String jarName = "my_ejb_archive.jar";                   // Chosen jar name
      File actualOutFile = new File(buildDir + "/" + jarName); // The actual output file as a java.io.File
      JavaArchive ejbJar = ShrinkWrap.create(JavaArchive.class, jarName)
            .addClasses(MyEjbClass.class)                      // Add my EJB class and the ejb-jar.xml
            .addAsResource("ejb-jar.xml");                     // These exist on classpath so ShrinkWrap will find them
      ejbJar.as(ZipExporter.class).exportTo(actualOutFile);    // Create the physical file
   }
}

Now when you have successfully built your project with e.g. mvn clean package, you will now see that ShrinkWrap created my_ejb_archive.jar archive in the project build directory, containing the MyEjbClass.class and the ejb-jar.xml! When you’ve started off by a simple example like this, you can now move on to more sophisticated solutions and take advantage of ShrinkWraps features.

Tommy Tynjä
@tommysdk

Get started with AWS Elastic Beanstalk

Amazon Web Services (AWS) launched a beta of their new concept Elastic Beanstalk in January. AWS Elastic Beanstalk allows you to in a few clicks setup a new environment where you can deploy your application. Say you have a development team developing a web-app running on Tomcat and you need a test server where you can test your application. In a few simple steps you can setup a new machine with a fresh installation of Tomcat where you can deploy your application. You can even use the AWS Elastic Beanstalk command line client to deploy your application as simple as with:

$ elastic-beanstalk-update-application -a my_app.war -d "Application description"

I had the opportunity to try it out and I would like to share how you get started with the service.

As with other AWS cloud based services, you only pay for the resources your application consumes and if you’re only interested in a short evaluation, it will propably only cost you a couple of US dollars. This first release of Elastic Beanstalk is targeted for Java developers who are familiar with the Apache Tomcat software stack. The concept is simple, you simply upload your application (e.g. war-packaged web application) to a Elastic Beanstalk instance through the AWS web interface called the Management Console. The Management Console allows you to handle versioning of your applications, monitoring and log viewing straight throught the web interface. It also provides load balancing and scaling out of the box. The Elastic Beanstalk service is currently running on a 32-bit Amazon Linux AMI using Apache Tomcat 6.0.29.

But what if you would like to customize the software stack your application is running on? Common tasks you might want to do is adding jar-files to the Tomcat lib-directory, configure connection pooling capabilities, edit the Tomcat server.xml or even install third party products such as ActiveMQ. Fortunatly, all of this is possible! You first have to create your custom AMI (Amazon Machine Image). Go to the EC2 tab in the Management Console, select your default Elastic Beanstalk instance and select Instance Actions > Create Image (EBS AMI). You should then see your custom image under Images / AMIs in the left menu with a custom AMI ID. Back in the Elastic Beanstalk tab, select Environment Details of the environment you want to customize and select Edit Configuration. Under the Server tab, you can specify a Custom AMI ID to your instance, which should refer to the AMI ID of your newly created custom image. After applying the changes, your environment will “reboot”, running your custom AMI.

Now you might ask yourself, what IP address do my instance actually have? Well, you have to assign an IP address to it first. You can then either use this IP or the DNS name to log in to your instance. AWS is using a concept called Elastic IPs, which means that they provide a pool of IP addresses from where you can get a random free IP address to bind to your current instance. If you want to release the IP address from your instance, it is just as easy. All of this is done straight out of the Management Console in the EC2 tab under Elastic IPs. You just select Allocate Address and then bind this Elastic IP to your instance. To prevent users to have unused IP addresses lying around, AWS is charging your account for every unbound Elastic IP, which might end up a costful experience. So make sure you release your Elastic IP address back to the pool if you’re not using it.

To be able to log in to your machine, you will have to gerenate a key pair which is used as an authentication token. You generate a key pair in the EC2 tab under Networking & Security / Key Pairs. Then go back to the Elastic Beanstalk tab, select Environment Details of your environment and attach your key pair by providing it in the Server > Existing Key Pair field. You then need to download the key file (with a .pem extension by default) to the machine you will actually connect from. You also need to open the firewall for your instance to allow connections from the IP address you are connecting from. Do that by creating a security group Networking & Security Groups on the EC2 tab. Make sure to allow SSH over tcp for port 22 for the IP address you are connecting from. Then attach the security group to your Elastic Beanstalk environment by going to the Elastic Beanstalk tab and selecting Environment Details > Edit Configuration for your environment. Add the security group in the field EC2 Security Group on the Server tab.

So now you’re currently running a custom image (which is actually a replica of the default one) which has an IP address, a security group and a key pair assigned to it. Now is the time to log in to the machine and do some actual customization! Log in to your machine using ssh and the key you downloaded from your AWS Management Console, e.g.:

$ ssh -i /home/tommy/mykey.pem ec2-user@ec2-MY_ELASTIC_IP.compute-1.amazonaws.com

… where MY_ELASTIC_IP is the IP address of your machine, such as:

$ ssh -i /home/tommy/mykey.pem ec2-user@ec2-184-73-226-161.compute-1.amazonaws.com

Please note the hyphens instead of dots in the IP address! Then, you’re good to go and start customizing your current machine! If you would like to save these configurations onto a new image (AMI), just copy the current AMI through the Management Console. You can then use this image when booting up new environments. You find Tomcat under /usr/share/tomcat6/. See below for a login example:

tommy@linux /host $ ssh -i /home/tommy/mykey.pem ec2-user@ec2-184-73-226-161.compute-1.amazonaws.com
The authenticity of host 'ec2-184-73-226-161.compute-1.amazonaws.com (184.73.226.161)' can't be established.
RSA key fingerprint is 13:7d:aa:31:5c:3b:17:ed:74:6d:87:07:23:ee:33:20.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'ec2-184-73-226-161.compute-1.amazonaws.com,184.73.226.161' (RSA) to the list of known hosts.
Last login: Thu Feb  3 23:48:38 2011 from 72-21-198-68.amazon.com

 __|  __|_  )  Amazon Linux AMI
 _|  (     /     Beta
 ___|\___|___|

See /usr/share/doc/amzn-ami/image-release-notes for latest release notes.
[ec2-user@ip-10-122-194-97 ~]$  sudo su -
[root@ip-10-122-194-97 /]# ls -al /usr/share/tomcat6/
total 12
drwxrwxr-x  3 root tomcat 4096 Feb  3 23:50 .
drwxr-xr-x 64 root root   4096 Feb  3 23:50 ..
drwxr-xr-x  2 root root   4096 Feb  3 23:50 bin
lrwxrwxrwx  1 root tomcat   12 Feb  3 23:50 conf -> /etc/tomcat6
lrwxrwxrwx  1 root tomcat   23 Feb  3 23:50 lib -> /usr/share/java/tomcat6
lrwxrwxrwx  1 root tomcat   16 Feb  3 23:50 logs -> /var/log/tomcat6
lrwxrwxrwx  1 root tomcat   23 Feb  3 23:50 temp -> /var/cache/tomcat6/temp
lrwxrwxrwx  1 root tomcat   24 Feb  3 23:50 webapps -> /var/lib/tomcat6/webapps
lrwxrwxrwx  1 root tomcat   23 Feb  3 23:50 work -> /var/cache/tomcat6/work
Tommy Tynjä
@tommysdk

GlassFish 3.1

Idag släpptes applikationsservern GlassFish 3.1. Det mycket i den releasen som är värt att titta noga på och även om applikationsservrar ända sedan J2EE har haft svårt att få acceptans i systemutvecklarkretsar. Val av applikationsserver är ett strategiskt val, det är viktigt att man som företag “satsar på rätt häst”, efter som det är stor sannolikhet att man får leva med valet i flera år framöver.
GlassFish är referens implementation till Java EE specifikationen. Det betyder konkret att GlassFish alltid kommer ligga i framkant när Java och Java EE standarden utvecklas. När detta skrivs är vi på Java EE 6, en standard som innehåller väldigt mycket som höjer abstraktionsnivån på hur avancerade system utvecklas GlassFish är i dagsläget enda applikationsservern som implementerar hela Java EE 6 standarden. Standarden kräver att applikationsservern sköter det mesta av det som man för bara några åt sedan var tvungen att hacka mängder med XML för att få till. Man har tagit best practices från ramverk som Spring, Hibernate, Google Guice och Seam för att bygga upp en programmeringsmodell som bevisligen fungerar. GlassFish är således verkligen en plattform för att programmera på ett effektivt sätt.
GlassFish är ombyggd från 2.x versionen till att vara helt modulär och baserad på OSGi plattformen Apache Felix. Det betyder konkret att man har en plattform som är modulär och där man bara behöver köra de moduler som verkligen behövs. Det betyder dessutom att det är enkelt att vidareutveckla plattformen med OSGi boundles som deployas på Felix. GlassFish kan till och med interagera med OSGi boundles via injections i Java EE applikationer (sk. Hybridapplikationer).
GlassFish har i och med 3.1 åter fått stöd för klusting och central administration. Det är goda nyheter för företag med stora data centers som behöver en bra överblick över installationer och miljö och en hög tillgänglighet. Kort sagt, GlassFish tillför så mycket värde att det kanske, nästan överväger debaclet med Oracle -> Sun.

Att utveckla för driftbarhet

Ordet systemutveckling syftar till att handla om mer än programmering av affärslogik. Det syftar till att utveckla systemet som ska skapa affärsvärde. Har man väl vridit hjärnan till ett sådant tankesätt, är det lätt att ta till sig att saker som hur loggar skrivs ut potentiellt kan vara en väldigt viktig del av programmeringen. Den stackars jourpersonen som kl 03 ska försöka reda ut varför företaget plötsligt blöder pengar, vill nog gärna att Nagios, Hyperiq eller vad man nu använder; triggas på rätt sätt. Övervakningssystem som dem tittar ofta på loggar för att rapportera fel. Det betyder att loggar potentiellt kan vara väldigt viktiga == bör testas! Nedan visas ett exempel på hur vi gjorde ett enkelt test för att verifiera själva logutskriften hos en kund.
Vi tänker oss att vi har en service “MyService” som använder sig av en wrapper “RemoteProviderWrapper” för att anropa en extern tjänst av något slag.

package se.diabol.test.logunit
import org.apache.log4j.Logger
class MyService {
  private Logger log = Logger.getLogger(MyService.class)
  RemoteProviderWrapper remoteProviderWrapper = new RemoteProviderWrapper()
  void shakyServiceMethod(String parameter){
    try{
      remoteProviderWrapper.callRemoteProvider(parameter)
    }catch(RemoteProviderCommunicationException e){
      log.error "Communication failure with external provider: ${e.message}"
      // Do cleanup, rollback transactions, report to the user..
    }
  }
}

Om man tittar vi på vad som händer i själva catch blocket (jag är fullt medveten om att det inte är optimalt att lösta exception hantering på detta sätt, men det är bara ett exempel). Det skrivs ut ett felmeddelande som talar om att det inte går att kommunicera med den externa tjänsten. Denna loggutskrift är guld värd för någon som, utan programmerardjup kunskap om systemet, ska förstå vad som är roten till problemet. Hela systemet kan ju just nu stå och kräkas ur sig stackutskrifter från exceptions. Antagligen finns det en trigger i övervakningssystemet på denna logutskrift. Alltså bör vi testa att detta logmeddelande verkligen kommer ut som en del i vårt testramverk. Jag har skapat en log4j appender som sväljer alla meddelenaden för att senare i en testkod kunna hämta ut dem och verifiera vad de innehåller:

package se.diabol.test.logunit
import org.apache.log4j.AppenderSkeleton
import org.apache.log4j.spi.LoggingEvent
class UnitTestAppender extends AppenderSkeleton { 
  private List messages = []  
  protected void append(LoggingEvent event) {    
    messages += event.renderedMessage  
  }  
  void close() {}  
  boolean requiresLayout() {return false}  
  String[] getMessages() {
    return messages as String[]
  }
  void clear() {
    messages = []
  }
}

Ok, nu har vi en appender, då är det bara att tala om för log4j att den ska användas (sätter det på root loggern här)

log4j.rootCategory=DEBUG, junittestappender
log4j.appender.junittestappender=se.diabol.test.logunit.UnitTestAppender

Därefter kan man skriva ett unittest som använder appendern för att verifiera loggningen som sker i koden.

package se.diabol.test.logunit

import org.junit.Test
import groovy.mock.interceptor.*
import org.apache.log4j.LogManager

class MyServiceTest {
    @Test
    void makeFailedCallToRemoteProvider(){
        def appender = LogManager.rootLogger.getAppender("junittestappender")
        appender.clear()

        def mock = new MockFor(RemoteProviderWrapper.class)
        mock.demand.callRemoteProvider { throw new RemoteProviderCommunicationException("Communication link down!")}
        mock.use{
            new MyService().shakyServiceMethod("Test parameter")
        }

        assert appender.messages == ["Communication failure with external provider: Communication link down!"]
    }
}

Jag börjar med att hämta ut den appender som log4j har skapad och tömmer eventuella gamla meddelanden “clear()”. Sen använder jag grooys inbyggda mockningsfunktionalitet för att skapa en mockad “RemoteProviderWrapper”. Denna mock kommer skicka ett “RemoteProviderCommunicationException” varje gång den anropas. Innanför “mock.use{” blocket kommer alla försök att skapa en “RemoteProviderWrapper” returnera den mock jag angivit ovanför. Jag behöver alltså inte tala om för MyService att den ska använda den mockade klassen på något annat sätt. Sen anropar jag service metoden “shakyServiceMethod”. När det är gjort, hämtar jag ut allt som lagrats i test appendern och verifierar att en logutskrift verkligen skett.
Vad var nu sysftet med detta? Jo, plötsligt har blicken lyfts lite. Här finns en tanke om att det inte bara är själva koden som är viktigt. Denna kod sitter antagligen i någon modul som ingår i ett system. För modulen och programmeraren är loggningen helt irrelevant. Men för systemet och verksamheten kan det vara fråga om skillnader i timmars felsökning för att hitta en extern tjänst som gått ner, eller se ett korrekt felmeddelande i övervakningssystemet. Det är vad utveckling för driftbarhet handlar om.
Nästa steg är att även involvera nämnt övervakningssystem i systemutvecklingen och börja göra automatiska funktionstester som även omfattar övervakning.

Groovy och Grizzly http unit test

Hur ofta är det inte som man stöter på legacy kod som vill göra ett externt TCP anrop (socket, http, webservice eller något annat) och så sliter man sitt hår för att hitta det optimala sättet att skriva ett unit test för koden (som naturligtvis inte finns där från början) för att kunna göra den lite mindre legacy.

Jag stötte på detta igen häromdagen och bestämde mig för att testa ett groovy-grepp på problemet. Det visade sig vara en strålade idé (ödmjukt).

Säg att vi har följande lilla demoklass att testa.

package demo;

import java.io.IOException;
import java.net.HttpURLConnection;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;

public class HttpCallingBean {    

    public void sendMessage(String message) {
        HttpClient httpClient = new HttpClient();
        PostMethod postMethod = new PostMethod("http://localhost:8282");

        try {
            StringRequestEntity entity = new StringRequestEntity(message);
            postMethod.setRequestEntity(entity);
            httpClient.executeMethod(postMethod);
            if(postMethod.getStatusCode() != HttpURLConnection.HTTP_OK){
                throw new RuntimeException("Not ok!"); // Only a demo...
            }

        }catch(IOException e){
            e.printStackTrace(); // Only a demo...

        }finally{
            postMethod.releaseConnection();
        }
    }
}

Vill vi skriva ett test för detta (utan att bryta ut anropet i en annan klass och mocka den) så måste vi sätta upp en liten lyssnare på porten 8282 på localhost, vi vill dessutom integrera detta i junittestet så att lyssnaren startas och stoppas tillsammans med tester. Med Grizzly och Groovy visar det sig att detta är mycket enkelt. Nedan följer testkoden för klassen ovan

package demo

import groovy.util.GroovyTestCase
import com.sun.grizzly.http.SelectorThread
import com.sun.grizzly.tcp.Adapter
import com.sun.grizzly.tcp.Request
import com.sun.grizzly.tcp.Response
import com.sun.grizzly.util.buf.ByteChunk
import java.net.HttpURLConnection

class HttpCallingBeanTest extends GroovyTestCase {

 void testSayHello()throws Exception {
 def st = new SelectorThread()
 try{
 st.port = 8282
st.adapter = new BasicAdapter()
 st.listen()

 HttpCallingBean beanUnderTest = new HttpCallingBean()
 beanUnderTest.sendMessage("Hello grizzly")

 }finally{
 st.stopEndpoint()
 }
 }
}

class BasicAdapter implements Adapter {
 public void service(Request request, Response response) {
 def content = new ByteChunk()
 request.doRead(content)
 def bytes = null
 if(content.equals("Hello grizzly")){
 response.status = HttpURLConnection.HTTP_OK
 bytes = 'Success'.bytes<strong>
 }else{
 response.status = HttpURLConnection.HTTP_BAD_REQUEST
 bytes = 'Failure'.bytes
 }

 def chunk = new ByteChunk()
 chunk.append(bytes, 0, bytes.length)
 response.contentLength = bytes.length
 response.contentType = 'text/html'
 response.outputBuffer.doWrite(chunk, response)
 response.finish()
 }

 public void afterService(Request request, Response response) {
 request.recycle()
 response.recycle()
 }

 public void fireAdapterEvent(string, object) {}
}

Här har vi alltså ett unittest som startar en Grizzly SelectorThread och kopplar en enkel adapter (BasicAdapter) till den. Adaptern läser vad som kommer in och svarar med OK eller BAD_REQUEST. När testet är kört stoppas selector tråden i finally blocket och vi har ett komplett test för bönan med dess externa anrop i ett enda unittest.