Grails Web Services

In this blog we’ll expose a Grails service as a SOAP service. According to good practice we’ll build the WSDL first and then write the implementation code.
First things first. Let’s create a new grails application and call it grails-soap

grails> create-app grails-soap

 

CXF

For SOAP support we’ll be using the Grails CXF plugin. Just add the following line in the plugin section of your BuildConfig.groovy file to enable the plugin. Documentation for the plugin can be found here.

compile ':cxf:1.1.1'

 

WSDL

We’ll start with building the WSDL for the service. The service will be called DepartmentService and will return some Department data for a given id. We’ll place the WSDL in the src/java folder.

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="DepartmentService"
	targetNamespace="http://devjournal/DepartmentService" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12s/"
	xmlns:tns="http://devjournal/DepartmentService">
	<wsdl:types>
		<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema">
			<import namespace="http://devjournal/DepartmentService"
				schemaLocation="DepartmentService.xsd" />
		</xsd:schema>
	</wsdl:types>
	<wsdl:message name="DepartmentServiceRequestMessage">
		<wsdl:part name="in" element="tns:DepartmentServiceRequest" />
	</wsdl:message>
	<wsdl:message name="DepartmentServiceResponseMessage">
		<wsdl:part name="out" element="tns:DepartmentServiceResponse" />
	</wsdl:message>
	<wsdl:portType name="GetDepartmentById">
		<wsdl:operation name="getDepartmentById">
			<wsdl:input message="tns:DepartmentServiceRequestMessage" />
			<wsdl:output message="tns:DepartmentServiceResponseMessage" />
		</wsdl:operation>
	</wsdl:portType>
	<wsdl:binding name="GetDepartmentByIdSoap12" type="tns:GetDepartmentById">
		<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"
			style="document" />
		<wsdl:operation name="getDepartmentById">
			<soap12:operation
				soapAction="http://whitehorses.nl/Whitebook_SOA_UT/DepartmentService/GetDepartmentById"
				style="document" />
			<wsdl:input>
				<soap12:body use="literal" parts="in" />
			</wsdl:input>
			<wsdl:output>
				<soap12:body use="literal" parts="out" />
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>
	<wsdl:service name="DepartmentService">
		<wsdl:port binding="tns:GetDepartmentByIdSoap12" name="GetDepartmentByIdSoap12">
			<soap12:address location="http://www.example.org/" />
		</wsdl:port>
	</wsdl:service>
</wsdl:definitions>

The underlying xml schema file contains the response element. This file will also be placed in the src/java folder.

<?xml version="1.0" encoding="UTF-8"?>
<schema attributeFormDefault="unqualified" elementFormDefault="qualified"
        targetNamespace="http://devjournal/DepartmentService"
        xmlns:tns="http://devjournal/DepartmentService"
        xmlns="http://www.w3.org/2001/XMLSchema">
 <element name="DepartmentServiceRequest">
  <complexType>
   <sequence>
    <element name="Id" type="int"/>
   </sequence>
  </complexType>
 </element>
 <element name="DepartmentServiceResponse">
  <complexType>
   <sequence>
    <element name="Department" type="tns:departmentType" maxOccurs="1"
             minOccurs="0"/>
   </sequence>
  </complexType>
 </element>
 <complexType name="departmentType">
  <sequence>
   <element name="Id" type="int"/>
   <element name="Name" type="string"/>
   <element name="Location" type="string"/>
  </sequence>
 </complexType>
</schema>

 

wsdl2java

Now that we have the WSDL it’s time to generate the Java stubs. Although the CXF plug-in comes with a wsdl-to-java command it kept giving me a “GroovyCastException” when I tried to run it. To workaround this problem, I downloaded the latest apache-cxf distribution here (2.7.11 at the time of this writing) and used its wsdl2java command to generate the stubs.

$ $CXF_HOME/apache-cxf-2.7.11/bin/wsdl2java DepartmentService.wsdl

After running this command from within the /src/java directory, the following stub classes are added to your grails application:

wsdl2java classes

wsdl2java classes

 

service

Now everything is in place, we can start implementing the service. First create a new grails service component called DepartmentService

grails> create-service department

We’ll have this service implement the generated @WebService interface GetDepartmentById and override the getDepartmentById method (corresponding with the SOAP operation of the same name) For simplicity sake, we’ll just hardcode a response:

package grails.soap

