Dienstag, 27. September 2011

Arquillian How to - Article

Some weeks ago I was asked to write an article about how to use Arquillian. The article was published in the german magazine called "Java aktuell". This magazine is produced for the ijug.eu (INTERESSENVERBUND DER JAVA USER GROUPS E.V.). You can find the article below including the source code examples. Have fun reading.

Vor einigen Wochen wurde ich gefragt, ob ich Lust hätte, einen Artikel über Arquillian zu schreiben. Der Artikel wurde im Magazin "Java aktuell" veröffentlicht. Dieses Magazin wird für die ijug.eu veröffentlicht, den Interessenverbund der Java User Groups e.V.). Anbei findet ihr den Artikel und den dazugehörigen Quellcode. Viel Spaß beim Lesen.

PDF Sonderdruck - Artikel zum Download

Quellcode-Beispiele zum Download

Beispiel 1 - HelloArquillian

IntCounter.java


package eu.ijug.helloarquillian;

public class IntCounter {

public int count(int a, int b) {
return (a + b);
}

}


IntCounterTest.java


package eu.ijug.helloarquillian;

import javax.inject.Inject;
import junit.framework.Assert;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class IntCounterTest {

@Inject
private IntCounter counter;

@Deployment
public static JavaArchive createTestArchive() {
return ShrinkWrap.create(JavaArchive.class, "test.jar")
.addClasses(IntCounter.class)
.addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
}

@Test
public void testCount() {
Assert.assertEquals(2, counter.count(1, 1));
}

}


jndi.properties


java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099


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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>eu.ijug</groupId>
<artifactId>HelloArquillian</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>ejb</packaging>
<name>HelloArquillian EJB</name>
<description>A short example using Arquillian on a remote JBoss AS</description>

<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<arquillian.version>1.0.0.Alpha5</arquillian.version>
</properties>

<repositories>

<repository>
<id>jboss_maven_repository</id>
<name>JBoss Maven repository</name>
<url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>

<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>

<repository>
<id>jboss-deprecated-repository-group</id>
<name>JBoss Deprecated Maven Repository Group</name>
<url>https://repository.jboss.org/nexus/content/repositories/deprecated/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</snapshots>
</repository>

</repositories>

<dependencies>

<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.0-SP1</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-junit</artifactId>
<version>${arquillian.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-jbossas-remote-6</artifactId>
<version>${arquillian.version}</version>
</dependency>

<dependency>
<groupId>org.jboss.jbossas</groupId>
<artifactId>jboss-as-profileservice-client</artifactId>
<version>6.0.0.Final</version>
<type>pom</type>
</dependency>

</dependencies>

</project>


Beispiel 2 - HelloEmbedded

TimeServiceEJB.java


package eu.ijug.helloembedded;

import java.text.SimpleDateFormat;
import java.util.Date;
import javax.ejb.Stateless;

@Stateless
public class TimeServiceEJB {

public String getCurrentYear() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
return sdf.format(new Date());
}
}


TimeServiceTest.java


package eu.ijug.helloembedded;

import javax.ejb.EJB;

import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;

@RunWith(Arquillian.class)
public class TimeServiceTest {

@EJB
private TimeServiceEJB timeService;

@Deployment
public static JavaArchive createTestArchive() {
return ShrinkWrap.create(JavaArchive.class, "timeServiceEJB.jar").addClasses(TimeServiceEJB.class);
}

@Test
public void testGetCurrentYear() {
String year = timeService.getCurrentYear();
assertEquals("2011", year);
}
}


pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<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>eu.ijug</groupId>
<artifactId>HelloEmbedded</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>ejb</packaging>
<name>Hello Embedded EJB</name>
<description>A short example using Arquillian with embedded Glassfish 3.1 and EJB3.1</description>

<repositories>

<repository>
<id>jboss_maven_repository</id>
<name>JBoss Maven repository</name>
<url>http://repository.jboss.org/nexus/content/groups/public-jboss/groups/</url>
</repository>

<repository>
<id>jboss_public</id>
<name>JBoss public maven repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>

</repositories>

<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<arquillian.version>1.0.0.Alpha5</arquillian.version>
<glassfish.version>3.1</glassfish.version>
<junit.version>4.8.2</junit.version>
</properties>

<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-junit</artifactId>
<version>${arquillian.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-glassfish-embedded-3.1</artifactId>
<version>${arquillian.version}</version>
</dependency>

<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>${glassfish.version}</version>
</dependency>

</dependencies>

</project>

Samstag, 4. Juni 2011

Java 3D engine

Today I am adding another facette to this blog. If you need a bit variety of not always hearing about EJB3 and JSF... here you are.

Ever wondered how a 3D game could be programmed in Java? The link of the day is http://jmonkeyengine.org/. The jMonkey engine is really a great project. It´s open source! It´s full of features like physics engine and others. It´s fun AND it´s well documented with a tutorial page. So the first steps are really easy to learn. You will learn, what assets, meshes, models and nodes are. Some example code will come soon.

Here a first hello world example from their documentation:


package jme3test.helloworld;
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.math.ColorRGBA;
/** Sample 1 - how to get started with the most simple JME 3 application.
* Display a blue 3D cube and view from all sides by
* moving the mouse and pressing the WASD keys. */
public class HelloJME3 extends SimpleApplication {
public static void main(String[] args){
HelloJME3 app = new HelloJME3();
app.start();
}
@Override
public void simpleInitApp() {
Box b = new Box(Vector3f.ZERO, 1, 1, 1);
Geometry geom = new Geometry("Box", b);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", ColorRGBA.Blue);
geom.setMaterial(mat);
rootNode.attachChild(geom);
}
}


Stay tuned and write a comment, if you want to hear more (and especially want to SEE CODE) ;)

Have fun trying.

Sonntag, 1. Mai 2011

New JavaEE book by Adam Bien available

Adam Bien, Java Champion and book author, just announced his new book. It´s called "Real World Java EE Night Hacks" and he writes about topics like CDI, REST, JPA2, JMX, EJB 3.1, JAX-RS, Maven 3 and others. And he even managed to get a foreword by James Gosling ;) Give it a try:

http://www.adam-bien.com/roller/abien/entry/real_world_java_ee_night

Sonntag, 3. April 2011

RichFaces 4 Final available

RichFaces 4 Final is released ;) There are nice features like file upload available now. Check it out at http://www.jboss.org/richfaces!

Dienstag, 22. März 2011

Arquillian - Alpha 5 released

A new alpha version of Arquillian has been released some days ago. It includes support for things like multiple deployments, multiple containers and others. Take a look at the full release announcement here:

http://community.jboss.org/en/arquillian/blog/2011/03/18/arquillian-100-alpha5--released

Freitag, 18. März 2011

RichFaces 4 Showcase

JBoss RichFaces 4.0.0.Final is nearing gold status. Therefore the team now published a RichFaces Showcase application using Google´s App Engine. It can be found here:

http://richfaces-showcase.appspot.com/

If you want to try out the latest release candidate, RichFaces 4.0.0.CR1, you can also check out this article on how to use maven to include the neccesary libraries:

http://community.jboss.org/wiki/HowtoaddRichFaces4xtomavenbasedproject

Have fun trying.

Source: http://www.jboss.org/richfaces

Mittwoch, 9. Februar 2011

Arquillian - EJB3.1 Unit testing with JTA

In the last days i read a lot and testet much to see how integration testing / unit testing with stateless and stateful session beans could work. I found out that JavaEE6 introduced stuff like the EJBContainer, embedded glassfish and jboss appservers and some nice things like that. I managed to start and stop an embedded server and also posted in my last post how to add a datasource to this embedded glassfish (see this article). Now if you even want it to be another step simpler and easier, I would even recommend you to use a project called Arquillian. This tool uses ShrinkWrap to create a war file at unit test runtime, start your embedded server, deploy your war, start your tests and shutdown your embedded server again. What else would you wish? ;) It supports GlassFish, JBoss and some other appservers I guess... So give it a try.

There is just a couple of files you need. As earlier mentioned...
- the sun-resources.xml
- a persistence-test.xml using JTA (an example could be found in this article)
- a arquillian.xml file which could look like the following:


<?xml version="1.0" encoding="UTF-8"?>
<arquillian xmlns="http://jboss.com/arquillian"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gfembed="urn:arq:org.jboss.arquillian.container.glassfish.embedded_3">
<gfembed:container>
<gfembed:sunResourcesXml>src/test/resources/sun-resources.xml</gfembed:sunResourcesXml>
</gfembed:container>
</arquillian>


All of these files should reside in src/test/resources. And a unit test class could then look like this:


package de.mortensenit.myproduct.dao.jpa;

import de.mortensenit.myproduct.dao.AccountServiceDao;
import de.mortensenit.myproduct.model.Client;
import de.mortensenit.myproduct.model.User;
import java.io.File;
import javax.inject.Inject;
import static junit.framework.Assert.*;
import org.jboss.arquillian.api.Deployment;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Arquillian.class)
public class AccountServiceDaoJpaTest {

@Inject
private AccountServiceDao dao;

@Deployment
public static WebArchive createTestArchive() {
return ShrinkWrap.create(WebArchive.class, "test.war")
.addClasses(AccountServiceDaoJpa.class)
.addLibrary(new File("target/myproduct-model-1.0-SNAPSHOT.jar"))
.addManifestResource("persistence-test.xml", "persistence.xml")
.addManifestResource("sun-resources.xml")
.addWebResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
}

@Test
public void testFindClient() {
Client client = new Client();
client.setId("94aac911-189b-40cd-a03f-860c84fce3f2");
Client result = dao.find(Client.class, client);
assertEquals("94aac911-189b-40cd-a03f-860c84fce3f2", result.getId());
}


}


Last, but not least the pom.xml for the dependencies:

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<artifactId>myproduct</artifactId>
<groupId>de.mortensenit.myproduct</groupId>
<version>1.0-SNAPSHOT</version>
</parent>

<groupId>de.mortensenit.myproduct</groupId>
<artifactId>myproduct-jpa</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>ejb</packaging>
<name>myproduct-jpa</name>

<repositories>
<repository>
<id>jboss</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>glassfish-repository</id>
<name>Java.net Repository for Glassfish</name>
<url>http://download.java.net/maven/glassfish</url>
</repository>
<repository>
<id>java.net2</id>
<name>Java.Net Maven2 Repository, hosts the javaee-api dependency</name>
<url>http://download.java.net/maven/2</url>
</repository>
<repository>
<id>EclipseLink Repo</id>
<url>http://www.eclipse.org/downloads/download.php?r=1&nf=1&file=/rt/eclipselink/maven.repo</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>org.jboss.arquillian.container</groupId>
<artifactId>arquillian-glassfish-embedded-3</artifactId>
<version>1.0.0.Alpha4</version>
</dependency>
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.0.1-b02</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-junit</artifactId>
<version>1.0.0.Alpha4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.0-801.jdbc4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.mortensenit.myproduct</groupId>
<artifactId>myproduct-model</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>de.mortensenit.myproduct</groupId>
<artifactId>myproduct-dao</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

<build>
<plugins>
<!--
following plugin copies model jar into target folder because
the persistence unit needs it for the unit tests
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>compile</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>de.mortensenit.myproduct</groupId>
<artifactId>myproduct-model</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
<overWrite>true</overWrite>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.1</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>endorsed</id>
<activation>
<property>
<name>sun.boot.class.path</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<compilerArguments>
<bootclasspath>${settings.localRepository}/javax/javaee-endorsed-api/6.0/javaee-endorsed-api-6.0.jar${path.separator}${sun.boot.class.path}</bootclasspath>
</compilerArguments>
</configuration>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>6.0</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<netbeans.hint.deploy.server>gfv3ee6</netbeans.hint.deploy.server>
</properties>
</project>


For a deeper insight and good start, read also the following article:

http://community.jboss.org/en/arquillian/blog/2010/10/04/the-perfect-recipe-for-testing-jpa-2-revisited

By the way, a big thanks goes out to Adam Bien, aslak and jdlee for their help on this topic ;)