Saturday, March 28, 2015

Creating a Jersey WebService In Gatein 3.8.1/JBOSS

I have recently been playing around with GateIn at work. GateIn allows you to build a custom portal based on portlets you can develop in Java. Since it is built on JBOSS it offers things like application clustering and SSO, so its a pretty nice open source product.

However, being new to JBOSS (and java development in general) I ran into a few frustrating issues while trying to deploy a webservice application. After a few days of plugging away at it and reading some helpful blogs I was able to get it working. The issue is that GateIn/JBOSS loads its own implementation of JAX-RS and will not allow you to load any others unless you explicitly say not to in your webapp.

In this blog I will go over how to create a simple REST web service using Jersey that can be deployed and used in GateIn/JBOSS

Prerequisites (what I will be using)

  • Eclipse Luna with Dynamic Web Project Installed
  • GateIn 3.8.1 JBOSS available here
  • Java SDK (The project will need to be set to use 1.7 compatibility)
Project Setup

1. Create a new Dynamic Web Project with the Project name "hellows" and select next


2. Select next again to accept the default output folder
3. Select the checkbox next to Generate web.xml deployment descriptor and leave the rest of the defaults and then select finish to create the project


4. Since we will be using Maven to manage the dependencies, right click on the hellows project and select Configure > Convert to Maven Project
5. In the Create new POM window change the Group Id to com.vbranden (or whatever you like) and leave the rest of the defaults. Then select finish to convert the project

6. Open the hellows/pom.xml file, select the pom.xml tab on the bottom and replace it with the following then save. This will download the dependencies and place them in the project's classpath

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>com.horiuchi</groupId>  
  <artifactId>testws</artifactId>  
  <version>0.0.1-SNAPSHOT</version>  
  <packaging>war</packaging>  
  <build>  
   <sourceDirectory>src</sourceDirectory>  
   <plugins>  
    <plugin>  
     <artifactId>maven-compiler-plugin</artifactId>  
     <version>3.1</version>  
     <configuration>  
      <source>1.8</source>  
      <target>1.8</target>  
     </configuration>  
    </plugin>  
    <plugin>  
     <artifactId>maven-war-plugin</artifactId>  
     <version>2.4</version>  
     <configuration>  
      <warSourceDirectory>WebContent</warSourceDirectory>  
      <failOnMissingWebXml>false</failOnMissingWebXml>  
     </configuration>  
    </plugin>  
   </plugins>  
  </build>  
  <dependencies>  
       <dependency>  
            <groupId>org.glassfish.jersey.containers</groupId>  
            <artifactId>jersey-container-servlet</artifactId>  
            <version>2.17</version>  
       </dependency>  
       <dependency>  
            <groupId>org.glassfish.jersey.media</groupId>  
            <artifactId>jersey-media-json-jackson</artifactId>  
            <version>2.17</version>  
       </dependency>  
  </dependencies>  
 </project>  

7. Update the web.xml file in hellows/WebContent/WEB-INF and replace it with the following and save