import javax.jws.WebService

import org.grails.cxf.utils.EndpointType

import devjournal.departmentservice.DepartmentServiceRequest
import devjournal.departmentservice.DepartmentServiceResponse
import devjournal.departmentservice.DepartmentType
import devjournal.departmentservice.GetDepartmentById


@WebService(targetNamespace = "http://devjournal/DepartmentService", name = "GetDepartmentById", serviceName = 'DepartmentService',
portName = 'GetDepartmentById')
class DepartmentService implements GetDepartmentById {

	static expose = EndpointType.JAX_WS_WSDL
	static soap12 = true
	static address = 'DepartmentService'
	
	def serviceMethod() {
	}

	@Override
	public DepartmentServiceResponse getDepartmentById(
			DepartmentServiceRequest departmentServiceRequest) {

		DepartmentType department = new DepartmentType(id: departmentServiceRequest.id, location:'Amsterdam', name: 'Sales')
		return new DepartmentServiceResponse(department:department)
	}
}

As you can see in the code above, we’ve implemented the GetDepartmentById interface and added the @WebService annotation to the service. With the serviceName and portName attributes we can influence the WSDL that’s eventually being served.
The cxf-plugin allows further configuration by means of static properties. Setting the soap12 property to “true” makes the DepartmentService adhere to the SOAP 1.2 specification. With the address property we can adjust the endpoint of the service. By default it would be the default address of the grails service, i.e. “/services/department”. In the above example the endpoint will be “/services/DepartmentService”. Refer to the cxf-plugin documentation for an overview of available properties.
 

Testing the web service

Now let’s fire up the application and give it a spin

grails> run-app

The WSDL should be available at http://localhost:8080/services/DepartmentService?WSDL and can be tested with SoapUI. The screenshot below shows the result.

DepartmentService Test

DepartmentService Test


 

Conclusion

In this blog I’ve shown how easy it is to expose a grails service via SOAP. Although the service had been turned into a SOAP service it’s still available as a normal grail service to the rest of the application, so there’s no violation of the DRY principle and code can be reused.

Mule – Building a webservice proxy

In this blogpost we’ll develop a simple webservice proxy using the latest Mule Studio Community Edition (currently version 1.3.1 which uses Mule ESB v.3.3), which can be downloaded here. The proxy will do some basic routing. No transformation will be done. That area will be explored in a future blogpost.

webservice proxy

mule proxy service

The webservice which will be used for proxying is a simple jax-ws webservice for retrieving employee data based on their department id. The webservice will be exposed via the following url: http://localhost:8083/HR/hrManagerService?wsdl. See this blogpost for building a simple jax-ws webservice on your own.

Creating a new Mule project

First we’ll create a new Mule project based on Maven. This can be done in 3 simple steps. First select File > New > Mule Project. Give the project a Name and a Description and click Next >.

Screenshot from 2013-01-03 12:35:35

New Mule Project – Step 1 of 3

Now, create a flow for the project. Give it a Name, File name and a Description and click Next >.

Screenshot from 2013-01-03 12:35:55

New Mule Project – Step 2 of 3

Finally select the option for creating the Maven pom.xml file and fill in a Group Id and Artifact Id and click Finish.

Screenshot from 2013-01-03 12:39:13

New Mule Project – Step 3 of 3

That’s all. We’ve created the skeleton for our web service proxy and are now ready to implement the flow.

Building the flow

Open the mule-proxy.mflow file and drag a Flow Scope into it. Give it an appropriate name, like MuleProxyFlow.

MuleProxyFlow-begin

MuleProxyFlow

Now let’s build the flow for the proxy service back to front. We’ll begin with adding a HTTP Endpoint to the flow which will resemble the webservice we’re gonna proxy. Right click the Endpoint and select Convert to an outbound endpoint. Next select Properties, clear the Host and Port values and fill in the endpoint of the webservice in the Address field.

Screenshot from 2013-01-03 14:34:20

HTTP Outbound Endpoint Properties – General

Screenshot from 2013-01-03 14:41:01

HTTP Outbound Endpoint Properties – Advanced

Next, we’ll create a client for the web service. Select a SOAP Component and drag it to the left of the HTTP Endpoint. Change the Operation field to Proxy client.

Screenshot from 2013-01-03 14:54:31

SOAP Component – Proxy client

