Webservices with JAX-WS

This document is referring to a past Scout release. Please click here for the recent version.

The Java API for XML-Based Web Services (JAX-WS) is a Java programming language API for creating web services. JAX-WS is one of the Java XML programming APIs, and is part of the Java EE platform.

Scout facilitates working with webservices, supports you in the generation of artifacts, and provides the following functionality:

Functionality

  • ready to go Maven profile for easy webservice stub and artifact generation

  • full JAX-WS 2.3 compliance

  • JAX-WS implementor independence

  • provides an up front port type EntryPoint to enforce for authentication, and to run web requests in a RunContext

  • adds cancellation support for on-going webservice requests

  • provides a port cache for webservice consumers

  • allows to participate in 2PC protocol for webservice consumers

  • allows to provide 'init parameters' to handlers

JAX-WS implementor and deployment

JAX-WS version and implementor

The JAX-WS Scout integration provides a thin layer on top of JAX-WS implementors to facilitate working with webservices. It depends on the JAX-WS 2.3.x API as specified in JSR 224. It is implementor neutral, and was tested with with the following implementations:

  • JAX-WS RI (reference implementation)

  • JAX-WS METRO

  • Apache CXF

The integration requires you to bundle the JAX-WS implementor with your application. When publishing webservices, it therefore is easiest to ship with a separate implementor: Declare a respective Maven dependency in your webapp project - that is the Maven module ending in .app.

Configure JAX-WS implementor

JAX-WS Scout integration is prepared to run with different implementors. Unfortunately, some implementors do not implement the JSR exactly, or some important functionality is missing in the JSR. To address this fact without loosing implementor independence, the delegate bean JaxWsImplementorSpecifics exists.

As of now, Scout ships with three such implementor specific classes, which are activated via config.properties by setting the property scout.jaxws.implementor with its fully qualified class name. By default, JAX-WS METRO implementor is installed.

For instance, support for Apache CXF implementor is activated as following:

scout.jaxws.implementor=org.eclipse.scout.rt.server.jaxws.implementor.JaxWsCxfSpecifics
class description

JaxWsRISpecifics

implementor specifics for JAX-WS Reference Implementation (RI) as contained in JRE

JaxWsMetroSpecifics

implementor specifics for JAX-WS METRO implementation

JaxWsCxfSpecifics

implementor specifics for Apache JAX-WS CXF implementation

Of course, other implementors can be used as well. For that to work, install your own JaxWsImplementorSpecifics class, and reference its fully qualified name in config.properties.

JaxWsImplementorSpecifics

This class encapsulates functionality that is defined in JAX-WS JSR 224, but may diverge among JAX-WS implementors. As of now, the following points are addressed:

  • missing support in JSR to set socket connect and read timeout;

  • proprietary 'property' to set response code in Apache CXF;

  • when working with Apache CXF, response header must be set directly onto Servlet Response, and not via MessageContext;

  • when working with JAX-WS METRO or JAX-WS RI, the handler’s return value is ignored in one-way communication; instead, the chain must be exited by throwing a webservice exception;

Learn more about how to configure a JAX-WS implementor: Configure JAX-WS implementor

Configure JAX-WS Maven dependency in pom.xml

The effective dependency to the JAX-WS implementor is to be specified in the pom.xml of the webapp module (i.e. .app, not the server module).

A generally applicable configuration cannot be given, because the effective configuration depends on the implementor you choose. However, if JAX-WS RI is sufficient, you do not have to specify an implementor at all because already contained in JRE.

Listing 1 provides sample configuration for shipping with JAX_WS METRO and Listing 2 does the same for Apache CXF

Listing 1. Maven dependency for JAX-WS METRO
<!-- JAX-WS METRO not bundled with JRE -->
<dependency>
  <groupId>com.sun.xml.ws</groupId>
  <artifactId>jaxws-rt</artifactId>
  <version>...</version>
</dependency>
Listing 2. Maven dependency for Apache CXF
<!-- JAX-WS Apache CXF -->
<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-frontend-jaxws</artifactId>
  <version>...</version>
</dependency>
<dependency>
  <groupId>org.apache.cxf</groupId>
  <artifactId>cxf-rt-transports-http</artifactId>
  <version>...</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-web</artifactId>
  <version>...</version>
</dependency>

Configure JAX-WS servlet

This section describes the configuration of the entry point Servlet to publish webservices. If working with webservice consumers only, no configuration is required.

Similar to the pom.xml as described in Configure JAX-WS Maven dependency in pom.xml, the way the servlet needs to be registered differs from implementor to implementor. The following Listing 3 show a sample configuration for JAX-WS METRO and Listing 4 for Apache CXF.

Listing 3. Registration for JAX-WS METRO Servlet
@Order(5)
public static class WSServletContextListenerFilterContributor implements IServletFilterContributor {

  @Override
  public void contribute(ServletContextHandler handler) {
    handler.addEventListener(new WSServletContextListener());
  }
}

/**
 * JAX-WS Metro.
 */
@Order(10)
public static class JaxWsServletServletContributor implements IServletContributor {

  @Override
  public void contribute(ServletContextHandler handler) {
    // JAX-WS METRO not bundled with JRE
    handler.setInitParameter("com.sun.xml.ws.server.http.publishStatusPage", "true");
    handler.setInitParameter("com.sun.xml.ws.server.http.publishWSDL", "true");

    ServletHolder servlet = handler.addServlet(WSServlet.class, "/jaxws/*"); (1)
    servlet.setInitOrder(1); // load-on-startup
  }
}
1 the base URL where to publish the webservice endpoints
Listing 4. Registration for Apache CXF Servlet
/**
 * JAX-WS Apache CXF.
 */
@Order(10)
public static class JaxWsServletServletContributor implements IServletContributor {

  @Override
  public void contribute(ServletContextHandler handler) {
    ServletHolder servlet = handler.addServlet(CXFServlet.class, "/jaxws/*"); (2)
    servlet.setInitParameter("config-location", "/WEB-INF/cxf-jaxws.xml"); (1)
    servlet.setInitOrder(1); // load-on-startup
  }
}
1 Apache CXF specific configuration file for endpoints to be published. See Apache CXF for more information.
2 the base URL where to publish the webservice endpoints
Do not forget to exclude the webservice’s Servlet URL pattern from authentication filter.

Modularization

Scout JAX-WS integration does not prescribe how to organize your webservices in terms of Maven modules. You could either put all your webservices directly into the server module, or create a separate jaxws module containing all webservices, or even create a separate jaxws module for each webservice. Most often, the second approach of a single, separate jaxws module, which the server module depends on, is chosen.

This is mainly because of the following benefits:

  • annotation processing must not be enabled for the entire server module

  • one module to build all webservice artifacts at once

  • easier to work with shared element types among webservices

jaxws modularization
Figure 1. typical modularization

It is important to note, that the server depends on the jaxws module, and not vice versa. The jaxws module is primarily of technical nature, meaning that it knows how to generate its WS artifacts, and also contains those. However, implementing port type beans and even implementing handler beans are typically put into the server module to the access service and database layer. On the other hand, WS clients may be put into jaxws module, because they rarely contain any project specific business logic.

You may ask yourself, how the jaxws module can access the implementing port type and handlers located in the server module. That works because of the indirection via bean manager, and because there is a flat classpath at runtime.

See WebServiceEntryPoint for more information.

Build webservice stubs and artifacts

Configure webservice stub generation via wsimport