web.xml
 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xmlns="http://java.sun.com/xml/ns/javaee"  
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  
      id="WebApp_ID" version="3.0">  
      <display-name>hellows</display-name>  
      <servlet>  
           <servlet-name>hellows servlet</servlet-name>  
           <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>  
           <init-param>  
                <param-name>javax.ws.rs.Application</param-name>  
                <param-value>com.vbranden.HelloApplication</param-value>  
           </init-param>  
           <load-on-startup>1</load-on-startup>  
      </servlet>  
      <servlet-mapping>  
           <servlet-name>hellows servlet</servlet-name>  
           <url-pattern>/*</url-pattern>  
      </servlet-mapping>  
      <context-param>  
           <param-name>resteasy.scan</param-name>  
           <param-value>false</param-value>  
      </context-param>  
      <context-param>  
           <param-name>resteasy.scan.resources</param-name>  
           <param-value>false</param-value>  
      </context-param>  
      <context-param>  
           <param-name>resteasy.scan.providers</param-name>  
           <param-value>false</param-value>  
      </context-param>  
 </web-app>  

8. Now we need to create the actual web service. First we will create the object model for our hellows response. Create a new class under Java Resources/src named HelloObject.java and modify the package to com.vbranden.models. Keep the rest of the defaults


Replace the code for HelloObject.java with the following

HelloObject.java
 package com.vbranden.models;  
 import javax.xml.bind.annotation.XmlElement;  
 import javax.xml.bind.annotation.XmlRootElement;  
 @XmlRootElement(name = "HelloObject")  
 public class HelloObject {  
      private String type;  
      private String message;  
      public HelloObject() {}  
      public HelloObject(String type, String message) {  
           this.setType(type);  
           this.setMessage(message);  
      }  
      /**  
       * @return the message  
       */  
      @XmlElement  
      public String getMessage() {  
           return message;  
      }  
      /**  
       * @param message the message to set  
       */  
      public void setMessage(String message) {  
           this.message = message;  
      }  
      /**  
       * @return the type  
       */  
      @XmlElement  
      public String getType() {  
           return type;  
      }  
      /**  
       * @param type the type to set  
       */  
      public void setType(String type) {  
           this.type = type;  
      }  
 }  

9. Create a new class under Java Resources/src named HelloResource.java and modify the package to com.vbranden.resources. Keep the rest of the defaults


Replace the code for HelloResource.java with the following

HelloResource.java
 package com.vbranden.resources;  
 import javax.ws.rs.GET;  
 import javax.ws.rs.Path;  
 import javax.ws.rs.Produces;  
 import javax.ws.rs.core.MediaType;  
 import javax.ws.rs.core.Response;  
 import com.vbranden.models.HelloObject;  
 @Path("/rest")  
 public class HelloResource {  
      @Path("hello")  
      @GET  
      @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})  
      public Response getHello() {  
           // create a new HelloObject  
           HelloObject hello = new HelloObject("Flanders", "Hi-diddly-ho, neighborino");  
           return Response.ok().entity(hello).build();  
      }  
 }  

10. Next we need to create a class that extends ResourceConfig. This class will point to the package where our resources are. Create a new class under Java Resources/src named HelloApplication.java and modify the package to com.vbranden. Keep the rest of the defaults



Replace the code for HelloApplication.java with the following

HelloApplication.java
 package com.vbranden;  
 import org.glassfish.jersey.server.ResourceConfig;  
 public class HelloApplication extends ResourceConfig {  
      public HelloApplication() {  
           packages("com.vbranden.resources");  
      }  
 }  

11. Finally in order to use this project as a web service in GateIn/JBOSS we need to add the jboss-deployment-structure.xml file to the folder hellows/WebContent/META-INF. Right click the folder and select New > File and create jboss-deployment-structure.xml

Replace the code for jboss-deployment-structure.xml with the following

jboss-deployment-structure.xml
 <?xml version="1.0" encoding="UTF-8"?>  
 <jboss-deployment-structure>  
 <deployment>  
 <exclude-subsystems>  
  <subsystem name="resteasy" />  
 </exclude-subsystems>  
 <exclusions>  
  <module name="javaee.api" />  
  <module name="javax.ws.rs.api"/>  
  <module name="org.jboss.resteasy.resteasy-jaxrs" />  
 </exclusions>  
 <local-last value="true" />  
 </deployment>  
 </jboss-deployment-structure>  

12. Now export the project as a WAR file to the directory $GATEIN_HOME/standalone/deployments/hellows.war. GateIn will automatically deploy the web service and it will be ready to test

13. Using a tool like POSTMAN you can quickly check the web service by making a get request to http://127.0.0.1:8080/hellows/rest/hello


Without any options the response will be XML formatted. If you would like a JSON response add an Accept header for application/json


And thats it! Hopefully this will help out those of you with problems getting a JAX-RS webservice to work in GateIn or JBOSS.