JBoss.orgCommunity Documentation

Chapter 4. JBossWS-UserGuide

4.1. Common User Guide
4.1.1. Web Service Concepts
4.1.2. Web Service Endpoints
4.1.3. Web Service Clients
4.1.4. Common API
4.1.5. Tools
4.1.6. Configuration

 

Here below is the documentation that applies to all the JBossWS stack versions, hence including JBossWS-CXF. This includes basic JAX-WS usage as well as references to common additional functionalities the JBossWS Web Service Framework provides on top of the CXF stack.

With document style web services two business partners agree on the exchange of complex business documents that are well defined in XML schema. For example, one party sends a document describing a purchase order, the other responds (immediately or later) with a document that describes the status of the purchase order. No need to agree on such low level details as operation names and their associated parameters.

The payload of the SOAP message is an XML document that can be validated against XML schema.

Document is defined by the style attribute on the SOAP binding.

 <binding name='EndpointInterfaceBinding' type='tns:EndpointInterface'>
  <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/>
  <operation name='concat'>
   <soap:operation soapAction=''/>
   <input>
    <soap:body use='literal'/>
   </input>
   <output>
    <soap:body use='literal'/>
   </output>
  </operation></binding>

With document style web services the payload of every message is defined by a complex type in XML schema.

   <complexType name='concatType'>
    <sequence>
     <element name='String_1' nillable='true' type='string'/>
     <element name='long_1' type='long'/>
    </sequence>
   </complexType>
   <element name='concat' type='tns:concatType'/>

Therefore, message parts must refer to an element from the schema.

 <message name='EndpointInterface_concat'>
  <part name='parameters' element='tns:concat'/></message>

The following message definition is invalid.

 <message name='EndpointInterface_concat'>
  <part name='parameters' type='tns:concatType'/></message>

With RPC there is a wrapper element that names the endpoint operation. Child elements of the RPC parent are the individual parameters.

The SOAP body is constructed based on some simple rules:

RPC is defined by the style attribute on the SOAP binding.

 <binding name='EndpointInterfaceBinding' type='tns:EndpointInterface'>
  <soap:binding style='rpc' transport='http://schemas.xmlsoap.org/soap/http'/>
  <operation name='echo'>
   <soap:operation soapAction=''/>
   <input>
    <soap:body namespace='http://org.jboss.ws/samples/jsr181pojo' use='literal'/>
   </input>
   <output>
    <soap:body namespace='http://org.jboss.ws/samples/jsr181pojo' use='literal'/>
   </output>
  </operation></binding>

With rpc style web services the portType names the operation (i.e. the java method on the endpoint)

 <portType name='EndpointInterface'>
  <operation name='echo' parameterOrder='String_1'>
   <input message='tns:EndpointInterface_echo'/>
   <output message='tns:EndpointInterface_echoResponse'/>
  </operation></portType>

Operation parameters are defined by individual message parts.

 <message name='EndpointInterface_echo'>
  <part name='String_1' type='xsd:string'/></message><message name='EndpointInterface_echoResponse'>
  <part name='result' type='xsd:string'/></message>

Note, there is no complex type in XML schema that could validate the entire SOAP message payload.

@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class JSEBean01
{
   @WebMethod
   @WebResult(name="result")
   public String echo(@WebParam(name="String_1") String input)
   {
      ...
   }
}

The element names of RPC parameters/return values may be defined using the JAX-WS WebParam and WebResult annotations respectively.

SOAP encodeding style is defined by the infamous chapter 5 of the SOAP-1.1 specification. It has inherent interoperability issues that cannot be fixed. The Basic Profile-1.0 prohibits this encoding style in 4.1.7 SOAP encodingStyle Attribute.

JBossWS doesn't support rpc/encoded anymore.

 

JAX-WS simplifies the development model for a web service endpoint a great deal. In short, an endpoint implementation bean is annotated with JAX-WS annotations and deployed to the server. The server automatically generates and publishes the abstract contract (i.e. wsdl+schema) for client consumption. All marshalling/unmarshalling is delegated to JAXB.

 

