SeedStack Web-Services add-on provides JAX-WS integration through the Metro reference implementation.

Dependencies

In a standalone environment (not a Web server), use the following dependency:

<dependency>
    <groupId>org.seedstack.addons.ws</groupId>
    <artifactId>web-services-core</artifactId>
</dependency>
Show version
dependencies {
    compile("org.seedstack.addons.ws:web-services-core:3.0.0")
}

In a Web environment, use the following dependency instead:

<dependency>
    <groupId>org.seedstack.addons.ws</groupId>
    <artifactId>web-services-web</artifactId>
</dependency>
Show version
dependencies {
    compile("org.seedstack.addons.ws:web-services-web:3.0.0")
}

WSDL and XSD files

The WSDL and its optional XSD files must be placed under the META-INF/ws classpath directory to be properly detected by the Web-Services add-on. The WSDL below is used as a base for examples of this documentation.

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
        xmlns="http://schemas.xmlsoap.org/wsdl/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        targetNamespace="http://myproject.myorganization.org/wsdl/seed/hello/"
        xmlns:tns="http://myproject.myorganization.org/wsdl/seed/hello/"
        name="HelloService">

    <wsdl:message name="sayHello">
        <wsdl:part name="firstName" type="xsd:string"/>
    </wsdl:message>
    <wsdl:message name="sayHelloResponse">
        <wsdl:part name="return" type="xsd:string"/>
    </wsdl:message>

    <wsdl:portType name="Hello">
        <wsdl:operation name="sayHello">
            <wsdl:input message="tns:sayHello"/>
            <wsdl:output message="tns:sayHelloResponse"/>
        </wsdl:operation>
    </wsdl:portType>

    <wsdl:binding name="HelloServicePortBinding" type="tns:Hello">
        <soap:binding style="rpc"   transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="sayHello">
            <soap:operation soapAction=""/>
            <wsdl:input>
                <soap:body
                        namespace="http://myproject.myorganization.org/wsdl/seed/hello/"
                        use="literal"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body
                        namespace="http://myproject.myorganization.org/wsdl/seed/hello/"
                        use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="HelloService">

        <wsdl:port name="HelloServicePort" binding="tns:HelloServicePortBinding">
            <wsdl:documentation>Hello World</wsdl:documentation>
            <soap:address location="http://localhost:8080/ws/hello"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

WS-import Maven goal

WS-import is a tool which generates JAX-WS classes from WSDL such as:

  • Service Endpoint Interface (SEI)
  • Client Service
  • Exception class mapped from wsdl:fault
  • JAXB generated value types (mapped java classes from schema types)

You have to generate those artifacts to be able to consume or publish a Web-Service. A typical usage of the plugin can be:

<build>
    <plugins>
        <plugin>
            <groupId>org.jvnet.jax-ws-commons</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <version>2.3</version>
            <executions>
                <execution>
                    <id>wsimport</id>
                    <goals>
                        <goal>wsimport</goal>
                    </goals>
                    <phase>generate-sources</phase>
                    <configuration>
                        <verbose>true</verbose>
                        <wsdlDirectory>src/main/resources/META-INF/ws</wsdlDirectory>
                        <wsdlLocation>META-INF/ws/Hello.wsdl</wsdlLocation>
                        <wsdlFiles>
                            <wsdlFile>Hello.wsdl</wsdlFile>
                        </wsdlFiles>
                        <!-- The extension flag below is needed to use JMS transport -->
                        <extension>true</extension> 
                        <target>2.1</target>
                        <genJWS>false</genJWS>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

You can find more information about jaxws-maven-plugin here.

Consuming

JAX-WS classes

To be able to consume a Web-Service, the JAX-WS artifacts must have been generated with the WS-Import Maven goal described above.

Client code

You can find a typical JAX-WS client code below:

public class SomeClass {
    public void someMethod() {
        // Create the service and retrieve the port 
        Hello helloServicePort = new HelloService().getHelloServicePort();
        
        // Programmatically define the endpoint address
        ((BindingProvider) helloServicePort).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:" + wsPort + "/ws/hello");
        
        // Optionally specify the username and password
        ((BindingProvider) helloServicePort).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "user");
        ((BindingProvider) helloServicePort).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");

        // Call the operation
        helloServicePort.sayHello("World");
    }
}

You can find more advanced client JAX-WS examples in the Web-Services sample.

Publishing

JAX-WS classes

To be able to publish a Web-Service, the JAX-WS artifacts must have been generated with the WS-Import Maven goal described above.

Implementation class

An implementation of the generated Web-Service interface is required:

@WebService(
    endpointInterface = "org.myorganization.myproject.wsdl.seed.hello.HelloService",
    targetNamespace = "http://myproject.myorganization.org/wsdl/seed/hello/",
    serviceName = "HelloService",
    portName = "HelloServicePort"
)
public class HelloServiceImpl implements HelloService {
    @Override
    public String sayHello(String param) {
        return "Hello " + param;
    }
}

Configuration

To publish the Web-Service you must configure its endpoint:

webServices:
  # Configured endpoints with the name of the endpoint as key
  endpoints:
    HelloService:
      # Fully qualified name of the Web-Service implementation class
      implementation: (Class<?>)
      # Classpath location of the WSDL file
      wsdl: (String)
      # URL on which the Web-Service is exposed
      url: (String)
      # The location of the WS external metadata if any
      externalMetadata: (String)
      # The name of the WS to use (if not specified, the @WebService serviceName parameter is used)   
      serviceName: (String)
      # The name of the WS port to use (if not specified, the @WebService portName parameter is used)   
      portName: (String)
      # The binding of the WS
      binding: (##SOAP11_HTTP|##SOAP11_HTTP_MTOM|##SOAP12_HTTP|##SOAP12_HTTP_MTOM|##XML_HTTP)
      # If true, MTOM support is enabled for this endpoint
      enableMtom: (boolean)
      # The attachment size threshold from which MTOM is used
      mtomThreshold: (Integer)
      # The data binding mode of this endpoint
      dataBindingMode: (String)

To dump the webServices configuration options:

mvn -q -Dargs="webServices" seedstack:config
  • In a Web environment, the url attribute must only contain the suffix of the Web-Service such as /ws/hello as the hostname and the port are already determined by the environment.
  • In standalone mode, the full URL must be specified, such as http://myserver.example.org:8080/ws/hello.

JMS transport

This add-on provides an extension to use the JMS transport for Web-Services. To use it, add the following dependency:

<dependency>
    <groupId>org.seedstack.addons.ws</groupId>
    <artifactId>web-services-jms</artifactId>
</dependency>
Show version
dependencies {
    compile("org.seedstack.addons.ws:web-services-jms:3.0.0")
}

To specify a JMS destination, you must use an URI that conforms to the SOAP JMS specification instead of an HTTP URL. There are three main variants of JMS URI.

JNDI lookup

This variant allows to retrieve the connection factory and the destination from JNDI:

jms:jndi:[jndiDestinationName]?jndiConnectionFactoryName=[jndiConnectionFactoryName]

Where:

  • jndiDestinationName is the JNDI name of the JMS destination listened on.
  • jndiConnectionFactoryName is the JNDI name of the Connection Factory.

You can specify additional parameters:

  • jndiInitialContextFactory is the fully qualified name of the JNDI context class used for the lookup.
  • jndiURL is the URL to the JNDI context used for the lookup.
  • replyToName is the JNDI name of the reply destination.

The replyToName can be omitted in which case the implementation will create a temporary queue for the response.

Example:

jms:jndi:dynamicQueues/TEST.QUEUE?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory&jndiConnectionFactoryName=ConnectionFactory&jndiURL=vm://localhost?broker.persistent=false

Queue lookup

This variant allows to directly specify a queue name using a connection factory configured via the SeedStack JMS add-on:

jms:queue:[QUEUE.NAME]?connectionFactoryName=[configuredConnectionFactory]&replyToName=[REPLY.QUEUE.NAME]

Where:

  • QUEUE.NAME is the name of the queue.
  • configuredConnectionFactory is the name of the connection factory configured in the JMS add-on.
  • replyToName is the reply destination name.

The replyToName can be omitted in which case the implementation will create a temporary queue for the response.

Topic lookup

This variant allows to directly specify a queue name using a connection factory configured via the SeedStack JMS add-on:

jms:topic:TOPIC.NAME?connectionFactoryName=[configuredConnectionFactory]&replyToName=[REPLY.QUEUE.NAME]

Where:

  • TOPIC.NAME is the name of the topic.
  • configuredConnectionFactory is the name of the connection factory configured in the JMS add-on.
  • replyToName is the reply destination name.

The replyToName can be omitted in which case the implementation will create a temporary queue for the response (not a temporary topic).