February 18, 2010

Getting Started with JBoss Web Serivce using JAX-WS on JBoss 5.1 using Maven, OpenEJB and eviware soapUI

The easiest way to get started with writing Web Service is using Java API for XML Web Service, JAX-WS. The downside with this is that the creation of the WSDL file is automatic, and that is not the preferred way of writing cross platform independent web service. If that is your design goal, you should handwrite the WSDL, i.e. contract first. But if you know that the only clients are going to be Java client, than automatically generating the WSDL could be fine.

A good practice when writing all kind of code, is to make the code testable and also make it testable outside the container. To achieve that I will use OpenEJB, if have never heard or used OpenEJB and you are writing EJB 3.0 applications, it is definitely worth the time to check it out.

Lets start with writing a standard Stateless EJB.

package se.msc.example.jbossws;

import javax.ejb.Remote;
import javax.jws.WebService;

@Remote
public interface HelloService {

 public String sayHello();
}


package se.msc.example.jbossws;

import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@Stateless
public class HelloServiceBean implements HelloService {

 @Override
 public String sayHello() {
  return "Hello World.";
 }
}


src/main/resources/META-INF/ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"
 version="3.0">

</ejb-jar>


src/main/resources/META-INF/jboss.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 
<jboss xmlns="http://www.jboss.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_5_1.xsd"
       version="3.0"> 
-->
<jboss>       
 
</jboss>


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>se.msc.example</groupId>
 <artifactid>jbossws</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>ejb</packaging>
 <name>JBoss WS Test</name>
 <url>http://www.msc.se/example/jbossws</url>
 <developers>
  <developer>
   <id>magnus.k.karlsson</id>
   <name>Magnus K Karlsson</name>
   <email>magnus.k.karlsson@msc.se</email>
   <organization>MSC</organization>
  </developer>
 </developers>
 <repositories>
  <repository>
   <id>repository.jboss.org</id>
   <name>Jboss Repository for Maven</name>
   <url>http://repository.jboss.org/maven2/</url>
  </repository>
 </repositories>
 <pluginrepositories>
  <pluginrepository>
   <id>repository.jboss.org</id>
   <name>Jboss Repository for Maven</name>
   <url>http://repository.jboss.org/maven2/</url>
  </pluginRepository>
 </pluginRepositories>
 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <jboss.home>/home/magnus/applications/jboss-5.1.0.GA-jdk6</jboss.home>
 </properties>
 <dependencies>
  <!-- sun's ejb 3.0 api -->
  <dependency>
   <groupid>javax.ejb</groupId>
   <artifactid>ejb-api</artifactId>
   <version>3.0</version>
   <scope>provided</scope>
  </dependency>
  <!-- jboss logging impl (jboss 5.1.0 GA) -->
  <dependency>
   <groupid>log4j</groupId>
   <artifactid>log4j</artifactId>
   <version>1.2.14</version>
   <scope>provided</scope>
  </dependency>
  <!-- unit testing -->
  <dependency>
   <groupid>junit</groupId>
   <artifactid>junit</artifactId>
   <version>4.7</version>
   <scope>test</scope>
  </dependency>
 </dependencies>
 <build>
  <finalname>jbossws-example</finalName>
  <plugins>
   <!-- to compile with jdk 1.6 -->
   <plugin>
    <groupid>org.apache.maven.plugins</groupId>
    <artifactid>maven-compiler-plugin</artifactId>
    <version>2.1</version>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>
   <!-- ejb 3.0 plugin -->
   <plugin>
    <groupid>org.apache.maven.plugins</groupId>
    <artifactid>maven-ejb-plugin</artifactId>
    <version>2.2</version>
    <configuration>
     <ejbversion>3.0</ejbVersion>
    </configuration>
   </plugin>
   <!-- plugin to harddeploy, hardundeploy, start and stop jboss -->
   <plugin>
    <groupid>org.codehaus.mojo</groupId>
    <artifactid>jboss-maven-plugin</artifactId>
    <version>1.4</version>
    <configuration>
     <jbosshome>${jboss.home}</jbossHome>
     <servername>default</serverName>
     <port>8080</port>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>