Let's take a look at simple POJO endpoint implementation. All endpoint associated metadata is provided via JSR-181 annotations

    @WebService
    @SOAPBinding(style = SOAPBinding.Style.RPC)
    public class JSEBean01
    {
       @WebMethod
       public String echo(String input)
       {
          ...
       }
    }

The endpoint as a web application

A JAX-WS java service endpoint (JSE) is deployed as a web application.

  <web-app ...>
    <servlet>
      <servlet-name>TestService</servlet-name>
      <servlet-class>org.jboss.test.ws.jaxws.samples.jsr181pojo.JSEBean01</servlet-class>
    </servlet>
    <servlet-mapping>
      <servlet-name>TestService</servlet-name>
      <url-pattern>/*</url-pattern>
    </servlet-mapping>
  </web-app>

Packaging the endpoint

A JSR-181 java service endpoint (JSE) is packaged as a web application in a *.war file.

    <war warfile="${build.dir}/libs/jbossws-samples-jsr181pojo.war" webxml="${build.resources.dir}/samples/jsr181pojo/WEB-INF/web.xml">
      <classes dir="${build.dir}/classes">
        <include name="org/jboss/test/ws/samples/jsr181pojo/JSEBean01.class"/>
      </classes>
    </war>

Note, only the endpoint implementation bean and web.xml are required.

Accessing the generated WSDL

A successfully deployed service endpoint will show up in the service endpoint manager. This is also where you find the links to the generated wsdl.

   http://yourhost:8080/jbossws/services

Note, it is also possible to generate the abstract contract off line using jbossw tools. For details of that please see Bottom-Up (Java to WSDL)

 

The JAX-WS programming model support the same set of annotations on EJB3 stateless session beans as on Plain old Java Object (POJO) endpoints.  EJB-2.1 endpoints are supported using the JAX-RPC progamming model (with JBossWS-Native only).

    @Stateless
    @Remote(EJB3RemoteInterface.class)
    @RemoteBinding(jndiBinding = "/ejb3/EJB3EndpointInterface")
 
    @WebService
    @SOAPBinding(style = SOAPBinding.Style.RPC)
    public class EJB3Bean01 implements EJB3RemoteInterface
    {
       @WebMethod
       public String echo(String input)
       {
          ...
       }
    }

Above you see an EJB-3.0 stateless session bean that exposes one method both on the remote interface and on and as an endpoint operation.

Packaging the endpoint

A JSR-181 EJB service endpoint is packaged as an ordinary ejb deployment.

    <jar jarfile="${build.dir}/libs/jbossws-samples-jsr181ejb.jar">
      <fileset dir="${build.dir}/classes">
        <include name="org/jboss/test/ws/samples/jsr181ejb/EJB3Bean01.class"/>
        <include name="org/jboss/test/ws/samples/jsr181ejb/EJB3RemoteInterface.class"/>
      </fileset>
    </jar>

Accessing the generated WSDL

A successfully deployed service endpoint will show up in the service endpoint manager. This is also where you find the links to the generated wsdl.

   http://yourhost:8080/jbossws/services

Note, it is also possible to generate the abstract contract off line using jbossw tools. For details of that please see Bottom-Up (Java to WSDL)

 

Service is an abstraction that represents a WSDL service. A WSDL service is a collection of related ports, each of which consists of a port type bound to a particular protocol and available at a particular endpoint address.

For most clients, you will start with a set of stubs generated from the WSDL. One of these will be the service, and you will create objects of that class in order to work with the service (see "static case" below).

Static case

Most clients will start with a WSDL file, and generate some stubs using jbossws tools like wsconsume.  This usually gives a mass of files, one of which is the top of the tree.  This is the service implementation class.

The generated implementation class can be recognised as it will have two public constructors, one with no arguments and one with two arguments, representing the wsdl location (a java.net.URL) and the service name (a javax.xml.namespace.QName) respectively.

Usually you will use the no-argument constructor. In this case the WSDL location and service name are those found in the WSDL. These are set implicitly from the WebServiceClient annotation that decorates the generated class.

The following code snippet shows the generated constructors from the generated class:

// Generated Service Class
 
@WebServiceClient(name="StockQuoteService", targetNamespace="http://example.com/stocks", wsdlLocation="http://example.com/stocks.wsdl")
public class StockQuoteService extends javax.xml.ws.Service 
{
   public StockQuoteService() 
   {
      super(new URL("http://example.com/stocks.wsdl"), new QName("http://example.com/stocks", "StockQuoteService"));
   }
 
   public StockQuoteService(String wsdlLocation, QName serviceName) 
   {
      super(wsdlLocation, serviceName);
   }
 
   ...
}

Section Dynamic Proxy explains how to obtain a port from the service and how to invoke an operation on the port. If you need to work with the XML payload directly or with the XML representation of the entire SOAP message, have a look at Dispatch.

Dynamic case

In the dynamic case, when nothing is generated, a web service client uses Service.create to create Service instances, the following code illustrates this process.

   URL wsdlLocation = new URL("http://example.org/my.wsdl");
   QName serviceName = new QName("http://example.org/sample", "MyService");
   Service service = Service.create(wsdlLocation, serviceName);

 

 

JAX-WS provides a flexible plug-in framework for message processing modules, known as handlers, that may be used to extend the capabilities of a JAX-WS runtime system. Handler Framework describes the handler framework in detail. A Service instance provides access to a HandlerResolver via a pair of getHandlerResolver/setHandlerResolver methods that may be used to configure a set of handlers on a per-service, per-port or per-protocol binding basis.

When a Service instance is used to create a proxy or a Dispatch instance then the handler resolver currently registered with the service is used to create the required handler chain. Subsequent changes to the handler resolver configured for a Service instance do not affect the handlers on previously created proxies, or Dispatch instances.

You can create an instance of a client proxy using one of getPort methods on the Service.

   /** 
    * The getPort method returns a proxy. A service client
    * uses this proxy to invoke operations on the target
    * service endpoint. The <code>serviceEndpointInterface</code>
    * specifies the service endpoint interface that is supported by
    * the created dynamic proxy instance.
    **/
   public <T> T getPort(QName portName, Class<T> serviceEndpointInterface)
   {
      ...
   }
 
   /** 
    * The getPort method returns a proxy. The parameter
    * <code>serviceEndpointInterface</code> specifies the service
    * endpoint interface that is supported by the returned proxy.
    * In the implementation of this method, the JAX-WS
    * runtime system takes the responsibility of selecting a protocol
    * binding (and a port) and configuring the proxy accordingly.
    * The returned proxy should not be reconfigured by the client.
    *
    **/
   public <T> T getPort(Class<T> serviceEndpointInterface)
   {
      ...
   }

The service endpoint interface (SEI) is usually generated using tools. For details see Top Down (WSDL to Java)

A generated static Service usually also offers typed methods to get ports. These methods also return dynamic proxies that implement the SEI.

@WebServiceClient(name = "TestEndpointService", targetNamespace = "http://org.jboss.ws/wsref", 
   wsdlLocation = "http://localhost.localdomain:8080/jaxws-samples-webserviceref?wsdl")
 
public class TestEndpointService extends Service
{
    ...
 
    public TestEndpointService(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }
 
    @WebEndpoint(name = "TestEndpointPort")
    public TestEndpoint getTestEndpointPort() 
    {
        return (TestEndpoint)super.getPort(TESTENDPOINTPORT, TestEndpoint.class);
    }
}

 

The WebServiceRef annotation is used to declare a reference to a Web service. It follows the resource pattern exemplified by the javax.annotation.Resource annotation in JSR-250.

There are two uses to the WebServiceRef annotation:

public class EJB3Client implements EJB3Remote
{
   @WebServiceRef
   public TestEndpointService service4;
 
   @WebServiceRef
   public TestEndpoint port3;

WebServiceRef Customization

Starting from jboss-5.0.x we offer a number of overrides and extensions to the WebServiceRef annotation. These include

Example:

  <service-ref>
   <service-ref-name>OrganizationService</service-ref-name>
   <wsdl-override>file:/wsdlRepository/organization-service.wsdl</wsdl-override>
  </service-ref>

  <service-ref>
   <service-ref-name>OrganizationService</service-ref-name>
   <config-name>Secure Client Config</config-name>
   <config-file>META-INF/jbossws-client-config.xml</config-file>
   <handler-chain>META-INF/jbossws-client-handlers.xml</handler-chain>
  </service-ref>
  
  <service-ref>
   <service-ref-name>SecureService</service-ref-name>
   <service-impl-class>org.jboss.tests.ws.jaxws.webserviceref.SecureEndpointService</service-impl-class>
   <service-qname>{http://org.jboss.ws/wsref}SecureEndpointService</service-qname>
    <port-component-ref>
     <service-endpoint-interface>org.jboss.tests.ws.jaxws.webserviceref.SecureEndpoint</service-endpoint-interface>
     <port-qname>{http://org.jboss.ws/wsref}SecureEndpointPort</port-qname>
     <stub-property>
      <prop-name>javax.xml.ws.security.auth.username</prop-name>
      <prop-value>kermit</prop-value>
     </stub-property>
     <stub-property>
      <prop-name>javax.xml.ws.security.auth.password</prop-name>
      <prop-value>thefrog</prop-value>
     </stub-property>
   </port-component-ref>
  </service-ref>

For details please see service-ref_5_0.dtd in the jboss docs directory.

 

XMLWeb Services use XML messages for communication between services and service clients. The higher level JAX-WS APIs are designed to hide the details of converting between Java method invocations and the corresponding XML messages, but in some cases operating at the XML message level is desirable. The Dispatch interface provides support for this mode of interaction.

Dispatch supports two usage modes, identified by the constants javax.xml.ws.Service.Mode.MESSAGE and javax.xml.ws.Service.Mode.PAYLOAD respectively:

Message In this mode, client applications work directly with protocol-specific message structures. E.g., when used with a SOAP protocol binding, a client application would work directly with a SOAP message.

Message Payload In this mode, client applications work with the payload of messages rather than the messages themselves. E.g., when used with a SOAP protocol binding, a client application would work with the contents of the SOAP Body rather than the SOAP message as a whole.

Dispatch is a low level API that requires clients to construct messages or message payloads as XML and requires an intimate knowledge of the desired message or payload structure. Dispatch is a generic class that supports input and output of messages or message payloads of any type.

      Service service = Service.create(wsdlURL, serviceName);
      Dispatch dispatch = service.createDispatch(portName, StreamSource.class, Mode.PAYLOAD);
 
      String payload = "<ns1:ping xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
      dispatch.invokeOneWay(new StreamSource(new StringReader(payload)));
 
      payload = "<ns1:feedback xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>";
      Source retObj = (Source)dispatch.invoke(new StreamSource(new StringReader(payload)));

The BindingProvider interface represents a component that provides a protocol binding for use by clients, it is implemented by proxies and is extended by the Dispatch interface.

BindingProvider instances may provide asynchronous operation capabilities. When used, asynchronous operation invocations are decoupled from the BindingProvider instance at invocation time such that the response context is not updated when the operation completes. Instead a separate response context is made available using the Response interface.

   public void testInvokeAsync() throws Exception
   {
      URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-samples-asynchronous?wsdl");
      QName serviceName = new QName(targetNS, "TestEndpointService");
      Service service = Service.create(wsdlURL, serviceName);
      TestEndpoint port = service.getPort(TestEndpoint.class);
 
      Response response = port.echoAsync("Async");
 
      // access future
      String retStr = (String) response.get();
      assertEquals("Async", retStr);
   }

This sections describes concepts that apply equally to Web Service Endpoints and Web Service Clients.

The handler framework is implemented by a JAX-WS protocol binding in both client and server side runtimes. Proxies, and Dispatch instances, known collectively as binding providers, each use protocol bindings to bind their abstract functionality to specific protocols.

Client and server-side handlers are organized into an ordered list known as a handler chain. The handlers within a handler chain are invoked each time a message is sent or received. Inbound messages are processed by handlers prior to binding provider processing. Outbound messages are processed by handlers after any binding provider processing.

Handlers are invoked with a message context that provides methods to access and modify inbound and outbound messages and to manage a set of properties. Message context properties may be used to facilitate communication between individual handlers and between handlers and client and service implementations. Different types of handlers are invoked with different types of message context.

MessageContext is the super interface for all JAX-WS message contexts. It extends Map<String,Object> with additional methods and constants to manage a set of properties that enable handlers in a handler chain to share processing related state. For example, a handler may use the put method to insert a property in the message context that one or more other handlers in the handler chain may subsequently obtain via the get method.

Properties are scoped as either APPLICATION or HANDLER. All properties are available to all handlers for an instance of an MEP on a particular endpoint. E.g., if a logical handler puts a property in the message context, that property will also be available to any protocol handlers in the chain during the execution of an MEP instance. APPLICATION scoped properties are also made available to client applications (see section 4.2.1) and service endpoint implementations. The defaultscope for a property is HANDLER.

Logical Handlers are passed a message context of type LogicalMessageContext when invoked. LogicalMessageContext extends MessageContext with methods to obtain and modify the message payload, it does not provide access to the protocol specific aspects of amessage. A protocol binding defines what component of a message are available via a logical message context. The SOAP binding defines that a logical handler deployed in a SOAP binding can access the contents of the SOAP body but not the SOAP headers whereas the XML/HTTP binding defines that a logical handler can access the entire XML payload of a message.

An implementation may thow a SOAPFaultException

   public void throwSoapFaultException()
   {
      SOAPFactory factory = SOAPFactory.newInstance();
      SOAPFault fault = factory.createFault("this is a fault string!", new QName("http://foo", "FooCode"));
      fault.setFaultActor("mr.actor");
      fault.addDetail().addChildElement("test");
      throw new SOAPFaultException(fault);
   }

or an application specific user exception

   public void throwApplicationException() throws UserException
   {
      throw new UserException("validation", 123, "Some validation error");
   }

Note

Note

In case of the latter JBossWS generates the required fault wrapper beans at runtime if they are not part of the deployment

 

This section describes propriatary JBoss extensions to JAX-WS, that works with all the supported stacks.

 

For the set of standard annotations, please have a look at JAX-WS_Annotations.

 

/**
 * Provides web context specific meta data to EJB based web service endpoints.
 *
 * @author thomas.diesler@jboss.org
 * @since 26-Apr-2005
 */
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE })
public @interface WebContext {
 
   /** 
    * The contextRoot element specifies the context root that the web service endpoint is deployed to.
    * If it is not specified it will be derived from the deployment short name.
    * 
    * Applies to server side port components only. 
    */
   String contextRoot() default "";
   
   /** 
    * The virtual hosts that the web service endpoint is deployed to.
    * 
    * Applies to server side port components only.
    */
   String[] virtualHosts() default {};
   
   /** 
    * Relative path that is appended to the contextRoot to form fully qualified
    * endpoint address for the web service endpoint.
    * 
    * Applies to server side port components only. 
    */
   String urlPattern() default "";
 
   /**
    * The authMethod is used to configure the authentication mechanism for the web service. 
    * As a prerequisite to gaining access to any web service which are protected by an authorization
    * constraint, a user must have authenticated using the configured mechanism.
    *
    * Legal values for this element are "BASIC", or "CLIENT-CERT".
    */
   String authMethod() default "";
 
   /**
    * The transportGuarantee specifies that the communication
    * between client and server should be NONE, INTEGRAL, or
    * CONFIDENTIAL. NONE means that the application does not require any
    * transport guarantees. A value of INTEGRAL means that the application
    * requires that the data sent between the client and server be sent in
    * such a way that it can't be changed in transit. CONFIDENTIAL means
    * that the application requires that the data be transmitted in a
    * fashion that prevents other entities from observing the contents of
    * the transmission. In most cases, the presence of the INTEGRAL or
    * CONFIDENTIAL flag will indicate that the use of SSL is required.
    */
   String transportGuarantee() default "";
 
   /**
    * A secure endpoint does not secure wsdl access by default.
    * Explicitly setting secureWSDLAccess overrides this behaviour.
    * 
    * Protect access to WSDL. See http://jira.jboss.org/jira/browse/JBWS-723   
    */
   boolean secureWSDLAccess() default false;
}
/**
 * Annotation for specifying the JBoss security domain for an EJB
 * 
 * @author <a href="mailto:bill@jboss.org">Bill Burke</a>
 **/
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME)
public @interface SecurityDomain
{
   /**
    * The required name for the security domain.
    * 
    * Do not use the JNDI name
    * 
    *    Good: "MyDomain"
    *    Bad:  "java:/jaas/MyDomain"
    */
   String value();
   
   /**
    * The name for the unauthenticated pricipal
    */
   String unauthenticatedPrincipal() default "";

As Kohsuke Kawaguchi writes on his blog, one common complaint from the JAXB users is the lack of support for binding 3rd party classes. The scenario is this you are trying to annotate your classes with JAXB annotations to make it XML bindable, but some of the classes are coming from libraries and JDK, and thus you cannot put necessary JAXB annotations on it.

To solve this JAXB has been designed to provide hooks for programmatic introduction of annotations to the runtime.

This is currently leveraged by the JBoss JAXB Introductions project, using which users can define annotations in XML and make JAXB see those as if those were in the class files (perhaps coming from 3rd party libraries).

 

JAXB Introductions are currently supported in JBossWS-Native (server side only, since 3.0.2.GA) and JBossWS-CXF (both server and client side, since 3.2.1.GA).

Take a look at the JAXB Introductions page on the wiki and at the examples in the sources.

 

JBossWS allows users to configure the soap:address attribute in the wsdl contract of deployed services as well as wsdl address in the web service console. [due to a known issue this does not currently work with JBossWS-Metro, see: JBWS-2462]

 

Server configuration options

 

There're few attributes in the jbossws deployers configuration (currently in jbossws.deployer/META-INF/stack-agnostic-jboss-beans.xml) controlling the way the soap:address attribute in the wsdl is rewritten.

<bean name="WSServerConfig" class="org.jboss.webservices.integration.config.ServerConfigImpl">
    <property name="mbeanServer"><inject bean="WSMBeanServerLocator" property="mbeanServer"/></property>

    <property name="webServiceHost">${jboss.bind.address}</property>
    <property name="modifySOAPAddress">true</property>

    <!--
      <property name="webServiceSecurePort">8443</property>
      <property name="webServicePort">8080</property>
    -->
  </bean>

 

If the content of <soap:address> in the wsdl is a valid URL, JBossWS will not rewrite it unless modifySOAPAddress is true. If the content of <soap:address> is not a valid URL instead, JBossWS will always rewrite it using the attribute values given below. Please note that the variable ${jboss.bind.address} can be used to set the address which the application is bound to at each startup.

 

The webServiceSecurePort and webServicePort attributes are used to explicitly define the ports to be used for rewriting the SOAP address. If these attributes are not set, the ports will be identified by querying the list of installed connectors. If multiple connectors are found the port of the first connector is used.

 

Dynamic rewrite

 

When the application server is bound to multiple addresses or non-trivial real-world network architectures cause request for different external addresses to hit the same endpoint, a static rewrite of the soap:address may not be enough. JBossWS allows for both the soap:address in the wsdl and the wsdl address in the console to be rewritten with the host use in the client request. This way, users always get the right wsdl address assuming they're connecting to an instance having the endpoint they're looking for. To trigger this behaviour, the jbossws.undefined.host value has to be specified for the webServiceHost attribute.

<property name="webServiceHost">jbossws.undefined.host</property>
<property name="modifySOAPAddress">true</property>

 

Of course, when a confidential transport address is required, the addresses are always rewritten using https protocol and the port currently configured for the https/ssl connector.