Now for the actual proxy service. Select another SOAP Component and drag it to the left of the Proxy client SOAP Component. Change the Operation to Proxy service. Fill in the Namespace and Service as well. They have to match the targetNamespace and name of the webservice as defined in the wsdl we’re gonna use for the proxy. Make sure that the Payload of the Proxy service and Proxy client match (in this example I choose to only exchange the SOAP body).

Screenshot from 2013-01-03 15:12:52

SOAP Component – Proxy service – General

In the Advanced section we’ll fill in the WSDL Location of the actual wsdl, which will serve as the wsdl for the proxy service. In this simple example, the wsdl of the proxy will match the wsdl of the actual webservice. I’ve raken the liberty to copy the wsdl and xsd files to the src/main/resources/wsdl and src/main/resources/xsd directories of the project. But for the sake of simplicity, you could also pick up the wsdl from it’s actual location, i.e. http://localhost:8083/HR/hrManagerService?wsdl and use that as the WSDL Location in the case of this example.

Screenshot from 2013-01-03 17:57:42

SOAP Component – Proxy service – Advanced

Finally, we’ll need to add the HTTP inbound endpoint. Again, clear the Host and Port fields and add the Address you’d like to use for the proxy, in this example it will be http://localhost:8081/hrManagerServiceProxy.

Screenshot from 2013-01-03 15:27:38

HTTP Inbound Endpoint Properties – General

Screenshot from 2013-01-03 15:27:50

HTTP Inbound Endpoint Properties – Advanced

That’s it. If you followed these steps correctly, your flow should resemble the flow below.

MuleProxyFlow-end

MuleProxyFlow

The xml configuration (src/main/app/mule-proxy.xml) should look like the code below.

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/cxf http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
  <flow name="MuleProxyFlow" doc:name="MuleProxyFlow">
    <http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8081/hrManagerServiceProxy" doc:name="HTTP"/>
    <cxf:proxy-service namespace="http://service.hrmanager.hr.whitehorses.nl/" service="HRManagerServiceImplService" payload="body" doc:name="SOAP" enableMuleSoapHeaders="false" wsdlLocation="wsdl/hrManagerService.wsdl"/>
    <cxf:proxy-client doc:name="SOAP" payload="body"/>
    <http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8083/HR/hrManagerService" doc:name="HTTP"/>
  </flow>
</mule>

Testing the proxy

Mule Studio

Now, let’s run the Mule proxy. You can do this directly inside Mule Studio by choosing Run As > Mule Application.

Maven

You can also use maven via the command line:

mvn clean install

There’s a small issue with the generated pom.xml file in this version of the Community Edition. If you use it as is, you’ll get an error concerning missing dependencies. To fix this, open the pom.xml file and search for the following snippet:

<dependency>
  <groupId>com.mulesoft.muleesb</groupId>
  <artifactId>mule-core-ee</artifactId>
  <version>${mule.version}</version>
  <scope>provided</scope>
</dependency>
<!-- Xml configuration -->
<dependency>
  <groupId>com.mulesoft.muleesb.modules</groupId>
  <artifactId>mule-module-spring-config-ee</artifactId>
  <version>${mule.version}</version>
  <scope>provided</scope>
</dependency>

Replace it with this one:

<dependency>
  <groupId>org.mule</groupId>
  <artifactId>mule-core</artifactId>
  <version>${mule.version}</version>
  <scope>provided</scope>
</dependency>
<!-- Xml configuration -->
<dependency>
  <groupId>org.mule.modules</groupId>
  <artifactId>mule-module-spring-config</artifactId>
  <version>${mule.version}</version>
  <scope>provided</scope>
</dependency>

Also you need to have a mule server running for this to work. See this blogpost for details. The install goal will deploy the mule project to the $MULE_HOME/apps directory of the mule server installation and if the server is running, it wil startup the project automatically.

SoapUI

Regardless of the way you’re running the mule project, be it via Maven or via Mule Studio, you should be able to test the proxy now with soapUI. Create a New Project, point it to the wsdl of the proxy, i,e. http://localhost:8081/hrManagerServieProxy?wsdl, and add a default TestSuite. Now you can run a TestCase against the proxy and it should yield the same result as it would when you’d call the webservice behind it directly.

Screenshot from 2013-01-03 21:26:50

soapUI – Testing the proxy

Summary

In this blogpost we’ve created a simple webservice proxy which does some basic routing without any kind of transformation. In the next post we’ll add some transformation and basic logging to the mix.

Developing a contract-first JAX-WS webservice

In this blog i’ll develop a simple webservice using JAX-WS. I’ll first start with the contract (wsdl and xsd’s). The contract will be used for generating the necessary JAXB artifacts. Getting the webservice up and running will be a piece of cake after that all thanks to Maven and JAX-WS.
First things first, let’s create a new Maven project. I’m using Netbeans as IDE for this.

New Maven Web Application

First Create a new Maven Web Application

and call it hello_person for example

The Contract

The webservice will accept a Person graph with a first and last name and will return a concatenated “Hello first name last name!”. Not very original but good enough for the example.
First we’ll define the xsd called helloPersonService.xsd for the request and response. The request will contain a Person object with a first and last name, the response will contain a Greetings string. We’ll store it in src/main/resources/xsd.

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            elementFormDefault="qualified"
            xmlns="http://example.nl/hellopersonservice/1.0"
            targetNamespace="http://example.nl/hellopersonservice/1.0">
    <xsd:element name="HelloPersonServiceRequest" type="HelloPersonServiceRequestType"/>
    <xsd:element name="HelloPersonServiceResponse" type="HelloPersonServiceResponseType"/>

    <xsd:complexType name="HelloPersonServiceRequestType">
        <xsd:element name="Person" type="PersonType"/>
    </xsd:complexType>
    
    <xsd:complexType name="HelloPersonServiceResponseType">
        <xsd:element name="Greetings" type="xsd:string"/>
    </xsd:complexType>

    <xsd:complexType name="PersonType">
        <xsd:sequence>
            <xsd:element name="FirstName" type="xsd:string"/>
            <xsd:element name="LastName" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

Now we’ll define a wsdl called helloPersonService.wsdl and we’ll store it in src/main/resources/wsdl

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
    name="helloPersonService"
    targetNamespace="http://example.nl/hellopersonservice/1.0"
    xmlns:tns="http://example.nl/hellopersonservice/1.0"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    >
    <wsdl:types>
        <xsd:schema targetNamespace="http://example.nl/hellopersonservice/1.0">
            <xsd:import schemaLocation="../xsd/helloPersonService.xsd"
                        namespace="http://example.nl/hellopersonservice/1.0"/>
        </xsd:schema>
    </wsdl:types>
    <wsdl:message name="HelloPersonServiceRequest">
        <wsdl:part name="HelloPersonServiceRequest" element="tns:HelloPersonServiceRequest"/>
    </wsdl:message>
    <wsdl:message name="HelloPersonServiceResponse">
        <wsdl:part name="HelloPersonServiceResponse" element="tns:HelloPersonServiceResponse"/>
    </wsdl:message>
    <wsdl:portType name="HelloPersonServicePortType">
        <wsdl:operation name="greetPerson">
            <wsdl:input name="HelloPersonServiceRequest" message="tns:HelloPersonServiceRequest"/>
            <wsdl:output name="HelloPersonServiceResponse" message="tns:HelloPersonServiceResponse"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="HelloPersonServiceBinding" type="tns:HelloPersonServicePortType">
        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="greetPerson">
            <soap:operation style="document" soapAction="http://example.nl/HelloPersonService/greetPerson"/>
            <wsdl:input name="HelloPersonServiceRequest">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="HelloPersonServiceResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="HelloPersonService">
        <wsdl:port name="HelloPersonServicePort" binding="tns:HelloPersonServiceBinding">
            <soap:address location="/service/helloPersonService" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

Getting the pom right

Next up is adding the necessary component to the pom file. We need the jax-ws runtime libraries, the jetty plugin as we use jetty as the servlet container, and the jaxws-maven-plugin for generating the java code from the contract. I’ve highlighted these dependencies in the pom file below.