Now lets test our EJB with OpenEJB. The first thing we need to do, is to add the OpenEJB dependency to our pom.xml

  <dependency>
   <groupid>org.apache.openejb</groupId>
   <artifactid>openejb-core</artifactId>
   <version>3.1.2</version>
   <scope>test</scope>
  </dependency>


Then we write our JUnit test case.

package se.msc.example.jbossws;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class HelloServiceStatelessTest {
 private InitialContext ctx;

 @BeforeClass
 public static void oneTimeSetUp() throws Exception {
 }

 @AfterClass
 public static void oneTimeTearDown() throws Exception {
 }

 @Before
 public void setUp() throws Exception {
  Properties prop = new Properties();
  prop.setProperty(Context.INITIAL_CONTEXT_FACTORY,
    "org.apache.openejb.client.LocalInitialContextFactory");
  ctx = new InitialContext(prop);
 }

 @After
 public void tearDown() throws Exception {
 }

 @Test
 public void testSayHello() throws Exception {
  Object obj = ctx.lookup("HelloServiceBeanRemote");
  assertNotNull(obj);
  assertTrue(obj instanceof HelloService);
  HelloService remote = (HelloService) obj;
  assertEquals("Hello World.", remote.sayHello());
 }
}


After verifying that our Stateless Session Bean is working, we now continue to deploy it to the JBoss container.

$ mvn clean install jboss:harddeploy


We start our JBoss container and checks that the EJB is successfully deployed.

Now lets add Web Service support to our EJB.

package se.msc.example.jbossws;

import javax.ejb.Remote;
import javax.jws.WebService;

@Remote
@WebService(targetNamespace = "http://www.msc.se/examples/jbossws/wsdl")
public interface HelloService {

 public String sayHello();
}


package se.msc.example.jbossws;

import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@Stateless
@WebService(serviceName = "HelloService", 
  targetNamespace = "http://www.msc.se/examples/jbossws/wsdl", 
  endpointInterface = "se.msc.example.jbossws.HelloService")
@SOAPBinding(style = Style.DOCUMENT)
public class HelloServiceBean implements HelloService {

 @Override
 public String sayHello() {
  return "Hello World.";
 }
}


Now lets write our JUnit test case, to test our web service outside the JBoss container.

package se.msc.example.jbossws;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import java.net.URL;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class HelloServiceWebServiceTest {
 private InitialContext ctx;

 @BeforeClass
 public static void oneTimeSetUp() throws Exception {
 }

 @AfterClass
 public static void oneTimeTearDown() throws Exception {
 }

 @Before
 public void setUp() throws Exception {
  Properties prop = new Properties();
  prop.setProperty(Context.INITIAL_CONTEXT_FACTORY,
    "org.apache.openejb.client.LocalInitialContextFactory");
  prop.setProperty("openejb.embedded.remotable", "true");
  ctx = new InitialContext(prop);
 }

 @After
 public void tearDown() throws Exception {
 }

 @Test
 public void testWebService() throws Exception {
  Service service = Service.create(
    new URL("http://127.0.0.1:4204/HelloServiceBean?wsdl"), 
    new QName("http://www.msc.se/examples/jbossws/wsdl", "HelloService"));
  assertNotNull(service);
  HelloService hello = service.getPort(HelloService.class);
  assertEquals("Hello World.", hello.sayHello());
 }
}


Before running the testcase we need to update our pom.xml with a concrete web service implementation.

  <dependency>
   <groupid>org.apache.openejb</groupId>
   <artifactid>openejb-cxf</artifactId>
   <version>3.1.2</version>
   <scope>test</scope>
  </dependency>


After running the testcase from withing Eclipse, we can now be confident that we our is executing as expected. Now lets deploy our EJB to the JBoss container.

$ mvn clean install jboss:harddeploy


If you have stopped the JBoss, then restarted and verify that everything is looking healthy in the server log. Verify that the web service is working by firing up a web browser and go to http://localhost:8080/jbossws-example/HelloServiceBean?wsdl, to verify that you see the wsdl file.

Instead of writing a web service client, we are going to use a good test tool for testing web service – eviware soapUI. Start the soapUI and then select new project.

 

  

 

No comments: