== Quick Start

JBossWS uses WildFly as its target container. The following examples
focus on web service features that leverage EJB3 service
implementations and the JAX-WS programming models. For further
information on POJO service implementations and advanced topics
consult the <<Jakarta XML Web Services User Guide>> .

=== Developing web service implementations

Jakarta XML Web Services leverages annotations in order to express web service meta data on Java components and to describe the mapping between Java data types and XML. When developing web service implementations one needs to decide whether to start with an abstract contract (WSDL) or a Java component.

It is common practice for a developer create the web service in Java
and use vendor tools to generate the corresponding WSDL.
For this reason we are going to look at a service implementation that leverages
https://jakarta.ee/specifications/web-services-metadata/[Jakarta Web Service Metadata] .


[IMPORTANT]
====
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

* https://jakarta.ee/specifications/web-services-metadata/[Jakarta Web Service Metadata]

* https://jakarta.ee/specifications/xml-binding[Jakarta XML Binding
(JAXB)]
* https://jakarta.ee/specifications/xml-web-services/[Jakarta XML Web Services]
====

==== The service implementation class

When starting from Java, a service (endpoint) implementation must be provided. A valid endpoint implementation class must meet the following
requirements:

* It _must_ carry a `jakarta.jws.WebService` annotation (see Jakarta Web Service Metadata)
* All method parameters and return types _must_ be compatible with the
JAXB 3.0

Let's look at a sample EJB3 component that exposes as a web service.

For now ignore the EJB3 annotation `@Stateless` . Focus on the `@WebService` annotation.

===== Implementing the service

....
package org.jboss.test.ws.jaxws.samples.retail.profile;

import jakarta.ejb.Stateless;
import jakarta.jws.WebService;
import jakarta.jws.WebMethod;
import jakarta.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);
   }
}
....

....
1. This endpoint is using a stateless session bean implementation
2. This web service has an explicit namespace, (http://org.jboss.ws/samples/retail/profile)
3. The endpoint is declared to use a doc/lit bare parameter style.  This affects the endpoint statements generated in the WSDL.
4. 'getCustomerDiscount' is the public operation that a consumer can call.
....

===== What about the payload?

The method parameters and return values represent the XML
payload, because this is a stateless session bean the parameters and return value must be compatible with JAXB3. No JAXB annotations are needed for this example.

....
package org.jboss.test.ws.jaxws.samples.retail.profile;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.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 {

   protected Customer customer;

   public DiscountRequest() {
   }

   public DiscountRequest(Customer customer) {
      this.customer = customer;
   }

   public Customer getCustomer() {
      return customer;
   }

   public void setCustomer(Customer value) {
      this.customer = value;
   }

}
....

....
1. @XmlType is used to declare an XML type named, discountRequest, and a namespace name, (http://org.jboss.ws/samples/retail/profile).
....

[NOTE]
====
For more complex XML mapping consult the
https://jakarta.ee/specifications/xml-binding[JAXB documentation] .
====

==== Deploying service implementations

Web service deployment depends on the implementation type. Web services can be implemented as plain old Java objects, POJO or as EJB3 components.

===== EJB3 services

Create a JAR containing the service implementation class, the endpoint interface and any custom data types needed.  Drop the JAR in the _deployment_ directory.  No additional deployment descriptors required. Any meta data
required for the deployment of the actual web service is taken from the
annotations provided in the implementation class and the service
endpoint interface. JBossWS intercepts the EJB3 deployment (the
bean will be there) and creates an HTTP endpoint at deploy-time.

===== The JAR package structure

jar -tf jaxws-samples-retail.jar

 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

[IMPORTANT]
====
If the deployment was successful you should be able to see your endpoint
in the application server management console.
====

=== Consuming web services

When creating web service clients, one usually starts from the WSDL, but deciphering the WSDL can be complicated.
JBossWS ships with a set of tools to generate the required JAX-WS
artifacts to build client implementations. The following section
looks at a basic usage pattern. For a more detailed
introduction to the web service client please consult the user guide.

==== Creating the client artifacts

===== Using wsconsume

The _wsconsume_ tool is used to consume the abstract contract (WSDL) and
produce annotated Java classes.
The following discussion starts with the WSDL from our retail example
(ProfileMgmtService.wsdl) above. For a detailed tool reference
consult the user guide.

....
wsconsume is a command line tool that generates
portable JAX-WS artifacts from a WSDL file.

usage: org.jboss.ws.tools.jaxws.command.wsconsume [options] <wsdl-url>

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
....

Let's try it on our sample:

....
~./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
....

[arabic]
. Note we used the `-p` switch to specify the package name
of the generated sources.

===== The generated artifacts explained

[cols=",",options="header",]
|===
|File |Purpose
|ProfileMgmt.java |Service Endpoint Interface
|Customer.java |Custom data type
|Discount*.java |Custom data type
|ObjectFactory.java |JAXB XML Registry
|package-info.java |Holder for JAXB package annotations
|ProfileMgmtService.java |Service factory
|===

_wsconsume_ generates all the custom data types (JAXB annotated
classes), the service endpoint interface and a service factory class.

==== Constructing a service stub

Web service clients make use of a service stub that hides the details of
a remote web service invocation. To a client application a WS invocation
looks like an invocation of any other business component. In this
case the service endpoint interface is the business interface.
JAX-WS does use a service factory class to construct this as particular
service stub:

....
import jakarta.xml.ws.Service;
[...]
Service service = Service.create(                                 (1)
new URL("http://example.org/service?wsdl"),
new QName("MyService")
);
ProfileMgmt profileMgmt = service.getPort(ProfileMgmt.class);     (2)

// do something with the service stub here...                     (3)
....

[arabic]
. Create a service factory using the WSDL location and the service name
. Use the tool created service endpoint interface to build the service
stub
. Use the stub like any other business interface


==== Resolving dependencies and running the client

To successfully run a WS client application, a classloader
needs to be properly setup to include the JBossWS components and its
required transitive dependencies. Depending on the environment the
client is run in, this might require adding some jars to the
classpath, or adding some artifact dependencies to the maven dependency
tree. Even for simply developing a client, users might
need to resolve proper dependencies (e.g. to setup their IDE).

Below you will find some options for resolving dependencies and running a WS
client using the JBossWS libraries:

===== Maven project

The JBossWS project is composed of multiple Maven artifacts that can be
used to declare dependencies in user Maven projects. In particular, the
`
              org.jboss.ws.cxf:jbossws-cxf-client
            ` artifact can be used for getting the whole JBossWS client
dependency. Users should simply add a dependency to it in their Maven
project and make sure JBossWS components (in particular
`org.jboss.ws.cxf:jbossws-cxf-factories` ) come before jars of any other
JAX-WS implementation in your classpath.

===== JBoss Modules environment

One approach for running a WS client is to leverage JBoss
Modules, creating a classloading environment equivalent to the
server container WS endpoints run in. This is achieved by using the
_jboss-modules.jar_ coming with WildFly as follows:

....
java -jar $WILDFLY_HOME/jboss-modules.jar -mp $WILDFLY_HOME/modules -jar client.jar
....

The _client.jar_ is meant to contain the WS client application and
include a _MANIFEST.MF_ file specifying the proper `Main-Class` as well
as <<JBoss Modules>> dependencies, for instance:

....
Manifest-Version: 1.0
Main-Class: org.jboss.test.ws.jaxws.jbws1666.TestClient
Dependencies: org.jboss.ws.cxf.jbossws-cxf-client
....

===== Flat classpath setup

Alternatively, users can setup their application classpath manually
(e.g when compiling and running the application directly through `javac`
/ `java` command or using `Ant` ).

=== Maven archetype quick start

A convenient approach to start a new project aiming at providing and/or
consuming a JAX-WS endpoint is to use the JBossWS _jaxws-codefirst_
Maven Archetype. A starting project (including working build and sample
helloworld client and endpoint) is created in few seconds. It's simply a
matter of issuing a command and answering several simple questions about the
desired artifact and group ids for the project being generated:

....
> mvn archetype:generate -Dfilter=org.jboss.ws.plugins.archetypes:
....

The generated project includes:

* a sample HelloWorld code-first POJO endpoint
* an integration test that gets the WSDL contract for the above service,
builds a client and invokes the endpoint
* a pom.xml for creating a war archive; the project has proper WS
component dependencies and uses both wsprovide and wsconsume maven
plugins for generating the contract for the code-first endpoint and then
generating the client stubs for such contract
* a plugin for deploying the archive on WildFly.

The project is built and tested by running:

....
> mvn wildfly:deploy
> mvn integration-test
....

The build processes the various plugins and calls into the JBossWS tools
to generate all the required classes for building the deployment archive
and client. The user can test the sample, have a look at the project
structure and then either trash the sample endpoint and testcase and
replace them with his own components, or modify them step-by-step to
achieve their own needs.

=== Appendix

==== Sample wsdl contract

....
<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>
               <xs:element minOccurs='0' name='customer' type='ns1:customer'/>
               <xs:element name='discount' type='xs:double'/>
            </xs:sequence>
         </xs:complexType>
      </xs:schema>

   </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>
....