The Maven plugin 'com.sun.xml.ws:jaxws-maven-plugin' with the goal 'wsimport' is used to generate a webservice stub from a WSDL file and its referenced XSD schema files. If your Maven module inherits from the Scout module 'maven_rt_plugin_config-master', the 'jaxws' profile is available, which activates automatically upon the presence of a 'WEB-INF/wsdl' folder. Instead of inheriting from that module, you can alternatively copy the 'jaxws' profile into your projects parent POM module.

This profile is for convenience purpose, and provides a ready-to-go configuration to generate webservice stubs and webservice provider artifacts. It configures the 'jaxws-maven-plugin' to look for WSDL and XSD files in the folder 'src/main/resources/WEB-INF/wsdl', and for binding files in the folder '/src/main/resources/WEB-INF/binding'. Upon generation, the stub will be put into the folder 'target/generated-sources/wsimport'.

The profiles requires the Scout runtime version to be specified, and which is used to refer to org.eclipse.scout.jaxws.apt module to generate webservice provider artifacts. However, this version is typically defined in pom.xml of the parent module, because also used to refer to other Scout runtime artifacts.

Listing 5. Scout version defined as Maven property
<properties>
  <org.eclipse.scout.rt.version>5.2.0-SNAPSHOT</org.eclipse.scout.rt.version>
</properties>

If your project design envisions a separate JAR module per WSDL, you simply have to set the property 'jaxws.wsdl.file' with the name of your WSDL file in the module’s pom.xml (example in Listing 6).

Listing 6. wsimport configuration in pom.xml if working with a single WSDL file per JAR module
<properties>
  <jaxws.wsdl.file>YourWebService.wsdl</jaxws.wsdl.file> (1)
</properties>
1 name of the wsdl file

Otherwise, if having multiple WSDL files in your JAR module, some little more configuration is required, namely a respective execution section per WSDL file. Thereby, the 'id' of the execution section must be unique. Scout 'jaxws' profile already provides one such section, which is used to generate the stub for a single WSDL file (see such configuration in Listing 6), and names it 'wsimport-1'. It is simplest to name the subsequent execution sections 'wsimport-2', 'wsimport-3', and so on.
For each execution section, you must configure its unique id, the goal 'wsimport', and in the configuration section the respective wsdlLocation and wsdlFile. For 'wsimport' to work, wsdlLocation is not required. However, that location will be referenced in generated artifacts to set the wsdl location via @WebService and @WebServiceClient. The complete configuration is presented in Listing 7.

If you decide to configure multiple WSDL files in your POM as described in Listing 7, the configuration defined in the parent POM (maven_rt_plugin_config-master) and expecting a configuration as presented in Listing 6 needs to be overridden, therefore one of your execution id needs to be wsimport-1.
Listing 7. wsimport configuration in pom.xml if working with multiple WSDL files per JAR module
<build>
  <plugins>
    <plugin>
      <groupId>com.sun.xml.ws</groupId>
      <artifactId>jaxws-maven-plugin</artifactId>
      <executions>
        <!-- YourFirstWebService.wsdl -->
        <execution> (1)
          <!-- DO NOT CHANGE THE ID: 'wsimport-1';
               it overrides an execution defined in the parent pom -->
          <id>wsimport-1</id> (2)
          <goals>
            <goal>wsimport</goal> (3)
          </goals>
          <configuration>
            <wsdlLocation>WEB-INF/wsdl/YourFirstWebService.wsdl</wsdlLocation> (4)
            <wsdlFiles>
              <wsdlFile>YourFirstWebService.wsdl</wsdlFile> (5)
            </wsdlFiles>
          </configuration>
        </execution>

        <!-- YourSecondWebService.wsdl -->
        <execution> (6)
          <id>wsimport-2</id>
          <goals>
            <goal>wsimport</goal>
          </goals>
          <configuration>
            <wsdlLocation>WEB-INF/wsdl/YourSecondWebService.wsdl</wsdlLocation>
            <wsdlFiles>
              <wsdlFile>YourSecondWebService.wsdl</wsdlFile>
            </wsdlFiles>
          </configuration>
        </execution>

        ...

      </executions>
    </plugin>
  </plugins>
</build>
1 declare an execution section for each WSDL file
2 give the section a unique id (wsimport-1, wsimport-2, wsimport-3, …​)
3 specify the goal 'wsimport' to build the webservice stub
4 specify the project relative path to the WSDL file
5 specify the relative path to the WSDL file (relative to 'WEB-INF/wsdl')
6 declare an execution section for the next WSDL file

Further, you can overwrite any configuration as defined by 'jaxws-maven-plugin'. See http://www.mojohaus.org/jaxws-maven-plugin/ for supported configuration properties.

Also, it is good practice to create a separate folder for each WSDL file, which also contains all its referenced XSD schemas. Then, do not forget to change the properties wsdlLocation and wsdlFile accordingly.

Customize WSDL components and XSD schema elements via binding files

By default, all XML files contained in folder 'WEB-INF/binding' are used as binding files. But, most often, you will have a global binding file, which applies to all your WSDL files, and some custom binding files different per WSDL file and XSD schema files. See how to explicitly configure binding files in Listing 8.

Listing 8. explicit configuration of binding files
<!-- YourFirstWebService.wsdl -->
<execution>
  ...
  <configuration>
    ...
    <bindingFiles>
      <bindingFile>global-bindings.xml</bindingFile> (1)
      <bindingFile>your-first-webservice-ws-bindings.xml</bindingFile> (2)
      <bindingFile>your-first-webservice-xs-bindings.xml</bindingFile> (3)
    </bindingFiles>
  </configuration>
</execution>

<!-- YourSecondWebService.wsdl -->
<execution>
  ...
  <configuration>
    ...
    <bindingFiles>
      <bindingFile>global-bindings.xml</bindingFile> (1)
      <bindingFile>your-second-webservice-ws-bindings.xml</bindingFile> (2)
      <bindingFile>your-second-webservice-xs-bindings.xml</bindingFile> (3)
    </bindingFiles>
  </configuration>
</execution>
1 global binding file which applies to all XSD schema elements. See Listing 9 for an example.
2 custom binding file to customize the webservice’s WSDL components in the namespace http://java.sun.com/xml/ns/jaxws. See Listing 10 for an example.
3 custom binding file to customize the webservice’s XSD schema elements in the namespace http://java.sun.com/xml/ns/jaxb. See Listing 11 for an example.

With binding files in place, you can customize almost every WSDL component and XSD element that can be mapped to Java, such as the service endpoint interface class, packages, method name, parameter name, exception class, etc.

The global binding file typically contains some customization for common data types like java.util.Date or java.util.Calendar, whereas the custom binding files are specific for a WSDL or XSD schema. See XML adapters to work with java.util.Date and java.util.Calendar.

Listing 9. example of global binding file in the namespace http://java.sun.com/xml/ns/jaxb
<bindings version="2.0"
  xmlns="http://java.sun.com/xml/ns/jaxb"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
  <globalBindings>
    <xjc:javaType
      name="java.util.Date"
      xmlType="xsd:date"
      adapter="org.eclipse.scout.rt.server.jaxws.adapter.UtcDateAdapter" />
    <xjc:javaType
      name="java.util.Date"
      xmlType="xsd:time"
      adapter="org.eclipse.scout.rt.server.jaxws.adapter.UtcTimeAdapter" />
    <xjc:javaType
      name="java.util.Date"
      xmlType="xsd:dateTime"
      adapter="org.eclipse.scout.rt.server.jaxws.adapter.UtcDateTimeAdapter" />
  </globalBindings>
</bindings>

By default, generated artifacts are put into the package corresponding to the element’s namespace. Sometimes, you like to control the package names, but you want to do that on a per-namespace basis, and not put all the artifacts of a webservice into the very same package. That is mainly to omit collisions, and to have artifacts shared among webservices not duplicated.

Two separate binding files are required to customize WSDL components and XSD schema elements.
That is because WSDL component customization is to be done in 'jaxws' namespace http://java.sun.com/xml/ns/jaxws, whereas XSD schema element customization in 'jaxb' namespace http://java.sun.com/xml/ns/jaxb.

Listing 10. example of jaxws component customization in the namespace http://java.sun.com/xml/ns/jaxws
<!-- binding to customize webservice components (xmlns=http://java.sun.com/xml/ns/jaxws) -->
<bindings xmlns="http://java.sun.com/xml/ns/jaxws"> (1)
    <package name="org.eclipse.ws.yourfirstwebservice"/> (2)
</bindings>
1 customization via jaxws namespace: http://java.sun.com/xml/ns/jaxws
2 instructs to put all webservice components (port type, service) into package org.eclipse.ws.yourfirstwebservice
Listing 11. example of xsd schema element customization in the namespace http://java.sun.com/xml/ns/jaxb
<!-- binding to customize xsd schema elements (xmlns=http://java.sun.com/xml/ns/jaxb) -->
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"> (1)
  <!-- namespace http://eclipse.org/public/services/ws/soap  -->
  <bindings scd="x-schema::tns" xmlns:tns="http://eclipse.org/public/services/ws/soap">
    <schemaBindings>
      <package name="org.eclipse.ws.yourfirstwebservice" /> (2)
    </schemaBindings>
  </bindings>

  <!-- namespace http://eclipse.org/public/services/ws/common/soap -->
  <bindings scd="x-schema::tns" xmlns:tns="http://eclipse.org/public/services/ws/common/soap">
    <schemaBindings>
      <package name="org.eclipse.ws.common" /> (3)
    </schemaBindings>
  </bindings>
</bindings>
1 customization via jaxb namespace: http://java.sun.com/xml/ns/jaxb
2 instructs to put all XSD schema elements in namespace http://eclipse.org/public/services/ws/soap into package org.eclipse.ws.yourfirstwebservice
3 instructs to put all XSD schema elements in namespace http://eclipse.org/public/services/ws/common/soap into package org.eclipse.ws.common
wsimport allows to directly configure the package name for files to be generated (packageName). However, this is discouraged, because all artifacts are put into the very same package. Use package customization on a per-namespace basis instead.
For shared webservice artifacts, you can also use XJC binding compiler to generate those artifacts in advance, and then provide the resulting episode binding file (META-INF/sun-jaxb.episode) to wsimport. See https://www.mojohaus.org/jaxb2-maven-plugin/Documentation/v2.4/example_xjc_basic.html for more information.

Annotation Processing Tool (APT)

Annotation Processing (APT) is a tool which can be enabled to fire for annotated types during compilation. In JAX-WS Scout integration, it is used as a trigger to generate webservice port type implementations. Such an auto-generated port type implementation is called an entry point. It is to be published as the webservice’s endpoint, and acts as an interceptor for webservice requests. It optionally enforces for authentication, and makes the request to be executed in a RunContext. Then, it handles the web request to the effectively implementing port type bean for actual processing.

The entry point generated simplifies the actual port type implementation by removing lot of glue code to be written by hand otherwise. Of course, this entry point is just for convenience purpose, and it is up to you to make use of this artifact.

When using 'jaxws' Scout Maven profile, annotation processing is enabled for that module by default. But, an entry point for a webservice port type will only be generated if enabled for that port type, meaning that a class annotated with WebServiceEntryPoint pointing to that very endpoint interface is found in this module. Anyway, for a sole webservice consumer, it makes no sense to generate an entry point at all.

Enable Annotation Processing Tool (APT) in Eclipse IDE

In Eclipse IDE, the workspace build ignores annotation processing as configured in pom.xml. Instead, it must be enabled separately with the following files. Nevertheless, to simply run Maven build with annotation support from within Eclipse IDE, those files are not required.

file description

.settings/org.eclipse.jdt.core.prefs

Enables APT for this module via the property org.eclipse.jdt.core.compiler.processAnnotations=enabled

.settings/org.eclipse.jdt.apt.core.prefs

Enables APT for this module via the property org.eclipse.jdt.apt.aptEnabled=true

.factorypath

Specifies the annotation processor to be used (JaxWsAnnotationProcessor) and dependent artifacts

Build webservice stubs and APT artifacts from console

Simply run mvn clean compile on the project. If you are experiencing some problems, run with -X debug flag to get a more detailed error message.

Build webservice stubs and APT artifacts from within Eclipse IDE

In the Eclipse IDE, there are three ways to generate webservice stubs and APT artifacts.

  1. the implicit way on behalf of the workspace build and m2e integration (automatically, but sometimes not reliable)

  2. the explicit but potentially slow way by doing a 'Update Maven Project' with 'clean projects' checked (Alt+F5)

  3. the explicit and faster way by running a Maven build for that project. Thereto, right-click on the project or pom.xml, then select the menu 'Run As | Maven build…​', then choose 'clean compile' as its goal and check 'Resolve workspace artifacts', and finally click 'Run'. Afterwards, do not forget to refresh the project by pressing F5.

If the webservice stub(s) or APT artifacts are not generated (anew or at all), delete the target folder manually, and continue according to procedure number three. A possible reason might be the presence of 'target\jaxws\wsartifact-hash'. Then, for each webservice, a 'hash file' is computed by 'wsimport', so that regeneration only occurs upon a change of WSDL or XSD files.

Exclude derived resources from version control

Stub and APT artifacts are derived resources, and should be excluded from version control. When working with Eclipse IDE, this is done automatically by eGit, because it adds derived resources to .gitignore (if configured to do so).

JaxWsAnnotationProcessor

JaxWsAnnotationProcessor is an annotation processor provided by Scout JAX-WS integration to generate an entry point for an endpoint interface during compilation. The instructions how to generate the entry point is given via a Java class or Java interface annotated with WebServiceEntryPoint annotation.

Provide a webservice

In this chapter, you will learn how to publish a webservice provider via an entry point.

The concept of an Entry Point

An entry point implements the endpoint interface (or port type interface), and is published as the webservice endpoint for that endpoint interface. The entry point itself is auto generated by JaxWsAnnotationProcessor during compile time, based on instructions as given by the respective class/interface annotated with WebServiceEntryPoint annotation. The entry point is responsible to enforce authentication and to run the web request in a RunContext. In turn, the request is propagated to the bean implementing the endpoint interface.

Figure 2 illustrates the endpoint’s class hierarchy and the message flow for a web request.

jaxws interaction entrypoint porttype
Figure 2. Interaction of entry point and port type

As you can see, both, entry point and port type implement the endpoint interface. But it is the entry point which is actually installed as the webservice endpoint, and which receives web requests. However, the webservice itself is implemented in the implementing bean, which typically is located in server module. See Modularization for more information. Upon a web request, the entry point simply intercepts the web request, and then invokes the web method on the implementing bean for further processing.

See an example of an implementing port type bean, which is invoked by entry point.

Do not forget to annotate the implementing bean with ApplicationScoped annotation in order to be found by bean manager.

Generate an Entry Point as an endpoint interface

This section describes the steps required to generate an entry point. For demonstration purposes, a simple ping webservice is used, which provides a single method 'ping' to accept and return a String object.

See the WSDL file of ping webservice: PingWebService.wsdl
See the endpoint interface of ping webservice: PingWebServicePortType.java

To generate an entry point for the webservice’s endpoint interface, create an interface as following in your jaxws project.

@WebServiceEntryPoint(endpointInterface = PingWebServicePortType.class) (2)
interface PingWebServiceEntryPointDefinition { (1)
}
1 Create an interface or class to act as an anchor for the WebServiceEntryPoint annotation. This class or interface has no special meaning, except that it declares the annotation to be interpreted by annotation processor.
2 Reference the endpoint interface for which an entry point should be generated for. Typically, the endpoint interface is generated by 'wsimport' and is annotated with WebService annotation.

It is important to understand, that the interface PingWebServiceEntryPointDefinition solely acts as the anchor for the WebServiceEntryPoint annotation. This class or interface has no special meaning, except that it declares the annotation to be interpreted by annotation processor. Typically, this class is called Entry Point Definition.

If running mvn clean compile, an entry point is generated for that endpoint interface. See the entry point as generated for ping webservice: PingWebServicePortTypeEntryPoint.java

If you should experience some problems in the entry point generation, refer to Build webservice stubs and APT artifacts from within Eclipse IDE, or Build webservice stubs and APT artifacts from console.

Instrument the Entry Point generation

This section gives an overview on how to configure the entry point to be generated.

attribute description

endpointInterface
(mandatory)

Specifies the endpoint interface for which to generate an entry point for.
An endpoint interface defines the service’s abstract webservice contract, and is also known as port type interface. Also, the endpoint interface is annotated with WebService annotation.

entryPointName

Specifies the class name of the entry point generated. If not set, the name is like the name of the endpoint interface suffixed with EntryPoint.

entryPointPackage

Specifies the package name of the entry point generated. If not set, the package name is the same as of the element declaring this WebServiceEntryPoint annotation.

serviceName

Specifies the service name as declared in the WSDL file, and must be set if publishing the webservice via auto discovery in an EE container. Both, 'serviceName' and 'portName' uniquely identify a webservice endpoint to be published.
See for valid service names in the WSDL: <wsdl:service name="SERVICE_NAME">…​</wsdl:service>

portName

Specifies the name of the port as declared in the WSDL file, and must be set if publishing the webservice via auto discovery in an EE container. Both, 'serviceName' and 'portName' uniquely identify a webservice endpoint to be published.
See for valid port names in the WSDL: <wsdl:service name="…​"><wsdl:port name="PORT_NAME" binding="…​"/></wsdl:service>

wsdlLocation

Specifies the location of the WSDL document. If not set, the location is derived from WebServiceClient annotation which is typically initialized with the 'wsdlLocation' as provided to 'wsimport'.

authentication

Specifies the authentication mechanism to be installed, and in which RunContext to run authenticated requests. By default, authentication is disabled. If enabled, an AuthenticationHandler is generated and registered in the handler chain as very first handler. However, the position of that handler can be changed via order field on Authentication annotation.
See Configure Authentication for more information.

handlerChain

Specifies the handlers to be installed. The order of the handlers is as declared. A handler is looked up as a bean, and must implement jakarta.xml.ws.handler.Handler interface.
See Configure JAX-WS Handlers for more information.

Besides the instructions which can be set via WebServiceEntryPoint annotation, it is further possible to contribute other annotations to the entry point. Simply declare the annotation of your choice as a sibling annotation to WebServiceEntryPoint annotation. In turn, this annotation will be added to the entry point as well. This may be useful to enable some vendor specific features, or e.g. to enable MTOM to efficiently send binary data to a client.
That also applies for WebService annotation to overwrite values as declared in the WSDL file.

Further, you can also provide your own handler chain binding file. However, handlers and authentication as declared via WebServiceEntryPoint annotation are ignored then.

Handlers registered via handlerChain must be beans, meaning either annotated with @Bean or @ApplicationScoped.
The binding to the concrete endpoint is done via 'endpointInterface' attribute. If a WSDL declares multiple services, create a separate entry point definition for each service to be published.
Annotate the Entry Point Definition class with `IgnoreWebServiceEntryPoint' to not generate an entry point for that definition. This is primarily used while developing an entry point, or for documenting purpose.
Some fields require you to provide a Java class. Such fields are mostly of the annotation type Clazz, which accepts either the concrete Class, or its 'fully qualified name'. Use the latter if the class is not visible from within jaxws module.
However, if ever possible specify a Class. Because most classes are looked up via bean manager, this can be achieved with an interface located in 'jaxws' module, but with an implementation in 'server' module.

Configure Authentication

The field 'authentication' on WebServiceEntryPoint configures what authentication mechanism to install on the webservice endpoint, and in which RunContext to run authenticated webservice requests. It consists of the IAuthenticationMethod to challenge the client to provide credentials, and the ICredentialVerifier to verify request’s credentials against a data source.

By default, authentication is disabled. If enabled, an AuthenticationHandler is generated and registered in the handler chain as very first handler. The position can be changed via order field on Authentication annotation.

The following properties can be set.

method
(mandatory)

Specifies the authentication method to be used to challenge the client to provide credentials. By default, NullAuthenticationMethod is used to disable authentication.
See IAuthenticationMethod for more information.

verifier

Specifies against which data source credentials are to be verified. By default, ForbiddenCredentialVerifier is used to reject any webservice request.
See ICredentialVerifier for more information.

order

Specifies the position where to register the authentication handler in the handler chain. By default, it is registered as the very first handler.

principalProducer

Indicates the principal producer to use to create principals to represent authenticated users. By default, SimplePrincipalProducer is used.

runContextProducer

Indicates which RunContext to use to run authenticated webservice requests. By default, ServerRunContextProducer is used, which is based on a session cache, and enforces to run in a new transaction.

If using container based authentication (authentication enforced by the application server), use ContainerBasedAuthenticationMethod as authentication method, and do not configure a credential verifier.

Example of an Entry Point definition

Listing 12. Example configuration for an entry point definition
@WebServiceEntryPoint(
    endpointInterface = PingWebServicePortType.class, (1)
    entryPointName = "PingWebServiceEntryPoint",
    entryPointPackage = "org.eclipse.scout.docs.ws.ping",
    serviceName = "PingWebService",
    portName = "PingWebServicePort",
    handlerChain = {(2)
        @Handler(@Clazz(CorrelationIdHandler.class)), (3)
        @Handler(value = @Clazz(IPAddressFilter.class), initParams = { (4)
            @InitParam(key = "rangeFrom", value = "192.200.0.0"),
            @InitParam(key = "rangeTo", value = "192.255.0.0")}),
        @Handler(@Clazz(LogHandler.class)), (5)
    },
    authentication = @Authentication( (6)
        order = 2, (7)
        method = @Clazz(BasicAuthenticationMethod.class), (8)
        verifier = @Clazz(ConfigFileCredentialVerifier.class))) (9)
@MTOM (10)
1 References the endpoint interface for which to generate an entry point for.
2 Declares the handlers to be installed on that entry point. The order is as declared.
3 Registers the 'CorrelationIdHandler' as the first handler to set a correlation ID onto the current message context. See Propagate state among Handlers and port type for more information about state propagation.
4 Registers the 'IpAddressFilter' as the second handler to filter for IP addresses. Also, this handler is parameterized with 'init params' to configure the valid IP range.
5 Registers the LogHandler as the third handler to log SOAP messages.
6 Configures the webservice’s authentication.
7 Configures the 'AuthHandler' to be put at position 2 (0-based), meaning in between of IpAddressFilter and LogHandler. By default, AuthHandler would be the very first handler in the handler chain.
8 Configures to use BASIC AUTH as authentication method.
9 Configures to verify user’s credentials against 'config.properties' file.
10 Specification of an MTOM annotation to be added to the entry point.

This configuration generates the following artifacts:

jaxws example pingws artifacts generated
Figure 3. generated artifacts

All artifacts are generated into the package 'org.eclipse.scout.docs.ws.ping', as specified by the definition. The entry point itself is generated into 'PingWebServiceEntryPoint.java'. Further, for each handler, a respective handler delegate is generated. That allows handlers to be looked up via bean manager, and to run the handlers on behalf of a RunContext. Also, an AuthHandler is generated to authenticate web requests as configured.

The handler-chain XML file generated looks as following. As specified, the authentication handler is installed as the third handler.

Listing 13. PingWebServiceEntryPoint_handler-chain.xml
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
  <handler-chain>
    <!-- Executed as 4. handler-->
    <handler>
      <handler-class>org.eclipse.scout.docs.ws.ping.PingWebServiceEntryPoint_LogHandler</handler-class>
    </handler>
  </handler-chain>
  <handler-chain>
    <!-- Executed as 3. handler-->
    <handler>
      <handler-class>org.eclipse.scout.docs.ws.ping.PingWebServiceEntryPoint_AuthHandler</handler-class>
    </handler>
  </handler-chain>
  <handler-chain>
    <!-- Executed as 2. handler-->
    <handler>
      <handler-class>org.eclipse.scout.docs.ws.ping.PingWebServiceEntryPoint_IPAddressFilter</handler-class>
    </handler>
  </handler-chain>
  <handler-chain>
    <!-- Executed as 1. handler-->
    <handler>
      <handler-class>org.eclipse.scout.docs.ws.ping.PingWebServiceEntryPoint_CorrelationIdHandler</handler-class>
    </handler>
  </handler-chain>
</handler-chains>

The following listing shows the beginning of the entry point generated. As you can see, the handler-chain XML file is referenced via HandlerChain annotation, and the MTOM annotation was added as well.

Listing 14. PingWebServiceEntryPoint.java
@WebService(name = "PingWebServicePortType",
    targetNamespace = "http://scout.eclipse.org/docs/ws/PingWebService/",
    endpointInterface = "org.eclipse.scout.docs.snippets.JaxWsSnippet.PingWebServicePortType",
    serviceName = "PingWebService",
    portName = "PingWebServicePort")
@MTOM
@HandlerChain(file = "PingWebServiceEntryPoint_handler-chain.xml")
public class PingWebServiceEntryPoint implements PingWebServicePortType {

Configure JAX-WS Handlers

See listing for an example of how to configure JAX-WS handlers.

JAX-WS handlers are configured directly on the entry point definition via the array field handlerChain. In turn, JaxWsAnnotationProcessor generates a 'handler XML file' with the handler’s order preserved, and which is registered in entry point via annotation handlerChain.

A handler can be initialized with static 'init parameters', which will be injected into the handler instance. For the injection to work, declare a member of the type Map in the handler class, and annotate it with jakarta.annotation.Resource annotation.

Because handlers are looked up via bean manager, a handler must be annotated with ApplicationScoped annotation.

If a handler requires to be run in a RunContext, annotate the handler with RunWithRunContext annotation, and optionally specify a RunContextProducer. If the web request is authenticated upon entering the handler, the RunContext is run on behalf of the authenticated user. Otherwise, if not authenticated yet, it is invoked with the Subject as configured in scout.jaxws.provider.user.handler config property.

Listing 15. Example of a JAX-WS Handler
@ApplicationScoped (1)
@RunWithRunContext (2)
public class IPAddressFilter implements SOAPHandler<SOAPMessageContext> {

  @Resource
  private Map<String, String> m_initParams; (3)

  @Override
  public boolean handleMessage(SOAPMessageContext context) {
    String rangeForm = m_initParams.get("rangeFrom"); (4)
    String rangeTo = m_initParams.get("rangeTo");
    // ...
    return true;
  }

  @Override
  public boolean handleFault(SOAPMessageContext context) {
    return true;
  }

  @Override
  public Set<QName> getHeaders() {
    return Collections.emptySet();
  }

  @Override
  public void close(MessageContext context) {
  }
}
1 Annotate the Handler with ApplicationScoped annotation, so it can be looked up via bean manager
2 Optionally annotate the Handler with RunWithRunContext annotation, so the handler is invoked in a RunContext
3 Declare a Map member annotated with Resource annotation to make injection of 'init parameters' work
4 Access injected 'init parameters'

Propagate state among Handlers and port type

Sometimes it is useful to share state among handlers, and even with the port type. This can be done via jakarta.xml.ws.handler.MessageContext. By default, a property put onto message context is only available in the handler chain. To make it available to the port type as well, set its scope to 'APPLICATION' accordingly.

The following listings gives an example of how to propagate state among handlers and port type.

Listing 16. This handler puts the correlation ID onto message context to be accessible by subsequent handlers and the port type.
@ApplicationScoped
public class CorrelationIdHandler implements SOAPHandler<SOAPMessageContext> {

  @Override
  public boolean handleMessage(SOAPMessageContext context) {
    context.put("cid", UUID.randomUUID().toString()); (1)
    context.setScope("cid", Scope.APPLICATION); (2)
    return true;
  }

  @Override
  public boolean handleFault(SOAPMessageContext context) {
    return true;
  }

  @Override
  public Set<QName> getHeaders() {
    return Collections.emptySet();
  }

  @Override
  public void close(MessageContext context) {
  }
}
1 Put the 'correlation ID' onto message context.
2 Set scope to APPLICATION to be accessible in port type. By default, the scope if HANDLER only.
Listing 17. This handler accesses the 'correlation ID' as set by the previous handler.
@ApplicationScoped
public class CorrelationIdLogger implements SOAPHandler<SOAPMessageContext> {

  @Override
  public boolean handleMessage(SOAPMessageContext context) {
    String correlationId = (String) context.get("cid"); (1)
    // ...
    return true;
  }

  @Override
  public boolean handleFault(SOAPMessageContext context) {
    return true;
  }

  @Override
  public void close(MessageContext context) {
  }

  @Override
  public Set<QName> getHeaders() {
    return Collections.emptySet();
  }
}
1 Get the 'correlation ID' from message context.
Listing 18. This port type accesses the 'correlation ID' as set by the previous handler.
@ApplicationScoped
public class CorrelationIdPortType implements PingWebServicePortType {

  @Override
  public String ping(String ping) {
    MessageContext currentMsgCtx = IWebServiceContext.CURRENT.get().getMessageContext(); (1)
    String correlationId = (String) currentMsgCtx.get("cid"); (2)
    // ...
    return ping;
  }
}
1 Get the current message context via thread local IWebServiceContext
2 Get the 'correlation ID' from message context.

JAX-WS Correlation ID Propagation

Scout’s JAX-WS integration already provides complete support for reading a correlation ID from the HTTP header named X-Scout-Correlation-Id of the incoming web service request and propagates it to the RunContext that executes the actual service operation. A new correlation ID is created if the HTTP header is empty or missing.

The CorrelationIdHandler example above just illustrates the capabilities of a SOAPHandler.
You have to implement your own handler if the consumer provides a correlation ID in another header parameter or as part of the request’s payload.
Listing 19. Add Scout’s WsProviderCorrelationIdHandler to the handler chain
@WebServiceEntryPoint(
    endpointInterface = PingWebServicePortType.class,
    entryPointName = "PingWebServiceEntryPoint",
    entryPointPackage = "org.eclipse.scout.docs.ws.ping2",
    serviceName = "PingWebService",
    portName = "PingWebServicePort",
    handlerChain = {
        @Handler(@Clazz(WsProviderCorrelationIdHandler.class)), (1)
        @Handler(@Clazz(LogHandler.class)),
    },
    authentication = @Authentication(
        method = @Clazz(BasicAuthenticationMethod.class),
        verifier = @Clazz(ConfigFileCredentialVerifier.class)))
1 Add the correlation ID handler at the beginning of the handler chain to ensure that all handlers can use its value (especially the LogHandler has to be added after the correlation ID handler).

Registration of webservice endpoints

The registration of webservice endpoints depends on the implementor you use. In the following, an example for JAX-WS METRO and Apache CXF is given.

JAX-WS METRO

During startup, JAX-WS METRO looks for the file '/WEB-INF/sun-jaxws.xml', which contains the endpoint definitions.

Listing 20. WEB-INF/sun-jaxws.xml
<jws:endpoints xmlns:jws="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">

  <!-- PingWebService -->
  <jws:endpoint
      name="PingService"
      implementation="org.eclipse.scout.docs.ws.ping.PingWebServiceEntryPoint"
      service="{http://scout.eclipse.org/docs/ws/PingWebService/}PingWebService"
      port="{http://scout.eclipse.org/docs/ws/PingWebService/}PingWebServiceSOAP"
      url-pattern="/jaxws/PingWebService"/>
</jws:endpoints>

Apache CXF

During startup, Apache CXF looks for the config file as specified in the registration via 'config-location'. See Listing 4 for more information.

Listing 21. WEB-INF/cxf-jaxws.xml
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  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">
  <import resource="classpath:META-INF/cxf/cxf.xml" />

  <!-- PingWebService -->
  <jaxws:endpoint id="PingWebService"
    implementor="org.eclipse.scout.docs.ws.ping.PingWebServiceEntryPoint"
    address="/PingWebService" />
</beans>
As the webservice endpoint, specify the fully qualified name to the entry point, and not to the implementing port type.
Depending on the implementor, a HTML page may be provided to see all webservices published.
For JAX-WS METRO, enter the URL to a concrete webservice, e.g. http://localhost:8080/jaxws/PingWebService.
For Apache CXF, enter the base URL where the webservices are published, e.g. http://localhost:8080/jaxws.

Consume a webservice

Communication with a webservice endpoint is done based on the webservice’s port generated by 'wsimport'. Learn more how to generate a webservice stub from a WSDL file.

To interact with a webservice endpoint, create a concrete 'WebServiceClient' class which extends from AbstractWebServiceClient, and specify the endpoint’s coordinates ('service' and 'port') via its bounded type parameters.

Listing 22. Example of a WS-Client
public class PingWebServiceClient extends AbstractWebServiceClient<PingWebService, PingWebServicePortType> { (1)
}
1 Specify 'service' and 'port' via bounded type parameters

A WS-Client can be configured with some default values like the endpoint URL, credentials, timeouts and more. However, the configuration can also be set or overwritten later when creating the InvocationContext.

Listing 23. Example of a WS-Client configuration
public class PingWebServiceClient1 extends AbstractWebServiceClient<PingWebService, PingWebServicePortType> {

  @Override
  protected Class<? extends IConfigProperty<String>> getConfiguredEndpointUrlProperty() {
    return JaxWsPingEndpointUrlProperty.class; (1)
  }

  @Override
  protected Class<? extends IConfigProperty<String>> getConfiguredUsernameProperty() {
    return JaxWsPingUsernameProperty.class; (2)
  }

  @Override
  protected Class<? extends IConfigProperty<String>> getConfiguredPasswordProperty() {
    return JaxWsPingPasswordProperty.class; (2)
  }

  @Override
  protected Class<? extends IConfigProperty<Integer>> getConfiguredConnectTimeoutProperty() {
    return JaxWsPingConnectTimeoutProperty.class; (3)
  }

  @Override
  protected Class<? extends IConfigProperty<Integer>> getConfiguredReadTimeoutProperty() {
    return JaxWsPingReadTimeoutProperty.class; (3)
  }
}
1 Specifies the endpoint URL
2 Specifies credentials
3 Specifies timeouts

Invoke a webservice

A webservice operation is invoked on behalf of an invocation context, which is associated with a dedicated port, and which specifies the data to be included in the web request. Upon a webservice call, the invocation context should be discarded.

Listing 24. Example of a webservice call
PingWebServicePortType port = BEANS.get(PingWebServiceClient.class).newInvocationContext().getPort(); (1)

port.ping("Hello world"); (2)
1 Obtain a new invocation context and port via WS-Client
2 Invoke the webservice operation

Invoking newInvocationContext() returns a new context and port instance. The context returned inherits all properties as configured for the WS-Client (endpoint URL, credentials, timeouts, …​), but which can be overwritten for the scope of this context.

The following listing illustrates how to set/overwrite properties.

Listing 25. Configure invocation context with data to be included in the web request
final InvocationContext<PingWebServicePortType> context = BEANS.get(PingWebServiceClient.class).newInvocationContext();

PingWebServicePortType port = context
    .withUsername("test-user") (1)
    .withPassword("secret")
    .withConnectTimeout(10, TimeUnit.SECONDS) (2)
    .withoutReadTimeout() (3)
    .withHttpRequestHeader("X-ENV", "integration") (4)
    .getPort();

port.ping("Hello world"); (5)
1 Set the credentials
2 Change the connect timeout to 10s
3 Unset the read timeout
4 Add a HTTP request header
5 Invoke the webservice operation

The WS-Client provides port instances via a preemptive port cache. This cache improves performance because port creation may be an expensive operation due to WSDL/schema validation. The cache is based on a 'corePoolSize', meaning that that number of ports is created on a preemptive basis. If more ports than that number are required, they are created on demand, and additionally added to the cache until expired, which is useful at a high load.

The JAX-WS specification does not specify thread safety of a port instance. Therefore, a port should not be used concurrently among threads. Further, JAX-WS API does not support to reset the Port’s request and response context, which is why a port should only be used for a single webservice call.

Cancel a webservice request

The WS-Client supports for cancellation of webservice requests. Internally, every web request is run in another thread, which the calling thread waits for to complete. Upon cancellation, that other thread is interrupted, and the calling thread released with a WebServiceRequestCancelledException. However, depending on the JAX-WS implementor, the web request may still be running, because JAX-WS API does not support the cancellation of a web request.

Get information about the last web request

The invocation context allows you to access HTTP status code and HTTP headers of the last web request.

final InvocationContext<PingWebServicePortType> context = BEANS.get(PingWebServiceClient.class).newInvocationContext();

String pingResult = context.getPort().ping("Hello world");

// Get HTTP status code
int httpStatusCode = context.getHttpStatusCode();

// Get HTTP response header
List<String> httpResponseHeader = context.getHttpResponseHeader("X-CUSTOM-HEADER");

Propagate state to Handlers

An invocation context can be associated with request context properties, which are propagated to handlers and JAX-WS implementor.

BEANS.get(PingWebServiceClient.class).newInvocationContext()
    .withRequestContextProperty("cid", UUID.randomUUID().toString()) (1)
    .getPort().ping("Hello world"); (2)
1 Propagate the correlation ID
2 Invoke the web operation

Learn more how to access context properties from within a handler in Listing 17.

Install handlers and provide credentials for authentication

To install a handler, overwrite execInstallHandlers and add the handler to the given List. The handlers are invoked in the order as added to the handler-chain. By default, there is no handler installed.

The method execInstallHandlers is invoked upon preemptive creation of the port. Consequently, you cannot do any assumption about the calling thread.

If a handler requires to run in another RunContext than the calling context, annotate it with RunWithRunContext annotation, e.g. to start a new transaction to log into database.

If the endpoint requires to authenticate requests, an authentication handler is typically added to the list, e.g. BasicAuthenticationHandler for 'Basic authentication', or WsseUsernameTokenAuthenticationHandler for 'Message Level WS-Security authentication', or some other handler to provide credentials.

public class PingWebServiceClient2 extends AbstractWebServiceClient<PingWebService, PingWebServicePortType> {

  @Override
  protected void execInstallHandlers(List<jakarta.xml.ws.handler.Handler<?>> handlerChain) {
    handlerChain.add(new BasicAuthenticationHandler());
    handlerChain.add(BEANS.get(LogHandler.class));
  }
}
The credentials as provided via InvocationContext can be accessed via request context with the property InvocationContext.PROP_USERNAME and InvocationContext.PROP_PASSWORD.

JAX-WS Client Correlation ID Propagation

The current context’s correlation ID can be forwarded to the consumed web service. Scout provides a handler that sets the X-Scout-Correlation-Id HTTP header on the outgoing request.

public class PingWebServiceClient3 extends AbstractWebServiceClient<PingWebService, PingWebServicePortType> {

  @Override
  protected void execInstallHandlers(List<jakarta.xml.ws.handler.Handler<?>> handlerChain) {
    handlerChain.add(new BasicAuthenticationHandler());
    handlerChain.add(BEANS.get(LogHandler.class));
    handlerChain.add(BEANS.get(WsConsumerCorrelationIdHandler.class)); (1)
  }
}
1 The handler can be at any position in the handler chain.

Default configuration of WS-Clients

The following properties can be set globally for all WS-Clients. However, a WS-Client can overwrite any of these values.

property description default value

scout.jaxws.consumer.portCache.enabled

To indicate whether to use a preemptive port cache for WS-Clients.
Depending on the implementor used, cached ports may increase performance, because port creation is an expensive operation due to WSDL and schema validation. The cache is based on a 'corePoolSize', meaning that that number of ports is created on a preemptive basis. If more ports than that number is required, they are created on demand and also added to the cache until expired, which is useful at a high load.

true

scout.jaxws.consumer.portCache.corePoolSize

Number of ports to be preemptively cached to speed up webservice calls.

10

scout.jaxws.consumer.portCache.ttl

Maximum time in seconds to retain ports in the cache if the 'corePoolSize' is exceeded. That typically occurs at high load, or if 'corePoolSize' is undersized.

15 minutes

scout.jaxws.consumer.connectTimeout

Connect timeout in milliseconds to abort a webservice request, if establishment of the HTTP connection takes longer than this timeout. A timeout of null means an infinite timeout.

infinite

scout.jaxws.consumer.readTimeout

Read timeout in milliseconds to abort a webservice request, if it takes longer than this timeout for data to be available for read. A timeout of null means an infinite timeout.

infinite

XML adapters to work with java.util.Date and java.util.Calendar

Scout ships with some XML adapters to not have to work with XMLGregorianCalendar, but with java.util.Date instead.
It is recommended to configure your global binding file accordingly. See Listing 9 for an example.

See the adapter’s JavaDoc for more detailed information.

Table 1. UTC Date adapters
adapter description

UtcDateAdapter

Use this adapter to work with UTC xsd:dates. A UTC date is also known as 'zulu' date, and has 'GMT+-00:00'. Unlike UtcDateTimeAdapter, this adapter truncates hours, minutes, seconds and milliseconds.

UtcTimeAdapter

Use this adapter to work with UTC xsd:times. A UTC time is also known as 'zulu' time, and has 'GMT+-00:00'. Unlike UtcDateTimeAdapter, this adapter sets year, month and day to the epoch, which is defined as 1970-01-01 in UTC.

UtcDateTimeAdapter

Use this adapter to work with UTC xsd:dateTimes. A UTC time is also known as 'zulu' time, and has 'GMT+-00:00'.

This adapter converts xsd:dateTime into UTC milliseconds, by respecting the timezone as provided. If the timezone is missing, the date is interpreted as UTC-time, and not local to the default JVM timezone. To convert a Date into xsd:dateTime, the date’s milliseconds are used as UTC milliseconds from the epoch, and are formatted as 'zulu' time.

Table 2. Calendar adapters
adapter description

CalendarDateAdapter

Use this adapter to work with Calendar xsd:dates without loosing timezone information. Unlike CalendarDateTimeAdapter, this adapter truncates hours, minutes, seconds and milliseconds.

CalendarTimeAdapter

Use this adapter to work with Calendar xsd:times without loosing timezone information. Unlike CalendarDateTimeAdapter, this adapter sets year, month and day to the epoch, which is defined as 1970-01-01 in UTC.

CalendarDateTimeAdapter

Adapter to convert a xsd:dateTime to a Calendar and vice versa. For both directions, the timezone information is not lost. Use this adapter if you expect to work with dates from various timezones without losing the local time. If the UTC (Zulu-time) is sufficient, use UtcDateTimeAdapter instead.

Table 3. Default timezone Date adapters
adapter description

DefaultTimezoneDateAdapter

Use this adapter to work with xsd:dates in the default timezone of the Java Virtual Machine. Depending on the JVM installation, the timezone may differ: 'GMT+-XX:XX'. Unlike DefaultTimezoneDateTimeAdapter, this adapter truncates hours, minutes, seconds and milliseconds.
Whenever possible, use UtcDateAdapter or CalendarDateAdapter instead.

DefaultTimezoneTimeAdapter

Use this adapter to work with xsd:times in the default timezone of the Java Virtual Machine. Depending on the JVM installation, the timezone may differ: 'GMT+-XX:XX'. Unlike DefaultTimezoneDateTimeAdapter, this adapter sets year, month and day to the epoch, which is defined as 1970-01-01 in UTC.
Whenever possible, use UtcTimeAdapter or CalendarTimeAdapter instead.

DefaultTimezoneDateTimeAdapter

Use this adapter to work with xsd:dateTimes in the default timezone of the Java Virtual Machine. Depending on the JVM installation, the timezone may differ: 'GMT+-XX:XX'.
Whenever possible, use UtcDateTimeAdapter or CalendarDateTimeAdapter instead.

JAX-WS Appendix

PingWebService.wsdl

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
  ~ Copyright (c) 2010, 2023 BSI Business Systems Integration AG
  ~
  ~ This program and the accompanying materials are made
  ~ available under the terms of the Eclipse Public License 2.0
  ~ which is available at https://www.eclipse.org/legal/epl-2.0/
  ~
  ~ SPDX-License-Identifier: EPL-2.0
  -->
<wsdl:definitions name="PingWebService"
  targetNamespace="http://scout.eclipse.org/docs/ws/PingWebService/"
  xmlns:tns="http://scout.eclipse.org/docs/ws/PingWebService/"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
    <xsd:schema targetNamespace="http://scout.eclipse.org/docs/ws/PingWebService/">
      <xsd:element name="pingRequest" type="xsd:string"/>
      <xsd:element name="pingResponse" type="xsd:string"/>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="pingRequest">
    <wsdl:part element="tns:pingRequest" name="ping" />
  </wsdl:message>
  <wsdl:message name="pingResponse">
    <wsdl:part element="tns:pingResponse" name="parameters" />
  </wsdl:message>
  <wsdl:portType name="PingWebServicePortType">
    <wsdl:operation name="ping">
      <wsdl:input message="tns:pingRequest" />
      <wsdl:output message="tns:pingResponse" />
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="PingWebServiceSOAP" type="tns:PingWebServicePortType">
    <soap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="ping">
      <soap:operation soapAction="http://scout.eclipse.org/docs/ws/PingWebService/ping" />
      <wsdl:input>
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="PingWebService">
    <wsdl:port binding="tns:PingWebServiceSOAP" name="PingWebServiceSOAP">
      <soap:address location="http://scout.eclipse.org/docs/ws/PingWebService/" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

PingWebServicePortType.java

@FunctionalInterface
@WebService(name = "PingWebServicePortType", targetNamespace = "http://scout.eclipse.org/docs/ws/PingWebService/")
@SOAPBinding(parameterStyle = ParameterStyle.BARE)
public interface PingWebServicePortType {

  @WebMethod(action = "http://scout.eclipse.org/docs/ws/PingWebService/ping")
  @WebResult(name = "pingResponse", targetNamespace = "http://scout.eclipse.org/docs/ws/PingWebService/", partName = "parameters")
  String ping(@WebParam(name = "pingRequest", targetNamespace = "http://scout.eclipse.org/docs/ws/PingWebService/", partName = "ping") String ping);
}

PingWebServicePortTypeEntryPoint.java

@Generated(value = "org.eclipse.scout.jaxws.apt.JaxWsAnnotationProcessor", date = "2016-01-25T14:22:58:583+0100", comments = "EntryPoint to run webservice requests on behalf of a RunContext")
@WebService(name = "PingWebServicePortType", targetNamespace = "http://scout.eclipse.org/docs/ws/PingWebService/", endpointInterface = "org.eclipse.scout.docs.ws.pingwebservice.PingWebServicePortType")
public class PingWebServicePortTypeEntryPoint implements org.eclipse.scout.docs.ws.pingwebservice.PingWebServicePortType {

  @Resource
  protected WebServiceContext m_webServiceContext;

  @Override
  public String ping(final String ping) {
    try {
      return lookupRunContext().call(new Callable<String>() {
        @Override
        public final String call() throws Exception {
          return BEANS.get(PingWebServicePortType.class).ping(ping);
        }
      }, DefaultExceptionTranslator.class);
    }
    catch (Exception e) {
      throw handleUndeclaredFault(e);
    }
  }

  protected RuntimeException handleUndeclaredFault(final Exception e) {
    throw BEANS.get(JaxWsUndeclaredExceptionTranslator.class).translate(e);
  }

  protected RunContext lookupRunContext() {
    return BEANS.get(JaxWsRunContextLookup.class).lookup(m_webServiceContext);
  }
}

PingWebServicePortTypeBean.java

@ApplicationScoped
public class PingWebServicePortTypeBean implements PingWebServicePortType {

  @Override
  public String ping(String ping) {
    return "ping: " + ping;
  }
}

.settings/org.eclipse.jdt.core.prefs file to enable APT in Eclipse IDE

...
org.eclipse.jdt.core.compiler.processAnnotations=enabled
...

.settings/org.eclipse.jdt.apt.core.prefs file to enable APT in Eclipse IDE

org.eclipse.jdt.apt.aptEnabled=true
org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations
org.eclipse.jdt.apt.processorOptions/consoleLog=true
org.eclipse.jdt.apt.reconcileEnabled=true

.factorypath file to enable APT in Eclipse IDE

<!-- Replace 'XXX-VERSION-XXX' by the respective Scout RT version -->
<factorypath>
    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/scout/rt/org.eclipse.scout.jaxws.apt/XXX-VERSION-XXX/org.eclipse.scout.jaxws.apt-XXX-VERSION-XXX.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/org/glassfish/jaxb/codemodel/4.0.4/codemodel-4.0.4.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/scout/rt/org.eclipse.scout.rt.platform/XXX-VERSION-XXX/org.eclipse.scout.rt.platform-XXX-VERSION-XXX.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/org/eclipse/scout/rt/org.eclipse.scout.rt.server.jaxws/XXX-VERSION-XXX/org.eclipse.scout.rt.server.jaxws-XXX-VERSION-XXX.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/servlet/jakarta.servlet-api/5.0.0/jakarta.servlet-api-5.0.0.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/org/slf4j/slf4j-api/2.0.9/slf4j-api-2.0.9.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/jws/jakarta.jws-api/3.0.0/jakarta.jws-api-3.0.0.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/annotation/jakarta.annotation-api/2.0.0/jakarta.annotation-api-2.0.0.jar" enabled="true" runInBatchMode="false"/>
    <factorypathentry kind="VARJAR" id="M2_REPO/jakarta/xml/ws/jakarta.xml.ws-api/3.0.1/jakarta.xml.ws-api-3.0.1.jar" enabled="true" runInBatchMode="false"/>
</factorypath>

Authentication Method

The authentication method specifies the protocol to challenge the webservice client to provide credentials.
Scout provides an implementation for BASIC and WSSE_UsernameToken. You can implement your own authentication method by implementing IAuthenticationMethod interface.

BasicAuthenticationMethod

Authentication method to apply Basic Access Authentication. This requires requests to provide a valid user name and password to access content. User’s credentials are transported in HTTP headers. Basic authentication also works across firewalls and proxy servers.

However, the disadvantage of Basic authentication is that it transmits unencrypted base64-encoded passwords across the network. Therefore, you only should use this authentication when you know that the connection between the client and the server is secure. The connection should be established either over a dedicated line or by using Secure Sockets Layer (SSL) encryption and Transport Layer Security (TLS).

WsseUsernameTokenMethod

Authentication method to apply Message Level WS-Security with UsernameToken Authentication. This requires requests to provide a valid user name and password to access content. User’s credentials are included in SOAP message headers.

However, the disadvantage of WSSE UsernameToken Authentication is that it transmits unencrypted passwords across the network. Therefore, you only should use this authentication when you know that the connection between the client and the server is secure. The connection should be established either over a dedicated line or by using Secure Sockets Layer (SSL) encryption and Transport Layer Security (TLS).

ContainerBasedAuthenticationMethod

Use this authentication method when using container based authentication, meaning that webservice requests are authenticated by the application server, or a Servlet filter.

Credential Verifier

Verifies user’s credentials against a data source like database, config.properties, Active Directory, or others.
Scout provides an implementation for verification against users in config.properties. You can implement your own verifier by implementing ICredentialVerifier interface.

If you require to run in a specific RunContext like a transaction for user’s verification, annotate the verifier with RunWithRunContext annotation, and specify a RunContextProducer accordingly.

ConfigFileCredentialVerifier

Credential verifier against credentials configured in config.properties file.

By default, this verifier expects the passwords in 'config.properties' to be a hash produced with SHA-512 algorithm. To support you in password hash generation, ConfigFileCredentialVerifier provides a static Java main method.

Credentials are loaded from property scout.auth.credentials. Multiple credentials are separated with the semicolon, username and password with the colon. If using hashed passwords (by default), the password’s salt and hash are separated with the dot.

To work with plaintext passwords, set the property scout.auth.credentialsPlaintext to true.

Example of hashed passwords: scott:SALT.PASSWORD-HASH;jack:SALT.PASSWORD-HASH;john:SALT.PASSWORD-HASH Example of plaintext passwords: scott:*;jack:;john:*