Web Services Guide
Web Services Guide
Web Services Guide
0 WebServices Guide
iii
JBoss AS 6.0 WebServices Guide
iv
13.4.3. Multiple handlers ........................................................................ 103
13.5. Future extensions .................................................................................. 103
13.5.1. Database recorder ...................................................................... 103
13.5.2. Custom log writer ....................................................................... 103
13.6. References ........................................................................................... 104
IV. Samples & Tutorials ................................................................................................. 105
14. JBossWS-CXFWS-Addressingtutorial ............................................................ 107
14.1. The Service .......................................................................................... 107
14.2. Generating WSDL and JAX-WS Endpoint Artifacts .................................. 108
14.3. Writing Regular JAX-WS Client .............................................................. 110
14.4. Turning on WS-Addressing 1.0 .............................................................. 111
14.4.1. Updating Endpoint Code to Configure WS-Addressing ................... 111
14.4.2. Updating Client Code to Configure WS-Addressing ....................... 111
14.4.3. Leveraging WS-Addressing Policy ............................................... 112
14.5. Sample Sources .................................................................................... 113
15. JBossWS-CXFWS-ReliableMessagingtutorial ................................................. 115
15.1. The service ........................................................................................... 115
15.2.
Generating WSDL and JAX-WS Endpoint Artifacts .................................. 116
15.3.
Generating JAX-WS Client Artifacts ........................................................ 118
15.4.
Writing Regular JAX-WS Client .............................................................. 119
15.5.
Turning on WS-RM 1.0 .......................................................................... 120
15.5.1. Extending WSDL Using WS-Policy .............................................. 120
15.5.2. Basic WS-RM configuration ......................................................... 122
15.5.3. Advanced WS-RM configuration .................................................. 122
15.6. Sample Sources .................................................................................... 124
16. JBossWS-CXFJMStransporttutorial ................................................................ 125
16.1. WSDL ................................................................................................... 125
16.2. Service Implementation .......................................................................... 127
16.3. web.xml ................................................................................................ 128
16.4. jbossws-cxf.xml ..................................................................................... 129
17. JBossWS-JAX-WSAnnotations ....................................................................... 131
17.1. JAX-WS Annotations ............................................................................. 131
17.1.1. javax.xml.ws.ServiceMode ........................................................... 131
17.1.2. javax.xml.ws.WebFault ................................................................ 131
17.1.3. javax.xml.ws.RequestWrapper ..................................................... 131
17.1.4. javax.xml.ws.ResponseWrapper .................................................. 131
17.1.5. javax.xml.ws.WebServiceClient .................................................... 132
17.1.6. javax.xml.ws.WebEndpoint .......................................................... 132
17.1.7. javax.xml.ws.WebServiceProvider ................................................ 132
17.1.8. javax.xml.ws.BindingType ............................................................ 132
17.1.9. javax.xml.ws.WebServiceRef ....................................................... 132
17.1.10. javax.xml.ws.WebServiceRefs .................................................... 133
17.1.11. javax.xml.ws.Action ................................................................... 133
17.1.12. javax.xml.ws.FaultAction ............................................................ 133
v
JBoss AS 6.0 WebServices Guide
vi
Part I. WebServices Overview
Chapter 1.
JBossWS-WebServices
The Internet features a lot of pages about web services. They describe what web services are,
how they work, which kind of technology is most suitable for their development and so on. This
page's aim is not to provide another web service definition. We will instead highlight some key
concepts about Web services and what they're useful for right now.
Technical details will be later explained in the documentation. What comes out is that web services
provide a standard means of interoperating between different software applications. Each of these
applications may run on a variety of platforms and/or frameworks providing a set of functionalities.
The main concern is about interoperability between services.
• A service provider publishes a service contract that exposes the public functions (operations)
it is able to perform and thus service consumers can use.
• Both service providers and service consumers features concrete softwares that send and
receive messages according to the informations contained in the service contract they agreed
before the communication.
• Basic Web services specifications define the standard way of publishing a service contract and
communicating.
• Web services stacks (like JBossWS) conform to these specifications providing software layers
to developers who want to either implement a service provider or service consumer. This way
they almost only need to develop their own business logic in their preferred way, without dealing
with the low-level details of message exchanges and so on.
3
Chapter 1. JBossWS-WebServices
Enterprise system may benefit from web service technologies also for internal heterogenous
subsystems communication. As a matter of fact their interoperability boosts service reuse and
composition. No more need to rewrite whole functionalities only because they were developed by
another enterprise department using another software language.
Of course SOA is an architectural model agnostic to technology platforms and every enterprise
can pursue the strategic goals associated with service-oriented computing using different
technologies. However in the current marketplace, Web Services are probably the technology
platform that better suits SOA principles and are most used to get to this architecture.
Nowadays they are meant to be used for loosely-coupled coarse-grained communication, for
message (document) exchange. Moreover during the last years a lot of specifications (WS-
* [http://community.jboss.org/docs/DOC-13554#Future_of_Web_Services]) were discussed and
finally approved to standardize ws-related advanced aspects including reliable messaging,
message-level security, cross-service transactions, etc. Finally web service specifications also
4
What web services are not...
include notion of registries to collect service contract references, to easily discover service
implementations, etc.
This all means that the web services technology platform suits complex enterprise communication
and is not simply the latest way of doing remote procedure calls.
5
6
Chapter 2.
JBossWS-
Fromconceptstotechnology
This pages is meant to be something like a bridge from the very high level web service concepts
highlighted here and the most important specifications the web service technology platform is
based on.
Web service stacks like JBossWS usually have tools to both generate and consume technical
contracts. This helps ensuring also from a practical point of view that owners of service producer
(server) and consumer (client) only need contracts to establish the communication.
As previously said, tools allow developers to automatically generate WSDL contract files given
their service implementation. Advantages and disadvantage of this delivery process include:
7
Chapter 2. JBossWS-Fromconcep...
• Developers do not have to deal with contracts by hand thus deep knowledge of WSDL and
XML is not required.
• Less effort and time required for services to be developed and go live to production environment.
Developers may write contracts first instead. This usually implies an initial collaboration of
architects and business analysts to define a conceptual service design together.
• Services with contracts obtained this way may easily cooperate in a service oriented architecture
• More effort and time required for web service project start-up
• Contracts tend to have longer lifespans and usually require less maintenance.
Messages' content is described in the wsdl contract. The WSDL file also states the transport
protocol to be used for the transmission; the most common one is of course HTTP, however JMS,
SMTP and other ones are allowed.
2.3. Registries
TODO
8
References
However a real added value to the web service platform is coming from a lot of
recent additional specifications. These cover features that are really relevant to deliver
mission critical enterprise services. For example some of the most important agreements
major vendors came to are those on security (WS-Security [http://www.oasis-open.org/
committees/tc_home.php?wg_abbrev=wss]) and reliable messaging (WS-Reliable Messaging
[http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=ws-rx]).
Unfortunately the web service platform is still being defined and many other specifications have
not been implemented by all vendors yet. It is nevertheless important to know from a web service
beginner point of view that many advanced features are actually supported and thus make possible
to cope with many real world enterprise level issues. Moreover the platform is being continuously
enriched and standardized.
2.5. References
Further knowledge is of course required to better understand the web service technology platform.
This however goes beyond the aim of this web service introduction. The highlighted concepts and
references above should nevertheless allow developers with no previous exposure to web service
technology to go through the core of JBossWS documentation [http://community.jboss.org/docs/
DOC-13504].
A rich list of specifications and articles can be found here and should be used to acquire deeper
knowledge. Moreover the whole documentation refers to authoritative third-party documentation
and official specifications whenever required.
9
10
Part II. Main Documentation
JBoss Application Server 6.0 comes with JBossWS-CXF already installed. JBossWS-CXF is
basically the JBoss Web Service integration with Apache CXF stack. This way additional JBoss
features and customizations are added on top of already existing Apache CXF functionalities.
In particular the integration provides technologies for allowing the application server to support
JavaEE requirements in terms of Web Services functionalities.
Below you find the essential documentation on JBossWS - CXF coming with JBoss AS 6. That
covers a quick start, a full user guide and tooling.
Chapter 3.
JBossWS-QuickStart
In the following sections we will explore the samples that ship with the JBossWS distribution. They
provide a build structure based on Ant to get you started quickly.
If you are in charge to provide the service implementation, then you are probably going to start with
the implementation and derive the abstract contract from it. You are probably not even getting in
touch with the WSDL unless you hand it to 3rd party clients. For this reason we are going to look at
a service implementation that leverages JSR-181 annotations [http://jcp.org/en/jsr/detail?id=181].
Note
Note
Even though detailed knowledge of web service meta data is not required, it will
definitely help if you make yourself familiar with it. For further information see
When starting from Java you must provide the service implementation. A valid endpoint
implementation class must meet the following requirements:
• All method parameters and return types must be compatible with the JAXB 2.0
13
Chapter 3. JBossWS-QuickStart
Let's look at a sample EJB3 component that is going to be exposed as a web service. (This is
based on the Retail example).
Don't be confused with the EJB3 annotation @Stateless. We concentrate on the @WebService
annotation for now.
package org.jboss.test.ws.jaxws.samples.retail.profile;
import javax.ejb.Stateless;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
@Stateless (1)
@WebService( (2)
name="ProfileMgmt",
targetNamespace = "http://org.jboss.ws/samples/retail/profile",
serviceName = "ProfileMgmtService")
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) (3)
public class ProfileMgmtBean {
@WebMethod (4)
public DiscountResponse getCustomerDiscount(DiscountRequest request) {
return new DiscountResponse(request.getCustomer(), 10.00);
}
}
The method parameters and return values are going to represent our XML payload and
thus require being compatible with JAXB2 [http://java.sun.com/webservices/jaxb/]. Actually you
wouldn't need any JAXB annotations for this particular example, because JAXB relies on
meaningful defaults. For the sake of documentation we put the more important ones here.
package org.jboss.test.ws.jaxws.samples.retail.profile;
import javax.xml.bind.annotation.XmlAccessType;
14
Deploying service implementations
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;
import org.jboss.test.ws.jaxws.samples.retail.Customer;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType( (1)
name = "discountRequest",
namespace="http://org.jboss.ws/samples/retail/profile",
propOrder = { "customer" }
)
public class DiscountRequest {
public DiscountRequest() {
}
1. In this case we use @XmlType to specify an XML complex type name and override the
namespace.
EJB3 services
15
Chapter 3. JBossWS-QuickStart
Simply wrap up the service implementation class, the endpoint interface and any custom data
types in a JAR and drop them in the deploy directory. No additional deployment descriptors
required. Any meta data required for the deployment of the actual web service is taken from the
annotations provided on the implementation class and the service endpoint interface. JBossWS
will intercept that EJB3 deployment (the bean will also be there) and create an HTTP endpoint
at deploy-time:
org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.class
org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.class
org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.class
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.class
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtBean.class
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.class
org/jboss/test/ws/jaxws/samples/retail/profile/package-info.class
Note
Note
If the deployment was successful you should be able to see your endpoint at http:/
/localhost:8080/jbossws/services
Using wsconsume
The wsconsume tool is used to consume the abstract contract (WSDL) and produce annotated
Java classes (and optionally sources) that define it. We are going to start with the WSDL from
16
Consuming web services
our retail example (ProfileMgmtService.wsdl). For a detailed tool reference you need to consult
the user guide.
options:
-h, --help Show this help message
-b, --binding=<file> One or more JAX-WS or JAXB binding files
-k, --keep Keep/Generate Java source
-c --catalog=<file> Oasis XML Catalog file for entity resolution
-p --package=<name> The target package for generated source
-w --wsdlLocation=<loc> Value to use for @WebService.wsdlLocation
-o, --output=<directory> The directory to put generated artifacts
-s, --source=<directory> The directory to put Java source
-q, --quiet Be somewhat more quiet
-t, --show-traces Show full exception stack traces
~./wsconsume.sh -k
-p org.jboss.test.ws.jaxws.samples.retail.profile ProfileMgmtService.wsdl
(1)
org/jboss/test/ws/jaxws/samples/retail/profile/Customer.java
org/jboss/test/ws/jaxws/samples/retail/profile/DiscountRequest.java
org/jboss/test/ws/jaxws/samples/retail/profile/DiscountResponse.java
org/jboss/test/ws/jaxws/samples/retail/profile/ObjectFactory.java
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmt.java
org/jboss/test/ws/jaxws/samples/retail/profile/ProfileMgmtService.java
org/jboss/test/ws/jaxws/samples/retail/profile/package-info.java
1. As you can see we did use the -p switch to specify the package name of the generated sources.
File Purpose
ProfileMgmt.java Service Endpoint Interface
Customer.java Custom data type
Discount*.java Custom data type
ObjectFactory.java JAXB XML Registry
17
Chapter 3. JBossWS-QuickStart
File Purpose
package-info.java Holder for JAXB package annotations
ProfileMgmtService.java Service factory
Basically wsconsume generates all custom data types (JAXB annotated classes), the service
endpoint interface and a service factory class. We will look at how these artifacts can be used the
build web service client implementations in the next section.
import javax.xml.ws.Service;
1. Create a service factory using the WSDL location and the service name
2. Use the tool created service endpoint interface to build the service stub
Note
Note
The creation of the service stub is quite costly. You should take care that it
gets reused by your application code (However it's not thread safe). Within a
EE5 environment you might want to investigate the @WebServiceRef functionality.
18
Appendix
3.4. Appendix
3.4.1. ProfileMgmtService.wsdl
<definitions
name='ProfileMgmtService'
targetNamespace='http://org.jboss.ws/samples/retail/profile'
xmlns='http://schemas.xmlsoap.org/wsdl/'
xmlns:ns1='http://org.jboss.ws/samples/retail'
xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
xmlns:tns='http://org.jboss.ws/samples/retail/profile'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<types>
<xs:schema targetNamespace='http://org.jboss.ws/samples/retail'
version='1.0' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<xs:complexType name='customer'>
<xs:sequence>
<xs:element minOccurs='0' name='creditCardDetails'
type='xs:string'/>
<xs:element minOccurs='0' name='firstName' type='xs:string'/>
<xs:element minOccurs='0' name='lastName' type='xs:string'/>
</xs:sequence>
</xs:complexType>
</xs:schema>
<xs:schema
targetNamespace='http://org.jboss.ws/samples/retail/profile'
version='1.0'
xmlns:ns1='http://org.jboss.ws/samples/retail'
xmlns:tns='http://org.jboss.ws/samples/retail/profile'
xmlns:xs='http://www.w3.org/2001/XMLSchema'>
<xs:import namespace='http://org.jboss.ws/samples/retail'/>
<xs:element name='getCustomerDiscount'
nillable='true' type='tns:discountRequest'/>
<xs:element name='getCustomerDiscountResponse'
nillable='true' type='tns:discountResponse'/>
<xs:complexType name='discountRequest'>
<xs:sequence>
<xs:element minOccurs='0' name='customer'
type='ns1:customer'/>
</xs:sequence>
</xs:complexType>
<xs:complexType name='discountResponse'>
<xs:sequence>
19
Chapter 3. JBossWS-QuickStart
</types>
<message name='ProfileMgmt_getCustomerDiscount'>
<part element='tns:getCustomerDiscount' name='getCustomerDiscount'/>
</message>
<message name='ProfileMgmt_getCustomerDiscountResponse'>
<part element='tns:getCustomerDiscountResponse'
name='getCustomerDiscountResponse'/>
</message>
<portType name='ProfileMgmt'>
<operation name='getCustomerDiscount'
parameterOrder='getCustomerDiscount'>
<input message='tns:ProfileMgmt_getCustomerDiscount'/>
<output message='tns:ProfileMgmt_getCustomerDiscountResponse'/>
</operation>
</portType>
<binding name='ProfileMgmtBinding' type='tns:ProfileMgmt'>
<soap:binding style='document'
transport='http://schemas.xmlsoap.org/soap/http'/>
<operation name='getCustomerDiscount'>
<soap:operation soapAction=''/>
<input>
<soap:body use='literal'/>
</input>
<output>
<soap:body use='literal'/>
</output>
</operation>
</binding>
<service name='ProfileMgmtService'>
<port binding='tns:ProfileMgmtBinding' name='ProfileMgmtPort'>
<soap:address
location='http://<HOST>:<PORT>/jaxws-samples-retail/ProfileMgmtBean'/>
</port>
</service>
</definitions>
20
Chapter 4.
JBossWS-UserGuide
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.
4.1.1.1. 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.
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'/>
21
Chapter 4. JBossWS-UserGuide
</sequence>
</complexType>
<element name='concat' type='tns:concatType'/>
<message name='EndpointInterface_concat'>
<part name='parameters' element='tns:concat'/></message>
<message name='EndpointInterface_concat'>
<part name='parameters' type='tns:concatType'/></message>
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;
22
Web Service Concepts
...
}
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.
4.1.1.2. 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 port type operation name defines the endpoint method name
23
Chapter 4. JBossWS-UserGuide
<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>
<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.
4.1.1.3. RPC/Encoded
24
Web Service Endpoints
20000508] specification. It has inherent interoperability issues that cannot be fixed. The Basic
Profile-1.0 [http://www.ws-i.org/Profiles/BasicProfile-1.0-2004-04-16.html] prohibits this encoding
style in 4.1.7 SOAP encodingStyle Attribute [http://www.ws-i.org/Profiles/BasicProfile-1.0-2004-
04-16.html#refinement16448072].
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)
{
...
}
}
<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>
25
Chapter 4. JBossWS-UserGuide
</servlet-mapping>
</web-app>
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.
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)
{
...
}
26
Web Service Endpoints
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.
<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>
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)
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 instances 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>
27
Chapter 4. JBossWS-UserGuide
{
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)
4.1.2.4. 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);
28
Web Service Clients
}
}
4.1.3.1. Service
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:
@WebServiceClient(name="StockQuoteService",
targetNamespace="http://example.com/stocks",
wsdlLocation="http://example.com/stocks.wsdl")
public class StockQuoteService extends javax.xml.ws.Service
{
public StockQuoteService()
{
29
Chapter 4. JBossWS-UserGuide
...
}
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.
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.
4.1.3.1.3. 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.
30
Web Service Clients
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)
31
Chapter 4. JBossWS-UserGuide
@WebEndpoint(name = "TestEndpointPort")
public TestEndpoint getTestEndpointPort()
{
return (TestEndpoint)super.getPort(TESTENDPOINTPORT,
TestEndpoint.class);
}
}
4.1.3.3. 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.
1. 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.
2. 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.
@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
32
Web Service Clients
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>
33
Chapter 4. JBossWS-UserGuide
4.1.3.4. 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.
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.
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.
34
Web Service Clients
// access future
String retStr = (String) response.get();
assertEquals("Async", retStr);
}
@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;
}
}
There are two properties to configure the http connection timeout and client receive time out:
35
Chapter 4. JBossWS-UserGuide
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"); }
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.
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.
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.
On the service endpoint, handlers are defined using the @HandlerChain annotation.
@WebService
@HandlerChain(file = "jaxws-server-source-handlers.xml")
36
Common API
2. A relative path from the source file or class file. (ex: bar/handlerfile1.xml)
On the client side, handler can be configured using the @HandlerChain annotation on the SEI
or dynamically using the API.
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
37
Chapter 4. JBossWS-UserGuide
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.
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.
38
Common API
4.1.4.4.1.1. WebContext
/**
* Provides web context specific meta data to EJB based web service
endpoints.
*
* @author thomas.diesler@jboss.org [mailto: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
39
Chapter 4. JBossWS-UserGuide
/**
* 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;
}
4.1.4.4.1.2. SecurityDomain
/**
* Annotation for specifying the JBoss security domain for an EJB
*
* @author <a href="mailto:bill@jboss.org [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"
40
Tools
*/
String value();
/**
* The name for the unauthenticated pricipal
*/
String unauthenticatedPrincipal() default "";
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).
4.1.5. 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.
JBoss and its web service framework come with some tools allowing WS endpoint management.
41
Chapter 4. JBossWS-UserGuide
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.
4.1.6. Configuration
<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
42
Configuration
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.
43
44
Chapter 5.
JBossWS-StackCXFUserGuide
Note
This page covers features available in JBossWS CXF stack only. Please refer to
the common user guide for a basic introduction to JAX-WS programming as well as
documentation on all features, tools, etc. the JBossWS Web Service Framework
provides for every supported stack (including CXF stack).
Also please note this page does not go through the documentation of every feature,
option, etc. provided by Apache CXF; on the countrary the only topics covered here
are specific issues regarding integration with JBoss and stack specific features
provided by JBossWS Web Service Framework for the CXF stack. A few tutorials
are also provided for show how to leverage some WS technologies.
The algorithm for selecting the actual implementation of BusFactory to be used leverages
the Service API, basically looking for optional configurations in META-INF/services/... location
using the current classloader. JBossWS-CXF integration comes with his own implementation
of BusFactory, org.jboss.wsf.stack.cxf.client.configuration.JBossWSBusFactory, that allows
for automatic detection of Spring availability as well as seamless setup of JBossWS
customizations on top of Apache CXF. JBossWSBusFactory is automatically retrieved by the
BusFactory.newInstance() call above.
45
Chapter 5. JBossWS-StackCXFUs...
If user do not provide its own CXF configuration file, a default one is automatically generated
during the deployment.
For POJO deployments the generated jbossws-cxf.xml has the following content:
<beans
xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd'>
46
Extended Features
</jaxws:invoker>
</jaxws:endpoint></beans>
For EJB3 deployments the generated jbossws-cxf.xml has the following content:
<beans
xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd'>
Providing custom CXF configuration to the endpoint deployment is useful in cases when users
want to use features that are not part of standard JAX-WS specification but CXF implements them.
For example see CXF WS-RM tutorial customization file. We are providing custom CXF endpoint
configuration there to turn on WS-RM feature for endpoint.
Note
Note
47
Chapter 5. JBossWS-StackCXFUs...
5.2.1. WS-Addressing
Apache CXF has a thorough support for WS-Addressing; details are available at the following
pages:
Given the JAXWS specification currently covers WS-Addressing basic fuctionalities, users simply
needing to enable it can make use of the @Addressing annotation and AddressingFeature, as
shown in the following JBossWS-CXF tutorial:
5.2.2. WS-ReliableMessaging
5.2.3. WS-Policy
Apache CXF technical documentation on the WS-Policy engine and its configuration is available
at:
For a complete sample of WS-Policy usage, please take a look at the JBossWS-CXF WS-
ReliableMessaging tutorial below, as WS-RM is implemented leveraging policies there:
48
WS-Security
When building up the Bus without Spring libraries available on the classpath, JBossWSBusFactory
still makes sure the PolicyEngine (as well as the RMManager) is properly setup. This allows users
to leverage basic WS-Policy functionalities the same way they'd do with a full Spring-enabled Bus.
5.2.4. WS-Security
Apache CXF [http://cxf.apache.org/] leverages WSS4J [http://ws.apache.org/wss4j/] to provide
WS-Security functionalities. This means that thanks to the JBossWS-CXF integration, users can
create web service applications using CXF - WSS4J implementation of WS-Security and deploy
them on JBoss Application Server.
The Apache CXF documentation features an brief chapter on how to use WSS4J security in
CXF [http://cwiki.apache.org/CXF20DOC/ws-security.html]. Here below instead you'll find some
explanations on how to create a simple application and what you need to do to leverage WSS4J
security on JBoss.
First of all you need to create the web service endpoint / client using JAX-WS. This can be achieved
in many ways, for instance you might want to:
1. write your endpoint implementation, then run the wsprovide JBoss commandline tool which
generates the service contract (bottom-up approach);
2. run the wsconsume JBoss commandline tool to get the client artifacts from the service contract
(top-down approach);
Turn on WS-Security
49
Chapter 5. JBossWS-StackCXFUs...
WSS4J security is triggered through interceptors that are added to the service and/or client. These
interceptors allows you to perform the most common WS-Security related process:
• sign messages;
• timestamp messages.
Interceptors can be added either programmatically or through the Spring xml configuration of
endpoints.
For instance, on server side, you can configure signature and encryption in the jboss-cxf.xml file
this way:
<beans
xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd'>
<bean id="Sign_Request"
class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<constructor-arg>
<map>
<entry key="action" value="Timestamp Signature Encrypt"/>
<entry key="signaturePropFile" value="bob.properties"/>
<entry key="decryptionPropFile" value="bob.properties"/>
<entry key="passwordCallbackClass"
value="org.jboss.test.ws.jaxws.samples.wsse.KeystorePasswordCallback"/>
</map>
</constructor-arg>
</bean>
<bean id="Sign_Response"
class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<constructor-arg>
<map>
<entry key="action" value="Timestamp Signature Encrypt"/>
<entry key="user" value="bob"/>
50
WS-Security
<jaxws:endpoint
id='ServiceImpl'
address='http://@jboss.bind.address@:8080/jaxws-samples-wsse-sign-encrypt'
implementor='org.jboss.test.ws.jaxws.samples.wsse.ServiceImpl'>
<jaxws:invoker>
<bean class='org.jboss.wsf.stack.cxf.InvokerJSE'/>
</jaxws:invoker>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor"/>
<ref bean="Sign_Response"/>
</jaxws:outInterceptors>
<jaxws:inInterceptors>
<ref bean="Sign_Request"/>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
This specifies the whole security configuration (including algorithms and elements to be signed/
encrypted); moreover it references a properties file (bob.properties) providing the keystore-related
information:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=password
org.apache.ws.security.crypto.merlin.keystore.alias=bob
51
Chapter 5. JBossWS-StackCXFUs...
org.apache.ws.security.crypto.merlin.file=bob.jks
As you can see in the jbossws-cxf.xml file above, a keystore password callback handler is also
configured; while the properties file has the password for the keystore, this callback handler is
used to set password for each key (it has to match the one used when each key was imported
in the store). Here's a trivial example:
package org.jboss.test.ws.jaxws.samples.wsse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public KeystorePasswordCallback()
{
passwords.put("alice", "password");
passwords.put("bob", "password");
}
52
WS-Security
On client side, you can similarly setup the interceptors programmatically; here is an excerpt of
the client for the above described endpoint (of course you can also leverage a proper Spring
configuration for loading an already configured CXF Bus instance):
To deploy your web service endpoint, you need to package the following files along with your
service implementation and wsdl contract:
53
Chapter 5. JBossWS-StackCXFUs...
For instance, here are the archive contents for the afore mentioned signature & encryption sample
(POJO endpoint):
On client side, instead, you only need the properties and keystore files (assuming you setup the
interceptors programmatically).
Check that JBossWS-CXF is installed on your current JBoss Application Server, deploy and test
your WS-Security-enabled application.
54
WS-Security
Starting from JBossWS-CXF 3.1.1, WS-Security Policy implementation is available and can be
used to configure WS-Security more easily.
...
<binding name="SecurityServicePortBinding" type="tns:ServiceIface">
<wsp:PolicyReference URI="#SecurityServiceSignPolicy"/>
...
<wsp:Policy wsu:Id="SecurityServiceSignPolicy"
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding
xmlns:sp='http://schemas.xmlsoap.org/ws/2005/07/securitypolicy'>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken='http://
schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/
AlwaysToRecipient'>
<wsp:Policy>
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken='http://
schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always'>
<wsp:Policy>
<sp:WssX509V3Token10 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
55
Chapter 5. JBossWS-StackCXFUs...
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:OnlySignEntireHeadersAndBody />
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:Wss10
xmlns:sp='http://schemas.xmlsoap.org/ws/2005/07/securitypolicy'>
<wsp:Policy>
<sp:MustSupportRefEmbeddedToken />
</wsp:Policy>
</sp:Wss10>
<sp:SignedParts
xmlns:sp='http://schemas.xmlsoap.org/ws/2005/07/securitypolicy'>
<sp:Body />
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
...
Just few properties are also required to be set either in the message context or in the jbossws-
cxf.xml descriptor.
((BindingProvider)proxy).getRequestContext().put(SecurityConstants.CALLBACK_HANDLER,
new KeystorePasswordCallback());
((BindingProvider)proxy).getRequestContext().put(SecurityConstants.SIGNATURE_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource("META-INF/
alice.properties"));
((BindingProvider)proxy).getRequestContext().put(SecurityConstants.ENCRYPT_PROPERTIES,
Thread.currentThread().getContextClassLoader().getResource("META-INF/
alice.properties"));
<beans
xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd'>
<jaxws:endpoint
id='ServiceImpl'
address='http://@jboss.bind.address@:8080/jaxws-samples-wssePolicy-sign'
56
WS-Security
implementor='org.jboss.test.ws.jaxws.samples.wssePolicy.ServiceImpl'>
<jaxws:properties>
<entry key="ws-security.signature.properties"
value="bob.properties"/>
<entry key="ws-security.encryption.properties"
value="bob.properties"/>
<entry key="ws-security.callback-handler" value="org.jboss.test.ws.jaxws.samples.wsseP
>
</jaxws:properties>
</jaxws:endpoint>
</beans>
The Username Token Profile can of course be used to provide client's credentials to the
target endpoint. Starting from JBossWS-CXF 3.3.0 (which includes Apache CXF 2.2.8), the
username token information can be used for authentication and authorization on JBoss AS (JAAS
integration).
On server side, you need to specify what follows (for instance using a jbossws-cxf.xml descriptor):
<beans
xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jaxws='http://cxf.apache.org/jaxws'
xmlns:util='http://www.springframework.org/schema/util'
xsi:schemaLocation='http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
57
Chapter 5. JBossWS-StackCXFUs...
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd'>
<bean id="SecurityContextIn"
class="org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingInterceptor">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken"/>
</map>
</constructor-arg>
</bean>
<util:map id="methodPermissions">
<entry key="sayHello" value="friend"/>
<entry key="greetMe" value="snoopies"/>
</util:map>
<bean id="AuthorizeIn"
class="org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor">
<property name="methodRolesMap" ref="methodPermissions"/>
</bean>
<jaxws:endpoint
id='ServiceImpl'
address='http://@jboss.bind.address@:8080/jaxws-samples-wsse-username-
authorize'
implementor='org.jboss.test.ws.jaxws.samples.wsse.ServiceImpl'>
<jaxws:inInterceptors>
<ref bean="SecurityContextIn"/>
<ref bean="AuthorizeIn"/>
<bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/>
</jaxws:inInterceptors>
</jaxws:endpoint>
</beans>
Authentication and authorization will simply be delegated to the security domain configured for the
endpoint. Of course you can specify the login module you prefer for that security domain (refer
the application server / security documentation for that).
On client side, the username is provided through API (or a custom Spring configuration used to
load the Bus):
58
WS-Security
The password instead is provided through a password callback handler that needs to
implement javax.security.auth.callback.CallbackHandler, similarly to the keystore's password
callback handler.
If you're running an older JBossWS-CXF version, or you're not interested in the the application
server auth integration, you can use a password callback handler on server side too, configured
through a WSS4JInInterceptor:
<bean id="UsernameToken_Request">
<constructor-arg>
<map>
<entry key="action" value="UsernameToken"/>
<entry key="passwordCallbackClass" value="org.jboss.test.ws.jaxws.samples.wsse.ServerUs
>
</map>
</constructor-arg>
</bean>
package org.jboss.test.ws.jaxws.samples.wsse;
import java.io.IOException;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
59
Chapter 5. JBossWS-StackCXFUs...
WSPasswordCallback pc = (WSPasswordCallback)callbacks[0];
if (!("kermit".equals(pc.getIdentifier()) &&
"thefrog".equals(pc.getPassword())))
throw new SecurityException("User '" + pc.getIdentifier() + "' with
password '" + pc.getPassword() + "' not allowed.");
}
}
Samples
The JBossWS-CXF source distribution comes with some samples using X.509 certificate
signature and encryption as well as Username Token Profile. You can find them in package
org.jboss.test.ws.jaxws.samples.wsse .
Crypto algorithms
When requiring encryption, you might need to install an additional JCE provider supporting the
crypto algorithms Apache CXF uses. This usually means the Bouncy Castle provider need to be
configured in your JRE. Please refer the Native stack user [http://community.jboss.org/docs/DOC-
13532] guide for further information about this.
The JBossWS-CXF integration leverages CXF servlet transport for the deployment of endpoints
on top of the running JBoss Application Server.
60
SOAP Message Logging
defaults to using the Jetty [http://jetty.codehaus.org/jetty/] based http transport. Starting from
release 3.4.0, the JBossWS-CXF integration instead uses a different http transport module based
on the http server [http://download.oracle.com/javase/6/docs/jre/api/net/httpserver/spec/com/sun/
net/httpserver/package-summary.html] embedded in JDK6 distributions. Thanks to Apache CXF
transport pluggability, users can still change the transport they want to use in this case by
simply replacing the jbossws-cxf-transports-httpserver.jar library with another http transport one,
for instance the cxf-rt-transports-http-jetty.jar.
<cxf:bus>
<cxf:inInterceptors>
<ref bean="logInbound"/>
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref bean="logOutbound"/>
</cxf:outInterceptors>
<cxf:inFaultInterceptors>
<ref bean="logOutbound"/>
</cxf:inFaultInterceptors>
</cxf:bus>
Once you've uncommented the cxf-extension-jbossws.xml contents, you need to re-pack the jar/
zip.
[*] The cxf-extension-jbossws.xml is available from version 3.2.2; if you don't have that file, you
can manually add it and link it in cxf.extensions file.
Finally, please note that logging can be enabled in many ways with Apache CXF, see the following
documentation pages for instance:
• http://cxf.apache.org/docs/configuration.html
• http://cxf.apache.org/docs/debugging-and-logging.html
61
62
Chapter 6.
JBossWS-JAX-WSTools
The JAX-WS tools provided by JBossWS can be used in a variety of ways. First we will look at
server-side development strategies, and then proceed to the client.
• Providing a new service, and you want the contract to be generated for you
• Replacing the implementation of an existing Web Service, and you can't break compatibility
with older clients
• Exposing a service that conforms to a contract specified by a third party (e.g. a vender that calls
you back using an already defined protocol).
• Creating a service that adheres to the XML Schema and WSDL you developed by hand up front
Command Description
JBossWS - wsprovide Generates JAX-WS portable artifacts, and
provides the abstract contract. Used for
bottom-up development.
JBossWS - wsconsume Consumes the abstract contract (WSDL and
Schema files), and produces artifacts for both a
server and client. Used for top-down and client
development
JBossWS - wsrunclient Executes a Java client (has a main method)
using the JBossWS classpath.
63
Chapter 6. JBossWS-JAX-WSTools
generated for your service. For example, you can change the operation name to map to anything
you like. However, all of the annotations have sensible defaults, so only the @WebService
annotation is required.
package echo;
@javax.jws.WebService
public class Echo
{
public String echo(String input)
{
return input;
}
}
A JSE or EJB3 deployment can be built using this class, and it is the only Java code needed
to deploy on JBossWS. The WSDL, and all other Java artifacts called "wrapper classes" will be
generated for you at deploy time. This actually goes beyond the JAX-WS specification, which
requires that wrapper classes be generated using an offline tool. The reason for this requirement
is purely a vender implementation problem, and since we do not believe in burdening a developer
with a bunch of additional steps, we generate these as well. However, if you want your deployment
to be portable to other application servers, you will unfortunately need to use a tool and add the
generated classes to your deployment.
This is the primary purpose of the JBossWS - wsprovidetool, to generate portable JAX-WS
artifacts. Additionally, it can be used to "provide" the abstract contract (WSDL file) for your service.
This can be obtained by invoking JBossWS - wsprovide using the "-w" option:
64
Bottom-Up (Using wsprovide)
<output message='tns:Echo_echoResponse'/></operation>
</portType>
Note
Note
Remember that when deploying on JBossWS you do not need to run this tool.
You only need it for generating portable artifacts and/or the abstract contract for
your service.
Let's create a POJO endpoint for deployment on JBoss AS. A simple web.xml needs to be created:
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>Echo</servlet-name>
<servlet-class>echo.Echo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Echo</servlet-name>
<url-pattern>/Echo</url-pattern>
</servlet-mapping>
</web-app>
The web.xml and the single class can now be used to create a war:
$ mkdir -p WEB-INF/classes
$ cp -rp echo WEB-INF/classes/
$ cp web.xml WEB-INF
$ jar cvf echo.war WEB-INF
added manifest
adding: WEB-INF/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/echo/(in = 0) (out= 0)(stored 0%)
adding: WEB-INF/classes/echo/Echo.class(in = 340) (out= 247)(deflated 27%)
adding: WEB-INF/web.xml(in = 576) (out= 271)(deflated 52%)
cp echo.war /usr/local/jboss-4.2.0.GA-ejb3/server/default/deploy
65
Chapter 6. JBossWS-JAX-WSTools
This will internally invoke JBossWS - wsprovide, which will generate the WSDL. If deployment
was successful, and you are using the default settings, it should be available here: http://
localhost:8080/echo/Echo?wsdl
For a portable JAX-WS deployment, the wrapper classes generated earlier could be added to the
deployment.
Note
Note
Using the WSDL file from the bottom-up example, a new Java implementation that adheres to this
service can be generated. The "-k" option is passed to JBossWS - wsconsume to preserve the
Java source files that are generated, instead of providing just classes:
$ wsconsume -k EchoService.wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
File Purpose
Echo.java Service Endpoint Interface
Echo_Type.java Wrapper bean for request message
EchoResponse.java Wrapper bean for response message
66
Client Side
File Purpose
ObjectFactory.java JAXB XML Registry
package-info.java Holder for JAXB package annotations
EchoService.java Used only by JAX-WS clients
Examining the Service Endpoint Interface reveals annotations that are more explicit than in the
class written by hand in the bottom-up example, however, these evaluate to the same contract:
The only missing piece (besides the packaging) is the implementation class, which can now be
written, using the above interface.
package echo;
@javax.jws.WebService(endpointInterface="echo.Echo")
public class EchoImpl implements Echo
{
public String echo(String arg0)
{
return arg0;
}
}
67
Chapter 6. JBossWS-JAX-WSTools
reason, your software does not adhere to this principal, then you should not be using Web
Services. For the above reasons, the recommended methodology for developing a client is
to follow the top-down approach, even if the client is running on the same server.
Let's repeat the process of the top-down section, although using the deployed WSDL, instead of
the one generated offline by JBossWS - wsprovide. The reason why we do this is just to get the
right value for soap:address. This value must be computed at deploy time, since it is based on
container configuration specifics. You could of course edit the WSDL file yourself, although you
need to ensure that the path is correct.
Offline version:
<service name='EchoService'>
<port binding='tns:EchoBinding' name='EchoPort'>
<soap:address location='REPLACE_WITH_ACTUAL_URL'/>
</port></service>
Online version:
<service name="EchoService">
<port binding="tns:EchoBinding" name="EchoPort">
<soap:address location="http://localhost.localdomain:8080/echo/Echo"/>
</port>
</service>
$ wsconsume -k http://localhost:8080/echo/Echo?wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
The one class that was not examined in the top-down section, was EchoService.java. Notice how
it stores the location the WSDL was obtained from.
68
Client Side
{
private final static URL ECHOSERVICE_WSDL_LOCATION;
static {
URL url = null;
try {
url = new URL("http://localhost:8080/echo/Echo?wsdl");
} catch (MalformedURLException e) {
e.printStackTrace();
}
ECHOSERVICE_WSDL_LOCATION = url;
}
public EchoService() {
super(ECHOSERVICE_WSDL_LOCATION, new QName("http://echo/",
"EchoService"));
}
@WebEndpoint(name = "EchoPort")
public Echo getEchoPort() {
return (Echo)super.getPort(new QName("http://echo/", "EchoPort"),
Echo.class);
}
}
As you can see, this generated class extends the main client entry point in JAX-WS,
javax.xml.ws.Service. While you can use Service directly, this is far simpler since it provides the
configuration info for you. The only method we really care about is the getEchoPort() method,
which returns an instance of our Service Endpoint Interface. Any WS operation can then be called
by just invoking a method on the returned interface.
Note
Note
import echo.*;
69
Chapter 6. JBossWS-JAX-WSTools
It can then be easily executed using the JBossWS - wsrunclient tool. This is just a convenience
tool that invokes java with the needed classpath:
It is easy to change the endpoint address of your operation at runtime, setting the
ENDPOINT_ADDRESS_PROPERTY as shown below:
...
EchoService service = new EchoService();
Echo echo = service.getEchoPort();
70
JAX-WS binding customization
• http://java.sun.com/webservices/docs/2.0/jaxws/customizations.html
• xnsdoc [https://jax-ws.dev.java.net/nonav/guide/customizations/]
The schema for the binding customization files can be found here:
• https://jax-ws.dev.java.net/source/browse/jax-ws/guide/docs/wsdl-
customization.xsd?rev=1.2&view=log
71
72
Chapter 7.
JBossWS-wsconsume
wsconsume is a command line tool and ant task that "consumes" the abstract
contract (WSDL file) and produces portable JAX-WS service and client artifacts. For
a more detailed overview, see "Using wsconsume" [http://community.jboss.org/docs/DOC-
13544#TopDown_Using_wsconsume].
Note : The wsdlLocation is used when creating the Service to be used by clients and will be added
to the @WebServiceClient annotation, for an endpoint implementation based on the generated
service endpoint interface you will need to manually add the wsdlLocation to the @WebService
annotation on your web service implementation and not the service endpoint interface.
7.1.1. Examples
Generate artifacts in Java class form only:
wsconsume Example.wsdl
wsconsume -k Example.wsdl
73
Chapter 7. JBossWS-wsconsume
${project.build.testOutputDirectory}
sourceDirectory The output directory for Java ${project.build.directory}/
source. wsconsume/java
74
Examples
7.2.1. Examples
You can use wsconsume in your own project build simply referencing the maven-jaxws-tools-
plugin in the configured plugins in your pom.xml file.
The following example makes the plugin consume the test.wsdl file and generate SEI and
wrappers' java sources. The generated sources are then compiled together with the other project
classes.
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>1.0.0.GA</version>
<configuration>
<wsdls>
<wsdl>${basedir}/test.wsdl</wsdl>
</wsdls>
</configuration>
<executions>
<execution>
<goals>
<goal>wsconsume</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
You can also specify multiple wsdl files, as well as force the target package, enable SOAP 1.2
binding and turn the tool's verbose mode on:
<build>
75
Chapter 7. JBossWS-wsconsume
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>1.0.0.GA</version>
<configuration>
<wsdls>
<wsdl>${basedir}/test.wsdl</wsdl>
<wsdl>${basedir}/test2.wsdl</wsdl>
</wsdls>
<targetPackage>foo.bar</targetPackage>
<extension>true</extension>
<verbose>true</verbose>
</configuration>
<executions>
<execution>
<goals>
<goal>wsconsume</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Finally, if the wsconsume invocation is required for consuming a wsdl to be used in your testsuite
only, you might want to use the wsconsume-test goal as follows:
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>1.0.0.GA</version>
<configuration>
<wsdls>
<wsdl>${basedir}/test.wsdl</wsdl>
</wsdls>
</configuration>
<executions>
<execution>
<goals>
<goal>wsconsume-test</goal>
</goals>
</execution>
</executions>
76
Ant Task
</plugin>
</plugins>
</build>
Note
Note
77
Chapter 7. JBossWS-wsconsume
Note : The wsdlLocation is used when creating the Service to be used by clients and will be added
to the @WebServiceClient annotation, for an endpoint implementation based on the generated
service endpoint interface you will need to manually add the wsdlLocation to the @WebService
annotation on your web service implementation and not the service endpoint interface.
7.3.1. Examples
Generate JAX-WS source and classes in a separate JVM with separate directories, a custom wsdl
location attribute, and a list of binding files from foo.wsdl:
<wsconsume
fork="true"
verbose="true"
destdir="output"
sourcedestdir="gen-src"
keep="true"
wsdllocation="handEdited.wsdl"
wsdl="foo.wsdl">
<binding dir="binding-files" includes="*.xml" excludes="bad.xml"/>
</wsconsume>
78
Chapter 8.
JBossWS-wsprovide
wsprovide is a command line tool and ant task that generates portable JAX-WS
artifacts for a service endpoint implementation. It also has the option to "provide" the
abstract contract for offline usage. See "Using wsprovide" [http://community.jboss.org/docs/DOC-
13544#BottomUp_Using_wsprovide] for a detailed walk-through.
8.1.1. Examples
Generating wrapper classes for portable artifacts in the "generated" directory:
79
Chapter 8. JBossWS-wsprovide
${project.build.testOutputDirectory}
resourceDirectory The output directory for ${project.build.directory}/
resource artifacts (WSDL/ wsprovide/resources
XSD).
sourceDirectory The output directory for Java ${project.build.directory}/
source. wsprovide/java
extension Enable SOAP 1.2 binding false
extension.
generateWsdl Whether or not to generate false
WSDL.
verbose Enables more informational false
output about command
progress.
endpointClass Service Endpoint
Implementation.
8.2.1. Examples
You can use wsprovide in your own project build simply referencing the maven-jaxws-tools-plugin
in the configured plugins in your pom.xml file.
The following example makes the plugin provide the wsdl file and artifact sources for the specified
endpoint class:
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>@pom.version@</version>
<configuration>
<verbose>true</verbose>
<endpointClass>org.jboss.test.ws.plugins.tools.wsprovide.TestEndpoint</
endpointClass>
80
Ant Task
<generateWsdl>true</generateWsdl>
</configuration>
<executions>
<execution>
<goals>
<goal>wsprovide</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The following example does the same, but is meant for use in your own testsuite:
<build>
<plugins>
<plugin>
<groupId>org.jboss.ws.plugins</groupId>
<artifactId>maven-jaxws-tools-plugin</artifactId>
<version>@pom.version@</version>
<configuration>
<verbose>true</verbose>
<endpointClass>org.jboss.test.ws.plugins.tools.wsprovide.TestEndpoint2</
endpointClass>
<generateWsdl>true</generateWsdl>
</configuration>
<executions>
<execution>
<goals>
<goal>wsprovide-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Note
Note
81
Chapter 8. JBossWS-wsprovide
8.3.1. Examples
Executing wsprovide in verbose mode with separate output directories for source, resources, and
classes:
82
Examples
keep="true"
destdir="out"
resourcedestdir="out-resource"
sourcedestdir="out-source"
genwsdl="true"
verbose="true"
sei="org.jboss.test.ws.jaxws.jsr181.soapbinding.DocWrappedServiceImpl">
<classpath>
<pathelement path="${tests.output.dir}/classes"/>
</classpath>
</wsprovide>
</target>
83
84
Chapter 9.
JBossWS-wsrunclient
wsrunclient is a command line tool that invokes a JBossWS JAX-WS Web Service client. It builds
the correct classpath and endorsed libs for you. Feel free to use the code for this script to make
your own shell scripts. It is open source after all.
9.1. Usage
wsrunclient [-classpath <additional class path>] <java-main-class>
[arguments...]
9.2. Examples
Invoking a standalone JAX-WS client:
wsrunclient echo.EchoClient
85
86
Part III. Additional documentation
This section of the book provides documentation on common additional user requirements, like
enabling authentication, securing the transport, etc.
Chapter 10.
JBossWS-Authentication
This page explains the simplest way to authenticate a web service user with JBossWS.
First we secure the access to the SLSB as we would do for normal (non web service) invocations:
this can be easily done through the @RolesAllowed, @PermitAll, @DenyAll annotation. The
allowed user roles can be set with these annotations both on the bean class and on any of its
business methods.
@Stateless
@RolesAllowed("friend")
public class EndpointEJB implements EndpointInterface
{
...
}
Similarly POJO endpoints are secured the same way as we do for normal web applications in
web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>friend</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>friend</role-name>
</security-role>
@Stateless
@SecurityDomain("JBossWS")
@RolesAllowed("friend")
public class EndpointEJB implements EndpointInterface
{
...
}
89
Chapter 10. JBossWS-Authentic...
<jboss-web>
<security-domain>java:/jaas/JBossWS</security-domain>
</jboss-web>
<!--
A template configuration for the JBossWS security domain.
This defaults to the UsersRolesLoginModule the same as other and should
be
changed to a stronger authentication mechanism as required.
-->
<application-policy name="JBossWS">
<authentication>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag="required">
<module-option
name="usersProperties">props/jbossws-users.properties</module-option>
<module-option
name="rolesProperties">props/jbossws-roles.properties</module-option>
<module-option
name="unauthenticatedIdentity">anonymous</module-option>
</login-module>
</authentication>
</application-policy>
Of course you can define and use your own security domain as well as your login module (in order
to check for users' identity querying a database for example).
BindingProvider bp = (BindingProvider)port;
90
Using HTTP Basic Auth for security
bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "kermit");
bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
@Stateless
@SecurityDomain("JBossWS")
@RolesAllowed("friend")
@WebContext(contextRoot="/my-cxt", urlPattern="/*", authMethod="BASIC",
transportGuarantee="NONE", secureWSDLAccess=false)
public class EndpointEJB implements EndpointInterface
{
...
}
For POJO endpoints, we modify the web.xml adding the auth-method element:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Test Realm</realm-name>
</login-config>
91
92
Chapter 11.
JBossWS-Securetransport
JBossWS allows you to require that requests to a given endpoint use SSL by specifying
the transportGuarantee attribute in the @WebContext [http://community.jboss.org/docs/DOC-
13972#WebContext] annotation.
@Stateless
@SecurityDomain("JBossWS")
@RolesAllowed("friend")
@WebContext
(
contextRoot="/my-cxt",
urlPattern="/*",
authMethod="BASIC",
transportGuarantee="CONFIDENTIAL",
secureWSDLAccess=false
)
public class EndpointEJB implements EndpointInterface
{
...
}
Similarly to enforce the same requirement on POJO endpoints, you need to edit web.xml and add
a user-data-constraint element to your security-constraint element:
<security-constraint>
<web-resource-collection>
<web-resource-name>All resources</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>friend</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<security-role>
<role-name>friend</role-name>
</security-role>
If you're manually creating your service contract, make sure that the endpoint address in your
WSDL file uses a secure protocol. The easiest way is to add "https://" to the SOAP Address entry:
93
Chapter 11. JBossWS-Securetra...
<service name="MyService">
<port name="BasicSecuredPort" binding="tns:MyBinding">
<soap:address location="https://localhost:8443/my-ctx/SecureEndpoint"/>
</port>
</service>
keystorePass="jbossws"
truststoreFile="${jboss.server.home.dir}/conf/keystores/wsse.keystore"
truststorePass="jbossws"
sslProtocol = "TLS" />
<sysproperty key="javax.net.ssl.keyStore"
value="${test.resources.dir}/wsse/wsse.keystore"/>
<sysproperty key="javax.net.ssl.trustStore"
value="${test.resources.dir}/wsse/wsse.truststore"/>
<sysproperty key="javax.net.ssl.keyStorePassword" value="jbossws"/>
<sysproperty key="javax.net.ssl.trustStorePassword" value="jbossws"/>
<sysproperty key="javax.net.ssl.keyStoreType" value="jks"/>
<sysproperty key="javax.net.ssl.trustStoreType" value="jks"/>
As you can see, this requires you to setup the environment specifying both the location and type
of your truststore.
94
Client side
95
96
Chapter 12.
JBossWS-Endpointmanagement
JBossWS registers MBeans that users can leverage to manage every webservice endpoint. Apart
from the obvious start/stop functionalities, they provide valuable information and statistics about
messages processed by the endpoints.
The application server also has an applet based web-console which basically has the same data
as the JMX-Console plus some advanced features including snapshot graphics.
Of course you can access an MBean programmatically too. Please refer to the JBoss JMX faq
[http://wiki.jboss.org/wiki/Wiki.jsp?page=FAQJBossJMX] for further details; here is a brief code
snippet you might want to start from in order to access a ManagedEndpointMBean from the same
virtual machine:
try
{
MBeanServer server = MBeanServerLocator.locate();
ManagedEndpointMBean mep = (ManagedEndpointMBean)MBeanProxyExt.create(
ManagedEndpointMBean.class,
"jboss.ws:context=my-ctx,endpoint=MyEndpoit",
server);
...
}
catch (Exception e)
{
e.printStackTrace();
}
12.2. Metrics
For each deployed endpoint you'll find an
org.jboss.wsf.framework.management.ManagedEndpoint MBean providing basic start/stop
functionalities and metrics. Calling a stopped endpoint will always result in a SOAP fault message.
• Min, max, average and total processing time: processing includes both the WS stack plus
application server work and the user business logic
97
Chapter 12. JBossWS-Endpointm...
12.3. Records
JBossWS features a highly configurable records' collection and management system. Each record
is basically composed of a message plus additional information (for example the caller address
and the called endpoint operation).
Endpoints can be configured with record processors that are invoked whenever a message flow
is detected and records are thus created.
Every deployed endpoint is configured with default record processors. However custom
processors as well as record filters can be easily plugged in and managed at any time through
JMX. This gives users the chance of performing advanced analysis of the webservice traffic
according to their business requirements.
Snapshots allow users to record changes of a given MBean attribute within a defined time interval.
Data are sampled at a given rate and may be plotted to graphs with a few clicks. Snapshots
are listed in the Web console and can be created simply browsing to http://localhost:8080/web-
console/createSnapshot.jsp .
Threshold monitors allow users to be notified whenever a given MBean attribute exceed a certain
range of values. The threshold monitor's creation and management processes are similar to
those mentioned above for the snapshots. Simply browse to http://localhost:8080/web-console/
createThresholdMonitor.jsp .
Speaking of WS availability and SLA, this all becomes interesting because users
can monitor and take snapshots of critical attributes like the average/max processing
time of a managed endpoint. Moreover, advanced analysis can be performed
leveraging ad-hoc attributes of custom record processors [http://jbossws.jboss.org/mediawiki/
index.php?title=Endpoint_management#Records].
98
Chapter 13.
JBossWS-Recordsmanagement
JBossWS records' collection and management system gives administrators a means of
performing custom analysis of their webservice traffic as well as exporting communication logs.
• Creation date
• Source host
• Destination host
• Message envelope (including both soap:header and soap:body for SOAP messages)
• Http headers
• Record group ID (allowing records belonging to the same message flow to be linked together)
Of course records may also have meaningful values for a subset of the afore mentioned record
attributes.
• Logging request and response messages: being able to record messages received from and
sent to a given service consumer without stopping the provider may be really useful. You just
need to set the recording attribute of their endpoint's LogRecorder to true. The added value of
this logging solution comes from the use of filters through which messages coming from a given
address and related to a given wsdl operation only can be logged.
99
Chapter 13. JBossWS-Recordsma...
• Accountability: service providers may want to know which consumers are actually hitting a
given service. This can be done for example using the getClientHosts functionality of the
MemoryBufferRecorder once it has been switched to recording state.
• Getting statistics, filtering records: service administrators might want to see the last records
related to a given endpoint or operation, the last records related to messages coming from
a given customer and the response the system gave them, etc. These information can be
obtained using the getRecordsByOperation, getRecordsByClientHost or the more general
getMatchingRecords functionality of the MemoryBufferRecorder.
• Record processors plugged into deployed endpoints; handlers collect records and send them
to every processors through the current endpoint. Processors may store records, convert them,
log them, ...
• MBean views of processors that can be used to configure and fine tune recording at runtime
• LogRecorder: a simple record processor that writes records to the configured log.
• MemoryBufferRecorder: a record processor that keeps the last received records in memory and
allows user to search / get statistics on them.
Every processors can be fine tuned to process some record attributes only according to the
user and/or performance requirements. Default processors are not in recording mode upon
creation, thus you need to switch them to recording mode through their MBean interfaces (see
the Recording flag in the jmx-console).
• processDestinationHost (true)
100
Server side
• processSourceHost (true)
• processHeaders (true)
• processEnvelope (true)
• processMessageType (true)
• processOperation (true)
• processDate (true)
• recording (false)
The recording system is available for all the JBossWS supported stacks. However slightly different
procedure is required to enable it depending on the used stack.
Native stack
<endpoint-config>
<config-name>Standard Endpoint</config-name>
<pre-handler-chains>
<javaee:handler-chain>
<javaee:protocol-bindings>##SOAP11_HTTP</javaee:protocol-bindings>
<javaee:handler>
<javaee:handler-name>Recording Handler</javaee:handler-name>
<javaee:handler-
class>org.jboss.wsf.framework.invocation.RecordingServerHandler</
javaee:handler-class>
</javaee:handler>
</javaee:handler-chain>
</pre-handler-chains>
</endpoint-config>
101
Chapter 13. JBossWS-Recordsma...
Once the handler is properly added to the chain, log recording configuration is agnostic to the
used stack. Users just need to tune the processors parameters though their MBean interfaces.
• Give you record processor an MBean interface declaring the manageable attributes: the
recording system will plug your processor to the endpoint and register a management
MBean for it using your interface. This allows you to create highly configurable
custom processors. For an example of this development option, take a look at the
org.jboss.wsf.framework.management.recording.MemoryBufferRecorder.
• Add your record processor to the managed endpoint as is: the recording system will plug it to
the endpoint and register a standard management MBean for its basic processing configuration.
The org.jboss.wsf.framework.management.recording.LogRecorder is an example of this
development option.
102
Handler's position
A code snippet showing how to get the MBeanProxy instance which you can invoke MBean with
can be found here.
For this reason, you might want to install multiple recording handlers into different points of the
handler chain. For instance, it could make sense to record messages both before and after
encryption/decryption when using WS-Security.
A DB based recorder could be developed; it should work the same way the MemoryBufferRecorder
does, except for records that should be saved through a given datasource. This will provide
persistence of data even in case of application server reboot and webservice application redeploy.
It will also allow records coming from different node of a cluster to be stored together. Finally this
would allow administrators to directly query the database, which might be far more efficient.
103
Chapter 13. JBossWS-Recordsma...
13.6. References
You might want to take a look at the org.jboss.wsf.framework.management.recording and
org.jboss.wsf.spi.management.recording packages in the source code to better understand how
all this works and can be used.
104
Part IV. Samples & Tutorials
Below you find few tutorials on WS-* technologies usage as well as a brief list of reference links
and the list of supported JAX-WS annotations.
Chapter 14.
JBossWS-CXFWS-
Addressingtutorial
Apache CXF [http://incubator.apache.org/cxf/] comes with support for WS-Addressing 1.0 [http:/
/www.w3.org/TR/ws-addr-core/]. In this sample we will show how to create client and endpoint
communicating each other using this feature.
Creating WS-Addressing based service and client is very simple. User needs to create regular
JAX-WS service and client first. The last step is to configure the addressing on both sides.
@WebService
(
portName = "AddressingServicePort",
serviceName = "AddressingService",
targetNamespace =
"http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsa.ServiceIface"
)
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "Hello World!";
}
}
package org.jboss.test.ws.jaxws.samples.wsa;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
107
Chapter 14. JBossWS-CXFWS-Add...
targetNamespace =
"http://www.jboss.org/jbossws/ws-extensions/wsaddressing"
)
public interface ServiceIface
{
@WebMethod
String sayHello();
}
Let's say that compiled endpoint and interface classes are located in directory /home/username/
wsa/cxf/classes. Our next step is to generate JAX-WS artifacts and WSDL that will be part of
endpoint archive.
cd JBOSS_HOME/bin
# compiled classes
ls
/home/username/wsa/cxf/wsprovide/generated/classes/org/jboss/test/ws/jaxws/
samples/wsa/jaxws
SayHello.class SayHelloResponse.class
# java sources
ls
/home/username/wsa/cxf/wsprovide/generated/src/org/jboss/test/ws/jaxws/
samples/wsa/jaxws
SayHello.java SayHelloResponse.java
# contract artifacts
ls /home/username/wsa/cxf/wsprovide/generated/wsdl/
AddressingService.wsdl
All aforementioned generated artifacts will be part of endpoint archive. But before we will create
the endpoint archive we need to reference generated WSDL from endpoint. To achieve that we
108
Generating WSDL and JAX-WS Endpoint
Artifacts
will use wsdlLocation annotation attribute. Here's the updated endpoint implementation before
packaging it to the war file:
package org.jboss.test.ws.jaxws.samples.wsa;
import javax.jws.WebService;
@WebService
(
portName = "AddressingServicePort",
serviceName = "AddressingService",
wsdlLocation = "WEB-INF/wsdl/AddressingService.wsdl",
targetNamespace =
"http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsa.ServiceIface"
)
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "Hello World!";
}
}
109
Chapter 14. JBossWS-CXFWS-Add...
<servlet-class>org.jboss.test.ws.jaxws.samples.wsa.ServiceImpl</servlet-
class>
</servlet>
<servlet-mapping>
<servlet-name>AddressingService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
package org.jboss.test.ws.jaxws.samples.wsa;
110
Turning on WS-Addressing 1.0
Now we have both endpoint and client implementation but without WS-Addressing in place. Our
next goal is to turn on the WS-Addressing feature.
package org.jboss.test.ws.jaxws.samples.wsa;
import javax.jws.WebService;
import javax.xml.ws.soap.Addressing;
@WebService
(
portName = "AddressingServicePort",
serviceName = "AddressingService",
wsdlLocation = "WEB-INF/wsdl/AddressingService.wsdl",
targetNamespace =
"http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsa.ServiceIface"
)
@Addressing(enabled=true, required=true)
public class ServiceImpl implements ServiceIface
{
public String sayHello()
{
return "Hello World!";
}
}
As users can see we added JAX-WS 2.1 Addressing annotation to configure WS-Addressing.
The next step is to repackage the endpoint archive to apply this change.
111
Chapter 14. JBossWS-CXFWS-Add...
package org.jboss.test.ws.jaxws.samples.wsa;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.soap.AddressingFeature;
And that's all. Now we have both JAX-WS client and endpoint communicating each other using
WS-Addressing feature.
An option you can also evaluate to simplify both client and server deployment, is to let the server
engine generate and publish the wsdl contract instead of using the one mentioned above: (please
note the removal of wsdlLocation attribute in the @WebService annotation)
@WebService
(
portName = "AddressingServicePort",
serviceName = "AddressingService",
112
Sample Sources
targetNamespace =
"http://www.jboss.org/jbossws/ws-extensions/wsaddressing",
endpointInterface = "org.jboss.test.ws.jaxws.samples.wsa.ServiceIface"
)
@Addressing(enabled=true, required=true)
public class ServiceImpl implements ServiceIface
{
...
}
This way the endpoint is published with a contract containing a WS-Addressing Policy that tells
clients addressing needs to be on.
<wsp:Policy wsu:Id="AddressingServiceSoapBinding_WSAM_Addressing_Policy">
<wsam:Addressing>
<wsp:Policy/>
</wsam:Addressing>
</wsp:Policy>
No need for setting the AddressingFeature, the policy engine takes care of enabling WS-
Addressing to match the policy advertised by the server.
113
114
Chapter 15.
JBossWS-CXFWS-
ReliableMessagingtutorial
Apache CXF [http://incubator.apache.org/cxf/] comes with support for WS-RM 1.0 [http://
specs.xmlsoap.org/ws/2005/02/rm/ws-reliablemessaging.pdf]. In this sample we will show how to
create client and endpoint communicating each other using WS-RM 1.0. The sample uses WS-
Policy [http://www.w3.org/2006/07/ws-policy/] specification to configure WS-RM.
Creating the WS-RM based service and client is very simple. User needs to create regular JAX-WS
service and client first. The last step is to configure WSRM.
package org.jboss.test.ws.jaxws.samples.wsrm.service;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
name = "SimpleService",
serviceName = "SimpleService",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsrm"
)
public class SimpleServiceImpl
{
@Oneway
@WebMethod
public void ping()
{
System.out.println("ping()");
}
@WebMethod
public String echo(String s)
{
System.out.println("echo(" + s + ")");
return s;
}
}
115
Chapter 15. JBossWS-CXFWS-Rel...
cd $JBOSS_HOME/bin
# compiled classes
ls
/home/username/wsrm/cxf/wsprovide/generated/classes/org/jboss/test/ws/
jaxws/samples/wsrm/service/jaxws/
Echo.class EchoResponse.class Ping.class
# java sources
ls
/home/username/wsrm/cxf/wsprovide/generated/src/org/jboss/test/ws/jaxws/
samples/wsrm/service/jaxws/
Echo.java EchoResponse.java Ping.java
# contract artifacts
ls /home/username/wsrm/cxf/wsprovide/generated/wsdl/
SimpleService.wsdl
All aforementioned generated artifacts will be part of endpoint archive. But before we will create
the endpoint archive we need to reference generated WSDL from endpoint. To achieve that we
will use wsdlLocation annotation attribute. Here's the updated endpoint implementation before
packaging it to the war file:
package org.jboss.test.ws.jaxws.samples.wsrm.service;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
116
Generating WSDL and JAX-WS Endpoint
Artifacts
@WebService
(
name = "SimpleService",
serviceName = "SimpleService",
wsdlLocation = "WEB-INF/wsdl/SimpleService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsrm"
)
public class SimpleServiceImpl
{
@Oneway
@WebMethod
public void ping()
{
System.out.println("ping()");
}
@WebMethod
public String echo(String s)
{
System.out.println("echo(" + s + ")");
return s;
}
}
117
Chapter 15. JBossWS-CXFWS-Rel...
<web-app
version="2.5" 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_2_5.xsd">
<servlet>
<servlet-name>SimpleService</servlet-name>
<servlet-
class>org.jboss.test.ws.jaxws.samples.wsrm.service.SimpleServiceImpl</
servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SimpleService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
cd $JBOSS_HOME/bin
./wsconsume.sh --keep \
--package=org.jboss.test.ws.jaxws.samples.wsrm.generated \
--output=/home/username/wsrm/cxf/wsconsume/generated/classes \
--source=/home/username/wsrm/cxf/wsconsume/generated/src \
/home/username/wsrm/cxf/wsprovide/generated/wsdl/SimpleService.wsdl
118
Writing Regular JAX-WS Client
# compiled classes
ls
/home/username/wsrm/cxf/wsconsume/generated/classes/org/jboss/test/ws/
jaxws/samples/wsrm/generated/
Echo.class ObjectFactory.class Ping.class
SimpleService_Service.class
EchoResponse.class package-info.class SimpleService.class
SimpleService_SimpleServicePort_Client.class
# java sources
ls
/home/username/wsrm/cxf/wsconsume/generated/src/org/jboss/test/ws/jaxws/
samples/wsrm/generated/
Echo.java ObjectFactory.java Ping.java
SimpleService_Service.java
EchoResponse.java package-info.java SimpleService.java
SimpleService_SimpleServicePort_Client.java
Now the last step is to write the regular JAX-WS client using generated artifacts.
package org.jboss.test.ws.jaxws.samples.wsrm.client;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService;
119
Chapter 15. JBossWS-CXFWS-Rel...
// invoke methods
proxy.ping(); // one way call
proxy.echo("Hello World!"); // request responce call
}
Now we have both endpoint and client implementation but without WSRM in place. Our next goal
is to turn on the WS-RM feature.
120
Extending WSDL Using WS-Policy
</wsdl:types>
<wsdl:message name="echoResponse">
<wsdl:part name="parameters" element="tns:echoResponse">
</wsdl:part>
</wsdl:message>
<wsdl:message name="echo">
<wsdl:part name="parameters" element="tns:echo">
</wsdl:part>
</wsdl:message>
<wsdl:message name="ping">
<wsdl:part name="parameters" element="tns:ping">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="SimpleService">
<wsdl:operation name="ping">
<wsdl:input name="ping" message="tns:ping">
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="echo">
<wsdl:input name="echo" message="tns:echo">
</wsdl:input>
<wsdl:output name="echoResponse" message="tns:echoResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="SimpleServiceSoapBinding" type="tns:SimpleService">
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!-- Created WS-Policy with WSRM addressing assertions -->
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - --><wsp:Policy>
<wswa:UsingAddressing
xmlns:wswa="http://www.w3.org/2006/05/addressing/wsdl"/>
<wsrmp:RMAssertion
xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"/>
</wsp:Policy>
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="ping">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="ping">
<soap:body use="literal"/>
</wsdl:input>
</wsdl:operation>
<wsdl:operation name="echo">
<soap:operation soapAction="" style="document"/>
<wsdl:input name="echo">
<soap:body use="literal"/>
</wsdl:input>
121
Chapter 15. JBossWS-CXFWS-Rel...
<wsdl:output name="echoResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="SimpleService">
<wsdl:port name="SimpleServicePort"
binding="tns:SimpleServiceSoapBinding">
<soap:address location="http://localhost:9090/hello"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
The endpoint advertises RM capabilities through the published wsdl and the client is required to
also enable WS-RM for successfully exchanging messages with the server.
The regular jaxws client above is enough if the user does not need to tune any specific detail of
the RM subsystem (acknowledgment / retransmission intervals, thresholds, ...)
Next step is to create the client CXF configuration file that will be used by client. The following
file was copied/pasted from CXF 2.0.5 ws_rm sample. It simply activates the WSRM protocol for
CXF client. We will name this file cxf.xml in our sample. Here's the content of this file:
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:wsa="http://cxf.apache.org/ws/addressing"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
122
Advanced WS-RM configuration
xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"
xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager"
xsi:schemaLocation="
http://cxf.apache.org/core
http://cxf.apache.org/schemas/core.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd
http://schemas.xmlsoap.org/ws/2005/02/rm/policy
http://schemas.xmlsoap.org/ws/2005/02/rm/wsrm-policy.xsd
http://cxf.apache.org/ws/rm/manager
http://cxf.apache.org/schemas/configuration/wsrm-manager.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<cxf:bus>
<cxf:features>
<cxf:logging/>
<wsa:addressing/>
<wsrm-mgr:reliableMessaging>
<wsrm-policy:RMAssertion>
<wsrm-policy:BaseRetransmissionInterval
Milliseconds="4000"/>
<wsrm-policy:AcknowledgementInterval
Milliseconds="2000"/>
</wsrm-policy:RMAssertion>
<wsrm-mgr:destinationPolicy>
<wsrm-mgr:acksPolicy intraMessageThreshold="0" />
</wsrm-mgr:destinationPolicy>
</wsrm-mgr:reliableMessaging>
</cxf:features>
</cxf:bus>
</beans>
And that's almost all. The client configuration needs to picked up by the client classloader; in order
to achieve that the cxf.xml file has to be put in the META-INF directory of client jar. That jar should
then be provided when setting the class loader.
package org.jboss.test.ws.jaxws.samples.wsrm.client;
import java.net.URL;
123
Chapter 15. JBossWS-CXFWS-Rel...
import java.io.File;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService;
// create service
QName serviceName = new
QName("http://www.jboss.org/jbossws/ws-extensions/wsrm", "SimpleService");
URL wsdlURL = new URL(serviceURL + "?wsdl");
Service service = Service.create(wsdlURL, serviceName);
SimpleService proxy =
(SimpleService)service.getPort(SimpleService.class);
// invoke methods
proxy.ping(); // one way call
proxy.echo("Hello World!"); // request responce call
// shutdown bus
bus.shutdown(true);
}
124
Chapter 16.
JBossWS-CXFJMStransporttutorial
JBossWS-CXF supports JMS Transport to transfer SOAP messages. There
is a testcase in the codebase to demonstrate this ability, available
here [http://anonsvn.jboss.org/repos/jbossws/stack/cxf/tags/jbossws-cxf-3.4.0.CR2/modules/
testsuite/cxf-spring-tests/src/test/java/org/jboss/test/ws/jaxws/samples/jmstransport/]. In this
tutorial, we will use a wsdl first web service example to show you how to enable this feature in
JBossWS.
16.1. WSDL
<wsdl:definitions name="OrganizationJMSEndpointService"
targetNamespace="http://org.jboss.ws/samples/jmstransport"
xmlns:jms="http://cxf.apache.org/transports/jms"
xmlns:ns1="http://schemas.xmlsoap.org/wsdl/soap/http"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://org.jboss.ws/samples/jmstransport"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:message name="getContactInfoResponse">
<wsdl:part name="return" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:message name="getContactInfo">
<wsdl:part name="arg0" type="xsd:string">
</wsdl:part>
</wsdl:message>
<wsdl:portType name="Organization">
<wsdl:operation name="getContactInfo">
<wsdl:input message="tns:getContactInfo" name="getContactInfo">
</wsdl:input>
<wsdl:output message="tns:getContactInfoResponse"
name="getContactInfoResponse">
</wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HTTPSoapBinding" type="tns:Organization">
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="getContactInfo">
<soap:operation soapAction="" style="rpc"/>
<wsdl:input name="getContactInfo">
<soap:body namespace="http://org.jboss.ws/samples/jmstransport"
use="literal"/>
125
Chapter 16. JBossWS-CXFJMStra...
</wsdl:input>
<wsdl:output name="getContactInfoResponse">
<soap:body namespace="http://org.jboss.ws/samples/jmstransport"
use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="OrganizationService">
<wsdl:port binding='tns:HTTPSoapBinding' name='HttpEndpointPort'>
<soap:address
location='http://@jboss.bind.address@:8080/jaxws-samples-jmstransport'/>
</wsdl:port>
<wsdl:port binding="tns:JMSSoapBinding" name="JmsEndpointPort">
<jms:address
destinationStyle="queue"
jndiConnectionFactoryName="ConnectionFactory"
jndiDestinationName="queue/RequestQueue"
jndiReplyDestinationName="queue/ResponseQueue">
>
</jms:address>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Apache CXF defines the jms wsdl extension, so the jms queue name or other information about
jms in wsdl port can be parsed to send or receive jms message. Check this wiki page to see what
jms attributes you can defined in WSDL. In this wsdl, we define two queues to send and receive
the soap message. CXF uses JNDI to look up the jms ConnectionFactory, so we may also need
to provide the JNDI properties as the following example :
126
Service Implementation
<jms:address
destinationStyle="queue"
jndiConnectionFactoryName="ConnectionFactory"
jndiDestinationName="queue/RequestQueue"
jndiReplyDestinationName="queue/ResponseQueue"
>
<jms:JMSNamingProperty name="java.naming.factory.initial"
value="org.jnp.interfaces.NamingContextFactory"/>
<jms:JMSNamingProperty name="java.naming.provider.url"
value="jnp://localhost:1099"/>
</jms:address>
After generated code from this wsdl , we wrote two class to implement this interface for this two
ports . We annotate the portName in annotation to tell web service stack which transport this
service uses :
@WebService (serviceName="OrganizationService",
portName="HttpEndpointPort",wsdlLocation =
"WEB-INF/wsdl/jmstransport.wsdl",targetNamespace =
"http://org.jboss.ws/samples/jmstransport", endpointInterface="org.jboss.test.ws.jaxws.sampl
@SOAPBinding(style = SOAPBinding.Style.RPC)
127
Chapter 16. JBossWS-CXFJMStra...
@WebService (serviceName="OrganizationService",portName="JmsEndpointPort",
wsdlLocation = "WEB-INF/wsdl/jmstransport.wsdl", targetNamespace =
"http://org.jboss.ws/samples/jmstransport", endpointInterface="org.jboss.test.ws.jaxws.sampl
@SOAPBinding(style = SOAPBinding.Style.RPC)
16.3. web.xml
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<servlet>
<servlet-name>OrganizationService</servlet-name>
<servlet-
class>org.jboss.test.ws.jaxws.samples.jmstransport.OrganizationHttpEndpoint</
servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>OrganizationService</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping></web-app>
128
jbossws-cxf.xml
It is almost the same as the usual web.xml to deploy a web service except the <load-on-startup>
servlet initializeparameter. This is for jms service start ready when deployment, no need to wait
until the first servlet request to start the jms endpoint.
16.4. jbossws-cxf.xml
In addition to web.xml, the jbossws-cxf.xml is needed to actually pass in cxf to start this two port.
<beans xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:beans='http://www.springframework.org/schema/beans'
xmlns:jms="http://cxf.apache.org/transports/jms"
xmlns:jaxws='http://cxf.apache.org/jaxws'
xsi:schemaLocation='http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.w3.org/2006/07/ws-policy
http://www.w3.org/2006/07/ws-policy.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/transports/jms
http://cxf.apache.org/schemas/configuration/jms.xsd'>
<import resource="classpath:META-INF/cxf/cxf-extension-jms.xml"/>
<jaxws:endpoint id='SOAPQueryService'
implementor='org.jboss.test.ws.jaxws.samples.jmstransport.OrganizationHttpEndpoint'
>
<jaxws:invoker>
<bean class='org.jboss.wsf.stack.cxf.InvokerJSE'/>
</jaxws:invoker>
</jaxws:endpoint>
<jaxws:endpoint id='JMSQueryService'
implementor='org.jboss.test.ws.jaxws.samples.jmstransport.OrganizationJmsEndpoint'
transportId="http://cxf.apache.org/transports/jms">
</jaxws:endpoint>
</beans>
Note: the import resource is the JmsTransportFactory configuration . It is required to jms transport
enablement .
129
Chapter 16. JBossWS-CXFJMStra...
Below gives the war file directory structure to make it more clear what inside :
|-- jmstransport-sample.war
`-- WEB-INF
|-- classes
| `-- org
| `-- jboss
| `-- test
| `-- ws
| `-- jaxws
| `-- samples
| `-- jmstransport
| |--
JMSTransportTestCase$ResponseListener.class
| |-- JMSTransportTestCase.class
| |-- Organization.class
| |-- OrganizationHttpEndpoint.class
| `-- OrganizationJmsEndpoint.class
|-- jboss-web.xml
|-- jbossws-cxf.xml
|-- web.xml
`-- wsdl
`-- jmstransport.wsdl
130
Chapter 17.
JBossWS-JAX-WSAnnotations
17.1.1. javax.xml.ws.ServiceMode
The ServiceMode annotation is used to specify the mode for a provider class, i.e. whether a
provider wants to have access to protocol message payloads (e.g. a SOAP body) or the entire
protocol messages (e.g. a SOAP envelope).
17.1.2. javax.xml.ws.WebFault
The WebFault annotation is used when mapping WSDL faults to Java exceptions, see section
2.5. It is used to capture the name of the fault element used when marshalling the JAXB type
generated from the global element referenced by the WSDL fault message. It can also be used
to customize the mapping of service specific exceptions to WSDL faults.
17.1.3. javax.xml.ws.RequestWrapper
The RequestWrapper annotation is applied to the methods of an SEI. It is used to capture the
JAXB generated request wrapper bean and the element name and namespace for marshalling
/ unmarshalling the bean. The default value of localName element is the operationName as defined
in WebMethod annotation and the default value for the targetNamespace element is the target
namespace of the SEI.When starting from Java, this annotation is used to resolve overloading
conflicts in document literal mode. Only the className element is required in this case.
17.1.4. javax.xml.ws.ResponseWrapper
131
Chapter 17. JBossWS-JAX-WSAnn...
annotation is used to resolve overloading conflicts in document literal mode. Only the className
element is required in this case.
17.1.5. javax.xml.ws.WebServiceClient
The WebServiceClient annotation is specified on a generated service class (see 2.7). It is used
to associate a class with a specific Web service, identify by a URL to a WSDL document and the
qualified name of a wsdl:service element.
17.1.6. javax.xml.ws.WebEndpoint
The WebEndpoint annotation is specified on the getPortName() methods of a generated service
class (see 2.7). It is used to associate a get method with a specific wsdl:port, identified by its local
name (a NCName).
17.1.7. javax.xml.ws.WebServiceProvider
The WebServiceProvider annotation is specified on classes that implement a strongly typed javax-
.xml.ws.Provider. It is used to declare that a class that satisfies the requirements for a provider
(see 5.1) does indeed define a Web service endpoint, much like the WebService annotation does
for SEI-based endpoints.
17.1.8. javax.xml.ws.BindingType
The BindingType annotation is applied to an endpoint implementation class. It specifies the binding
to use when publishing an endpoint of this type.
17.1.9. javax.xml.ws.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 [32]. The
WebServiceRef annotation is required to be honored when running on the Java EE 5 platform,
where it is subject to the common resource injection rules described by the platform specification
[33].
132
javax.xml.ws.WebServiceRefs
17.1.10. javax.xml.ws.WebServiceRefs
The WebServiceRefs annotation is used to declare multiple references to Web services on a
single class. It is necessary to work around the limition against specifying repeated annotations
of the same type on any given class, which prevents listing multiple javax.ws.WebServiceRef
annotations one after the other. This annotation follows the resource pattern exemplified by the
javax.annotation.Resources annotation in JSR-250.
Since no name and type can be inferred in this case, each WebServiceRef annotation inside
a WebServiceRefs MUST contain name and type elements with non-default values. The
WebServiceRef annotation is required to be honored when running on the Java EE 5 platform,
where it is subject to the common resource injection rules described by the platform specification.
17.1.11. javax.xml.ws.Action
The Action annotation is applied to the methods of a SEI. It used to generate the wsa:Action on
wsdl:input and wsdl:output of each wsdl:operation mapped from the annotated methods.
17.1.12. javax.xml.ws.FaultAction
The FaultAction annotation is used within the Action annotation to generate the wsa:Action
element on the wsdl:fault element of each wsdl:operation mapped from the annotated methods.
For details, see JSR 181 - Web Services Metadata for the Java Platform [http://jcp.org/en/jsr/
detail?id=181]
17.1.13.1. javax.jws.WebService
Marks a Java class as implementing a Web Service, or a Java interface as defining a Web Service
interface.
17.1.13.2. javax.jws.WebMethod
133
Chapter 17. JBossWS-JAX-WSAnn...
17.1.13.3. javax.jws.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. A JSR-181 processor is REQUIRED to report an error if an operation marked @Oneway
has a return value, declares any checked exceptions or has any INOUT or OUT parameters.
17.1.13.4. javax.jws.WebParam
Customizes the mapping of an individual parameter to a Web Service message part and XML
element.
17.1.13.5. javax.jws.WebResult
Customizes the mapping of the return value to a WSDL part and XML element.
17.1.13.6. javax.jws.SOAPBinding
Specifies the mapping of the Web Service onto the SOAP message protocol.
The SOAPBinding annotation has a target of TYPE and METHOD. The annotation may be placed
on a method if and only if the SOAPBinding.style is DOCUMENT. Implementations MUST report
an error if the SOAPBinding annotation is placed on a method with a SOAPBinding.style of RPC.
Methods that do not have a SOAPBinding annotation accept the SOAPBinding behavior defined
on the type.
17.1.13.7. javax.jws.HandlerChain
The @HandlerChain annotation associates the Web Service with an externally defined handler
chain.
The @HandlerChain annotation MAY be present on the endpoint interface and service
implementation bean. The service implementation bean's @HandlerChain is used if
@HandlerChain is present on both.
The @HandlerChain annotation MAY be specified on the type only. The annotation target includes
METHOD and FIELD for use by JAX-WS-2.0.
134