Introduction and architecture
The high level architecture of the JBossWS Web Service Framework is presented in the image here below:
This basically means users can choose to download, install and use three different JBossWS versions:
- JBossWS Native: this is the JBossWS Web Service Framework integrating the original JBossWS native stack that has been developed in the past years. This is what currently comes installed by default in every JBoss Application Server released version and has been used on top of JBoss AS 5 to make it successfully certified for Java EE 5. Please refer the JBossWS Native stack user guide for a complete documentation of JBossWS-Native specific features.
- JBossWS CXF: this is the JBossWS Web Service Framework integrating the Apache CXF web service stack. Please refer the JBossWS CXF stack user guide for a complete documentation of JBossWS-CXF specific features.
- JBossWS Metro: this is the JBossWS Web Service Framework integrating the GlassFish Metro web service stack. Please refer the JBossWS Metro stack user guide for a complete documentation of JBossWS-Metro specific features.
The JBossWS web service framework provides common features, tooling, management, deployment framework, etc. for all the supported stacks. At the same time, each stack comes with its own specific functional feature set, performance characteristics and -of course- community. So users can definitely choose the stack that best suits their needs and successfully use it on top of JBoss Application Server.
Common User Guide
Here below is the documentation that applies to every supported stacks. This includes basic JAX-WS usage as well as references to common additional functionalities the JBossWS Web Service Framework provides on top of the supported stacks.
Web Service Concepts
Document/Literal
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>
Document/Literal (Bare)
Bare is an implementation detail from the Java domain. Neither in the abstract contract (i.e. wsdl+schema) nor at the SOAP message level is a bare endpoint recognizable.
A bare endpoint or client uses a Java bean that represents the entire document payload.
@WebService
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class DocBareServiceImpl
{
@WebMethod
public SubmitBareResponse submitPO(SubmitBareRequest poRequest)
{
...
}
}
The trick is that the Java beans representing the payload contain JAXB annotations that define how the payload is represented on the wire.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "SubmitBareRequest", namespace="http://soapbinding.samples.jaxws.ws.test.jboss.org/", propOrder = { "product" })
@XmlRootElement(namespace="http://soapbinding.samples.jaxws.ws.test.jboss.org/", name = "SubmitPO")
public class SubmitBareRequest
{
@XmlElement(namespace="http://soapbinding.samples.jaxws.ws.test.jboss.org/", required = true)
private String product;
...
}
Document/Literal (Wrapped)
Wrapped is an implementation detail from the Java domain. Neither in the abstract contract (i.e. wsdl+schema) nor at the SOAP message level is a wrapped endpoint recognizable.
A wrapped endpoint or client uses the individual document payload properties. Wrapped is the default and does not have to be declared explicitly.
@WebService
public class DocWrappedServiceImpl
{
@WebMethod
@RequestWrapper (className="org.somepackage.SubmitPO")
@ResponseWrapper (className="org.somepackage.SubmitPOResponse")
public String submitPO(String product, int quantity)
{
...
}
}
Note, that with JBossWS the request/response wrapper annotations are not required, they will be generated on demand using sensible defaults.
RPC/Literal
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:
- The port type operation name defines the endpoint method name
- Message parts are endpoint method parameters
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.
RPC/Encoded
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.
Web Service Endpoints
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.
Plain old Java Object (POJO)
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)
EJB3 Stateless Session Bean (SLSB)
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)
Endpoint Provider
JAX-WS services typically implement a native Java service endpoint interface (SEI), perhaps mapped from a WSDL port type, either directly or via the use of annotations.
Java SEIs provide a high level Java-centric abstraction that hides the details of converting between Java objects and their XML representations for use in XML-based messages. However, in some cases it is desirable for services to be able to operate at the XML message level. The Provider interface offers an alternative to SEIs and may be implemented by services wishing to work at the XML message level.
A Provider based service instance’s invoke method is called for each message received for the service.
@WebServiceProvider(wsdlLocation = "WEB-INF/wsdl/Provider.wsdl")
@ServiceMode(value = Service.Mode.PAYLOAD)
public class ProviderBeanPayload implements Provider<Source>
{
public Source invoke(Source req)
{
// Access the entire request PAYLOAD and return the response PAYLOAD
}
}
Note, Service.Mode.PAYLOAD is the default and does not have to be declared explicitly. You can also use Service.Mode.MESSAGE to access the entire SOAP message (i.e. with MESSAGE the Provider can also see SOAP Headers)
The abstract contract for a provider endpoint cannot be derived/generated automatically. Therefore it is necessary to specify the wsdlLocation with the @WebServiceProvider annotation.
WebServiceContext
The WebServiceContext is treated as an injectable resource that can be set at the time an endpoint is initialized. The WebServiceContext object will then use thread-local information to return the correct information regardless of how many threads are concurrently being used to serve requests addressed to the same endpoint object.
@WebService
public class EndpointJSE
{
@Resource
WebServiceContext wsCtx;
@WebMethod
public String testGetMessageContext()
{
SOAPMessageContext jaxwsContext = (SOAPMessageContext)wsCtx.getMessageContext();
return jaxwsContext != null ? "pass" : "fail";
}
@WebMethod
public String testGetUserPrincipal()
{
Principal principal = wsCtx.getUserPrincipal();
return principal.getName();
}
@WebMethod
public boolean testIsUserInRole(String role)
{
return wsCtx.isUserInRole(role);
}
}
Web Service Clients
Service
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).
Service Usage
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);
Handler Resolver
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.
Executor
Service instances can be configured with a java.util.concurrent.Executor. The executor will then be used to invoke any asynchronous callbacks requested by the application. The setExecutor and getExecutor methods of Service can be used to modify and retrieve the executor configured for a service.
Dynamic Proxy
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);
}
}
WebServiceRef
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:
- To define a reference whose type is a generated service class. In this case, the type and value element will both refer to the generated service class type. Moreover, if the reference type can be inferred by the field/method declaration the annotation is applied to, the type and value elements MAY have the default value (Object.class, that is). If the type cannot be inferred, then at least the type element MUST be present with a non-default value.
- To define a reference whose type is a SEI. In this case, the type element MAY be present with its default value if the type of the reference can be inferred from the annotated field/method declaration, but the value element MUST always be present and refer to a generated service class type (a subtype of javax.xml.ws.Service). The wsdlLocation element, if present, overrides theWSDL location information specified in the WebService annotation of the referenced generated service class.
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
- define the port that should be used to resolve a container-managed port
- define default Stub property settings for Stub objects
- define the URL of a final WSDL document to be used
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>
port-component-ref
<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>
</>
</service-ref>
For details please see service-ref_5_0.dtd in the jboss docs directory.
Dispatch
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)));
Asynchronous Invocations
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);
}
Oneway Invocations
@Oneway indicates that the given web method has only an input message and no output. Typically, a oneway method returns the thread of control to the calling application prior to executing the actual business method.
@WebService (name="PingEndpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class PingEndpointImpl
{
private static String feedback;
@WebMethod
@Oneway
public void ping()
{
log.info("ping");
feedback = "ok";
}
@WebMethod
public String feedback()
{
log.info("feedback");
return feedback;
}
}
Timeout Configuration
There are two properties to configure the http connection timeout and client receive time out:
public void testConfigureTimeout() throws Exception
{
//Set timeout until a connection is established
((BindingProvider) port).getRequestContext().
put("javax.xml.ws.client.connectionTimeout", "6000");
//Set timeout until the response is received
((BindingProvider) port).getRequestContext().
put("javax.xml.ws.client.receiveTimeout", "1000");
port.echo("testTimeout");
}
Common API
This sections describes concepts that apply equally to Web Service Endpoints and Web Service Clients.
Handler Framework
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. For outbound messages, the handlers invocation starts with the first handler in the chain and proceeds in the same order as the handler chain. For inbound messages the processing order is reversed.
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.
Logical Handler
Handlers that only operate on message context properties and message payloads. Logical handlers are protocol agnostic and are unable to affect protocol specific parts of a message. Logical handlers are handlers that implement javax.xml.ws.handler.LogicalHandler.
Protocol Handler
Handlers that operate on message context properties and protocol specific messages. Protocol handlers are specific to a particular protocol and may access and change protocol specific aspects of a message. Protocol handlers are handlers that implement any interface derived from javax.xml.ws.handler.Handler except javax.xml.ws.handler.LogicalHandler.
Service endpoint handlers
On the service endpoint, handlers are defined using the @HandlerChain annotation.
@WebService
@HandlerChain(file = "jaxws-server-source-handlers.xml")
public class SOAPEndpointSourceImpl
{
...
}
The location of the handler chain file supports 2 formats
1. An absolute java.net.URL in externalForm. (ex: http://myhandlers.foo.com/handlerfile1.xml)
2. A relative path from the source file or class file. (ex: bar/handlerfile1.xml)
Service client handlers
On the client side, handler can be configured using the @HandlerChain annotation on the SEI or dynamically using the API.
Service service = Service.create(wsdlURL, serviceName);
Endpoint port = (Endpoint)service.getPort(Endpoint.class);
BindingProvider bindingProvider = (BindingProvider)port;
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(new LogHandler());
handlerChain.add(new AuthorizationHandler());
handlerChain.add(new RoutingHandler());
bindingProvider.getBinding().setHandlerChain(handlerChain); // important!
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 Message Context
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.
SOAP Message Context
SOAP handlers are passed a SOAPMessageContext when invoked. SOAPMessageContext extends MessageContext with methods to obtain and modify the SOAP message payload.
Fault Handling
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
In case of the latter JBossWS generates the required fault wrapper beans at runtime if they are not part of the deployment
JBossWS Extensions
This section describes propriatary JBoss extensions to JAX-WS, that works with all the supported stacks.
Proprietary Annotations
For the set of standard annotations, please have a look at JAX-WS_Annotations.
WebContext
/**
* 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;
}
SecurityDomain
/**
* 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 "";
JAXB Introductions
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.
Tools
The JBossWS Web Service Framework provides unified tooling for all the supported stacks. This currently includes common JAX-WS tools for both contract-first and code-first development and common management tools.
JAX-WS tools
Please refer to JBossWS_JAX-WS_Tools for details. This covers directions on web service contract generation (bottom-up development) and consumption (top-down and client development).
Management tools
JBoss and its web service framework come with some tools allowing WS endpoint management.
Please refer the Endpoint management page for an overview of the available tools. In particular the JBossWS - Records management gives administrators a means of performing custom analysis of their web service traffic as well as exporting communication logs.
Web Service console
All supported stacks provide a web console for getting the list of the endpoints currently deployed on a given host as well as basic metrics regarding invocations to them. The console is available at http://localhost:8080/jbossws/services assuming your application server is currently bound to localhost:8080.
Configuration
Address rewrite
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.
Comments