<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>nl.example</groupId>
    <artifactId>hello_person</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>hello_person Java EE 6 Webapp</name>
    <url>http://maven.apache.org</url>
    <repositories>
        <repository>
            <id>java.net2</id>
            <name>Repository hosting the jee6 artifacts</name>
            <url>http://download.java.net/maven/2</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>java.net2</id>
            <name>Repository hosting the jee6 artifacts</name>
            <url>http://download.java.net/maven/2</url>
        </pluginRepository>
    </pluginRepositories>
    <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.ws</groupId>
            <artifactId>jaxws-rt</artifactId>
            <version>2.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>

        <plugins>
            <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-war-plugin</artifactId>
                <version>2.1-beta-1</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <configuration>
                    <webAppConfig>
                        <contextPath>hello_person</contextPath>
                    </webAppConfig>
                    <connectors>
                        <connector implementation="org.eclipse.jetty.nio.SelectChannelConnector">
                            <port>8083</port>
                        </connector>
                    </connectors>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${basedir}/target/generated/src/main/java</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>1.12</version>
                <configuration>
                    <wsdlDirectory>${basedir}/src/main/resources/wsdl</wsdlDirectory>
                    <packageName>nl.example.hello_person.service.generated</packageName>
                    <keep>true</keep>
                    <sourceDestDir>${basedir}/target/generated/src/main/java</sourceDestDir>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>wsimport</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
        <finalName>hello_person</finalName>
    </build>
</project>

Writing the implementation

First, let’s do a Clean and Build in NetBeans. This will generate the JAXB/JAX-WS artifacts from the contract.
Notice that the jaxws-maven-plugin has generated an interface called nl.example.hello_person.service.generated.HelloPersonServicePortType for the PortType in the wsdl. This is the interface we have to implement. The code for the implementation is pretty straightforward. I’ve added it below for convenience. Notice that the implementation class is called nl.example.hello_person.service.HelloPersonServiceImpl. We’ll need this in one of the next steps. Also notice the necessary @WebService annotation. The endpointInterface atribute points of course to the generated interface.

package nl.example.hello_person.service;

import javax.jws.WebService;
import nl.example.hello_person.service.generated.HelloPersonServiceRequestType;
import nl.example.hello_person.service.generated.HelloPersonServiceResponseType;

@WebService(endpointInterface="nl.example.hello_person.service.generated.HelloPersonServicePortType")
public class HelloPersonServiceImpl implements nl.example.hello_person.service.generated.HelloPersonServicePortType {

    @Override
    public HelloPersonServiceResponseType greetPerson(HelloPersonServiceRequestType helloPersonServiceRequest) {
        HelloPersonServiceResponseType helloPersonServiceResponse = new HelloPersonServiceResponseType();
        helloPersonServiceResponse.setGreetings("Hello " + helloPersonServiceRequest.getPerson().getFirstName() + " " + helloPersonServiceRequest.getPerson().getLastName() + "!");
        return helloPersonServiceResponse;
    }

}

The web.xml file

Now, add a web.xml file to the project (you can do this via New File > Web > Standard Deployment Descriptor (web.xml)) and add the proper configuration for the jax-ws servlet to it:

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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/web-app_3_0.xsd"
         version="3.0">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <listener>
        <listener-class>
            com.sun.xml.ws.transport.http.servlet.WSServletContextListener
        </listener-class>
    </listener>
    <servlet>
        <description>JAX-WS endpoint</description>
        <display-name>The JAX-WS servlet</display-name>
        <servlet-name>jaxws</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>jaxws</servlet-name>
        <url-pattern>/helloPersonService</url-pattern>
    </servlet-mapping>
</web-app>

The sun-jaxws.xml file

The last step is adding the sun-jaxws.xml file to the WEB-INF directory of the project. This is the content of the file:

<?xml version="1.0" encoding="UTF-8"?>
<endpoints
    xmlns='http://java.sun.com/xml/ns/jax-ws/ri/runtime'
    version='2.0'>
    <endpoint
        name='helloPersonService'
        implementation='nl.example.hello_person.service.HelloPersonServiceImpl'
        url-pattern='/helloPersonService' />
</endpoints>

Notice that the implementation attribute is pointing to our implementation class.

Running the service

Add jetty:run as custom action (via Run > Set Project Configuration > Customize > Actions) and run it.
Now open a browser and check the following url http://localhost:8083/hello_person/helloPersonService. If you see the following screen, the webservice is up and running!

Testing the service

For testing I’m using the soapUI plugin for Netbeans.
After you’ve installed the plugin, you can create a new Web Service Testing Project (New Project > SOA > Web Service Testing Project)

Point the initial WSDL property to the url you’ve seen on the Web Services page: http://localhost:8083/hello_person/helloPersonService?wsdl.

The testsuite now contains a greetPerson Test Step. You can now test if the service works. If all goes well, you should see something similar to the picture below.

%d bloggers like this: