4 Programming the JWS File

This chapter describes how to program the JWS file that implements your WebLogic Web service using Java API for XML-based Web services (JAX-WS).

This chapter includes the following topics:

Overview of JWS Files and JWS Annotations

There are two ways to program a WebLogic Web service from scratch:

  1. Annotate a standard EJB or Java class with Web service Java annotations, as defined by JSR-181, the JAX-WS specification, and by the WebLogic Web services programming model.

  2. Combine a standard EJB or Java class with the various XML descriptor files and artifacts specified by JSR-109 (such as, deployment descriptors, WSDL files, data mapping descriptors, data binding artifacts for user-defined data types, and so on).

Oracle strongly recommends using option 1 above. Instead of authoring XML metadata descriptors yourself, the WebLogic Ant tasks and runtime will generate the required descriptors and artifacts based on the annotations you include in your JWS. Not only is this process much easier, but it keeps the information about your Web service in a central location, the JWS file, rather than scattering it across many Java and XML files.

The Java Web service (JWS) annotated file is the core of your Web service. It contains the Java code that determines how your Web service behaves. A JWS file is an ordinary Java class file that uses Java metadata annotations to specify the shape and characteristics of the Web service. The JWS annotations you can use in a JWS file include the standard ones defined by the Web services Metadata for the Java Platform specification (JSR-181), described at http://www.jcp.org/en/jsr/detail?id=181, plus a set of additional annotations based on the type of Web service you are building—JAX-WS or JAX-RPC. For a complete list of JWS annotations that are supported for JAX-WS and JAX-RPC Web services, see "Web Service Annotation Support" in WebLogic Web Services Reference for Oracle WebLogic Server.

When programming the JWS file, you include annotations to program basic Web service features. The annotations are used at different levels, or targets, in your JWS file. Some are used at the class-level to indicate that the annotation applies to the entire JWS file. Others are used at the method-level and yet others at the parameter level.

Java Requirements for a JWS File

When you program your JWS file, you must follow a set of requirements, as specified by the Web Services Metadata for the Java Platform specification (JSR-181) at http://www.jcp.org/en/jsr/detail?id=181. In particular, the Java class that implements the Web service:

  • Must be an outer public class, must not be declared final, and must not be abstract.

  • Must have a default public constructor.

  • Must not define a finalize() method.

  • Must include, at a minimum, a @WebService JWS annotation at the class level to indicate that the JWS file implements a Web service.

  • May reference a service endpoint interface by using the @WebService.endpointInterface annotation. In this case, it is assumed that the service endpoint interface exists and you cannot specify any other JWS annotations in the JWS file other than @WebService.endpointInterface, @WebService.serviceName, and @WebService.targetNamespace.

  • If JWS file does not implement a service endpoint interface, all public methods other than those inherited from java.lang.Object will be exposed as Web service operations. This behavior can be overridden by using the @WebMethod annotation to specify explicitly the public methods that are to be exposed. If a @WebMethod annotation is present, only the methods to which it is applied are exposed.

Programming the JWS File: Typical Steps

The following procedure describes the typical steps for programming a JWS file that implements a Web service.

Note:

It is assumed that you have created a JWS file and now want to add JWS annotations to it.

For more information about each of the JWS annotations, see "JWS Annotation Reference" in WebLogic Web Services Reference for Oracle WebLogic Server.

Table 4-1 Steps to Program the JWS File

#
Step Description

1

Import the standard JWS annotations that will be used in your JWS file.

The standard JWS annotations are in either the javax.jws, javax.jws.soap, or javax.xml.ws package. For example:

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.xml.ws.BindingType;

2

Import additional annotations, as required.

For a complete list of JWS annotations that are supported, see "Web Service Annotation Support" in WebLogic Web Services Reference for Oracle WebLogic Server.

3

Add the standard required @WebService JWS annotation at the class level to specify that the Java class exposes a Web service.

See Specifying that the JWS File Implements a Web Service (@WebService Annotation).

4

Add the standard @SOAPBinding JWS annotation at the class level to specify the mapping between the Web service and the SOAP message protocol. (Optional)

In particular, use this annotation to specify whether the Web service is document-literal, document-encoded, and so on. See Specifying the Mapping of the Web Service to the SOAP Message Protocol (@SOAPBinding Annotation).

Although this JWS annotation is not required, Oracle recommends you explicitly specify it in your JWS file to clarify the type of SOAP bindings a client application uses to invoke the Web service.

5

Add the JAX-WS @BindingType JWS annotation at the class level to specify the binding type to use for a Web service endpoint implementation class. (Optional)

See Specifying the Binding to Use for an Endpoint (@BindingType Annotation).

6

Add the standard @WebMethod annotation for each method in the JWS file that you want to expose as a public operation. (Optional)

Optionally specify that the operation takes only input parameters but does not return any value by using the standard @Oneway annotation. See Specifying That a JWS Method Be Exposed as a Public Operation (@WebMethod and @OneWay Annotations).

7

Add @WebParam annotation to customize the name of the input parameters of the exposed operations. (Optional)

See Customizing the Mapping Between Operation Parameters and WSDL Elements (@WebParam Annotation).

8

Add @WebResult annotations to customize the name and behavior of the return value of the exposed operations. (Optional)

See Customizing the Mapping Between the Operation Return Value and a WSDL Element (@WebResult Annotation).

9

Add your business code.

Add your business code to the methods to make the WebService behave as required.


Example of a JWS File

The following sample JWS file shows how to implement a simple Web service.

package examples.webservices.simple;
// Import the standard JWS annotation interfaces
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// Standard JWS annotation that specifies that the porType name of the Web
// Service is "SimplePortType", the service name is "SimpleService", and the
// targetNamespace used in the generated WSDL is "http://example.org"
@WebService(name="SimplePortType", serviceName="SimpleService",
            targetNamespace="http://example.org")
// Standard JWS annotation that specifies the mapping of the service onto the
// SOAP message protocol.  In particular, it specifies that the SOAP messages
// are document-literal-wrapped.
@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
             use=SOAPBinding.Use.LITERAL,
             parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)
/**
 * This JWS file forms the basis of simple Java-class implemented WebLogic
 * Web Service with a single operation: sayHello
 *
 */
public class SimpleImpl {
  // Standard JWS annotation that specifies that the method should be exposed
  // as a public operation.  Because the annotation does not include the
  // member-value "operationName", the public name of the operation is the
 // same as the method name: sayHello.
  @WebMethod()
  public String sayHello(String message) {
    System.out.println("sayHello:" + message);
    return "Here is the message: '" + message + "'";
  }
}

Specifying that the JWS File Implements a Web Service (@WebService Annotation)

Use the standard @WebService annotation to specify, at the class level, that the JWS file implements a Web service, as shown in the following code excerpt:

@WebService(name="SimplePortType", serviceName="SimpleService",
            targetNamespace="http://example.org")

In the example, the name of the Web service is SimplePortType, which will later map to the wsdl:portType element in the WSDL file generated by the jwsc Ant task. The service name is SimpleService, which will map to the wsdl:service element in the generated WSDL file. The target namespace used in the generated WSDL is http://example.org.

You can also specify the following additional attributes of the @WebService annotation:

  • endpointInterface—Fully qualified name of an existing service endpoint interface file. This annotation allows the separation of interface definition from the implementation. If you specify this attribute, the jwsc Ant task does not generate the interface for you, but assumes you have created it and it is in your CLASSPATH.

  • portname—Name that is used in the wsdl:port.

None of the attributes of the @WebService annotation is required. See the Web Services Metadata for the Java Platform (JSR 181) at http://www.jcp.org/en/jsr/detail?id=181 for the default values of each attribute.

Specifying the Mapping of the Web Service to the SOAP Message Protocol (@SOAPBinding Annotation)

It is assumed that you want your Web service to be available over the SOAP message protocol; for this reason, your JWS file should include the standard @SOAPBinding annotation, at the class level, to specify the SOAP bindings of the Web service (such as, document-encoded or document-literal-wrapped), as shown in the following code excerpt:

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
             use=SOAPBinding.Use.LITERAL,
             parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

In the example, the Web service uses document-wrapped-style encodings and literal message formats, which are also the default formats if you do not specify the @SOAPBinding annotation. In general, document-literal-wrapped Web services are the most interoperable type of Web service.

You use the parameterStyle attribute (in conjunction with the style=SOAPBinding.Style.DOCUMENT attribute) to specify whether the Web service operation parameters represent the entire SOAP message body, or whether the parameters are elements wrapped inside a top-level element with the same name as the operation.

The following table lists the possible and default values for the three attributes of the @SOAPBinding (either the standard or WebLogic-specific) annotation.

Table 4-2 Attributes of the @SOAPBinding Annotation

Attribute Possible Values Default Value

style

SOAPBinding.Style.RPC

SOAPBinding.Style.DOCUMENT

SOAPBinding.Style.DOCUMENT

use

SOAPBinding.Use.LITERAL

SOAPBinding.Use.LITERAL

parameterStyle

SOAPBinding.ParameterStyle.BARE

SOAPBinding.ParameterStyle.WRAPPED

SOAPBinding.ParameterStyle.WRAPPED


Specifying That a JWS Method Be Exposed as a Public Operation (@WebMethod and @OneWay Annotations)

Use the standard @WebMethod annotation to specify that a method of the JWS file should be exposed as a public operation of the Web service, as shown in the following code excerpt:

public class SimpleImpl {
  @WebMethod(operationName="sayHelloOperation")
  public String sayHello(String message) {
    System.out.println("sayHello:" + message);
    return "Here is the message: '" + message + "'";
  }
...

In the example, the sayHello() method of the SimpleImpl JWS file is exposed as a public operation of the Web service. The operationName attribute specifies, however, that the public name of the operation in the WSDL file is sayHelloOperation. If you do not specify the operationName attribute, the public name of the operation is the name of the method itself.

You can also use the action attribute to specify the action of the operation. When using SOAP as a binding, the value of the action attribute determines the value of the SOAPAction header in the SOAP messages.

To exclude a method as a Web service operation, specify @WebMethod(exclude="true").

Note:

For JAX-WS, the service endpoint interface (SEI) defines the public methods. If no SEI exists, then all public methods are exposed as Web service operations, unless they are tagged explicitly with @WebMethod(exclude="true").

You can specify that an operation not return a value to the calling application by using the standard @Oneway annotation, as shown in the following example:

 public class OneWayImpl {
  @WebMethod()
  @Oneway()
  public void ping() {
    System.out.println("ping operation");
  }
...

If you specify that an operation is one-way, the implementing method is required to return void, cannot use a Holder class as a parameter, and cannot throw any checked exceptions.

None of the attributes of the @WebMethod annotation is required. See the Web Services Metadata for the Java Platform (JSR 181) at http://www.jcp.org/en/jsr/detail?id=181 for the default values of each attribute, as well as additional information about the @WebMethod and @Oneway annotations.

Customizing the Mapping Between Operation Parameters and WSDL Elements (@WebParam Annotation)

Use the standard @WebParam annotation to customize the mapping between operation input parameters of the Web service and elements of the generated WSDL file, as well as specify the behavior of the parameter, as shown in the following code excerpt:

 public class SimpleImpl {
  @WebMethod()
  @WebResult(name="IntegerOutput",
             targetNamespace="http://example.org/docLiteralBare")
  public int echoInt(
      @WebParam(name="IntegerInput",
                targetNamespace="http://example.org/docLiteralBare")
      int input)
  {
      System.out.println("echoInt '" + input + "' to you too!");
      return input;
  }
...

In the example, the name of the parameter of the echoInt operation in the generated WSDL is IntegerInput; if the @WebParam annotation were not present in the JWS file, the name of the parameter in the generated WSDL file would be the same as the name of the method's parameter: input. The targetNamespace attribute specifies that the XML namespace for the parameter is http://example.org/docLiteralBare; this attribute is relevant only when using document-style SOAP bindings where the parameter maps to an XML element.

You can also specify the following additional attributes of the @WebParam annotation:

  • mode—The direction in which the parameter is flowing (WebParam.Mode.IN, WebParam.Mode.OUT, or WebParam.Mode.INOUT). OUT and INOUT modes are only supported for RPC-style operations or for parameters that map to headers.

  • header—Boolean attribute that, when set to true, specifies that the value of the parameter should be retrieved from the SOAP header, rather than the default body.

None of the attributes of the @WebParam annotation is required. See the Web Services Metadata for the Java Platform (JSR 181) at http://www.jcp.org/en/jsr/detail?id=181 for the default value of each attribute.

Customizing the Mapping Between the Operation Return Value and a WSDL Element (@WebResult Annotation)

Use the standard @WebResult annotation to customize the mapping between the Web service operation return value and the corresponding element of the generated WSDL file, as shown in the following code excerpt:

public class Simple {
  @WebMethod()
  @WebResult(name="IntegerOutput",
             targetNamespace="http://example.org/docLiteralBare")
  public int echoInt(
      @WebParam(name="IntegerInput",
                targetNamespace="http://example.org/docLiteralBare")
      int input)
  {
      System.out.println("echoInt '" + input + "' to you too!");
      return input;
  }
...

In the example, the name of the return value of the echoInt operation in the generated WSDL is IntegerOutput; if the @WebResult annotation were not present in the JWS file, the name of the return value in the generated WSDL file would be the hard-coded name return. The targetNamespace attribute specifies that the XML namespace for the return value is http://example.org/docLiteralBare; this attribute is relevant only when using document-style SOAP bindings where the return value maps to an XML element.

None of the attributes of the @WebResult annotation is required. See the Web Services Metadata for the Java Platform (JSR 181) at http://www.jcp.org/en/jsr/detail?id=181 for the default value of each attribute.

Specifying the Binding to Use for an Endpoint (@BindingType Annotation)

Use the JAX-WS @BindingType annotation to customize the binding to use for a web service endpoint implementation class, as shown in the following code excerpt:

import javax.xml.ws.BindingType;
import javax.xml.ws.soap.SOAPBinding;
 public class Simple {
  @WebService()
  @BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)
  public int echoInt(
      @WebParam(name="IntegerInput",
                targetNamespace="http://example.org/docLiteralBare")
      int input)
  {
      System.out.println("echoInt '" + input + "' to you too!");
      return input;
  }
...

In the example, the deployed endpoint would use the SOAP1.2 over HTTP binding. If not specified, the binding defaults to SOAP 1.1 over HTTP.

You can also specify the following additional attributes of the @BindingType annotation:

  • features—An array of features to enable/disable on the specified binding. If not specified, features are enabled based on their own rules.

For more information about the @BindingType annotation, see JAX-WS 2.1 Annotations at http://jax-ws.java.net/nonav/2.1.4/docs/annotations.html.

Accessing Runtime Information About a Web Service

When a client application invokes a WebLogic Web service that was implemented with a JWS file, WebLogic Server automatically creates a context that the Web service or client can use to access, and sometimes change, runtime information about the service.

To access runtime information, you can use one of the following methods:

The following sections describe how to use the BindingProvider, WebServiceContext, and MessageContext to access runtime information in more detail.

Accessing the Protocol Binding Context

Note:

The com.sun.xml.ws.developer.JAXWSProperties and com.sun.xml.ws.client.BindingProviderProperties APIs are supported as an extension to the JDK 6.0. Because the APIs are not provided as part of the JDK 6.0 kit, they are subject to change.

The javax.xml.ws.BindingProvider interface enables you to access from the client application the request and response context of the protocol binding. For more information, see http://download.oracle.com/javaee/5/api/javax/xml/ws/BindingProvider.html. For more information about developing Web service client files, see "Invoking Web Services".

The following example shows a simple Web service client application that uses the context to access HTTP request header information. The code in bold is discussed in the programming guidelines described following the example.

package examples.webservices.hello_world.client;

import javax.xml.namespace.QName;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.MessageContext;
import com.sun.xml.ws.developer.JAXWSProperties;
import com.sun.xml.ws.client.BindingProviderProperties;

/**
 * This is a simple standalone client application that invokes the
 * the <code>sayHelloWorld</code> operation of the Simple Web service.
 */

public class Main {
  public static void main(String[] args) {
    HelloWorldService service;
    try { 
       service = new HelloWorldService(new URL(args[0] + "?WSDL"), 
           new QName("http://hello_world.webservices.examples/", 
           "HelloWorldService") );
    } catch (MalformedURLException murl) { throw new RuntimeException(murl); }
      HelloWorldPortType port = service.getHelloWorldPortTypePort();
      String result = null;
      result = port.sayHelloWorld("Hi there!");
      System.out.println( "Got result: " + result );
      Map requestContext = ((BindingProvider)port).getRequestContext();
      requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                       "http://examples.com/HelloWorldImpl/HelloWorldService");
      requestContext.put(JAXWSProperties.CONNECT_TIMEOUT, 300); 
      requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 300); 
      Map responseContext = ((BindingProvider)port).getResponseContext();
      Integer responseCode = 
               (Integer)responseContext.get(MessageContext.HTTP_RESPONSE_CODE);
...
  }
}

Use the following guidelines in your JWS file to access the runtime context of the Web service, as shown in the code in bold in the preceding example:

  • Import the javax.xml.ws.BindingProvider API, as well as any other related APIs that you might use:

    import java.util.Map;
    import javax.xml.ws.BindingProvider;
    import javax.xml.ws.handler.MessageContext;
    import com.sun.xml.ws.developer.JAXWSProperties;
    import com.sun.xml.ws.client.BindingProviderProperties;
    import com.sun.xml.ws.client.BindingProviderProperties;
    
  • Use the methods of the BindingProvider class to access the binding protocol context information. The following example shows how to get the request and response context for the protocol binding and subsequently set the target service endpoint address used by the client for the request context, set the connection and read timeouts (in milliseconds) for the request context, and set the HTTP response status code for the response context:

    Map requestContext = ((BindingProvider)port).getRequestContext();
    requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                        "http://examples.com/HelloWorldImpl/HelloWorldService");
    requestContext.put(JAXWSProperties.CONNECT_TIMEOUT, 300); 
    requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 300); 
    Map responseContext = ((BindingProvider)port).getResponseContext();
    Integer responseCode = 
             (Integer)responseContext.get(MessageContext.HTTP_RESPONSE_CODE);
    

The following table summarizes the methods of the javax.xml.ws.BindingProvider that you can use in your JWS file to access runtime information about the Web service.

Table 4-3 Methods of the BindingProvider

Method Returns Description

getBinding()

Binding

Returns the binding for the binding provider.

getRequestContext()

java.Util.Map

Returns the context that is used to initialize the message and context for request messages.

getResponseContext()

java.Util.Map

Returns the response context.


One you get the request or response context, you can access the BindingProvider property values defined in the following table and the MessageContext property values defined in Using the MessageContext Property Values.

Table 4-4 Properties of BindingProvider

Property Type Description

ENDPOINT_ADDRESS_PROPERTY

java.lang.String

Target service endpoint address.

PASSWORD_PROPERTY

java.lang.String

Password used for authentication.

SESSION_MAINTAIN_PROPERTY

java.lang.Boolean

Flag that specifies whether a service client wants to participate in a session with a service endpoint. Defaults to false, indicating that the service client does not want to participate.

SOAPACTION_URI_PROPERTY

java.lang.String

Property for SOAPAction specifying the SOAPAction URI. This property is valid only if SOAPACTION_USE_PROPERTY is set to true.

SOAPACTION_USE_PROPERTY

java.lang.Boolean

Property for SOAPAction specifying whether or not SOAPAction should be used.

USERNAME_PROPERTY

java.lang.String

User name used for authentication.


In addition, in the previous example:

Accessing the Web Service Context

The javax.xml.ws.WebServiceContext interface enables you to access from the Web service runtime message context and security information relative to a request being served. Typically, a WebServiceContext is injected into an endpoint using the @Resource annotation. For more information, see http://download.oracle.com/javaee/5/api/javax/xml/ws/WebServiceContext.html.

The following example shows a simple JWS file that uses the context to access HTTP request header information. The code in bold is discussed in the programming guidelines described following the example.

package examples.webservices.jws_context;
import javax.jws.WebMethod;
import javax.jws.WebService;
import java.util.Map;
import javax.xml.ws.WebServiceContext;
import javax.annotation.Resource;
import javax.xml.ws.handler.MessageContext;
@WebService(name="JwsContextPortType", serviceName="JwsContextService",
            targetNamespace="http://example.org")
/**
 * Simple web service to show how to use the @Context annotation.
 */
public class JwsContextImpl {
  @Resource
  private WebServiceContext ctx; 
  @WebMethod()
  public String msgContext(String msg) {
    MessageContext context=ctx.getMessageContext();
    Map requestHeaders = (Map)context.get(MessageContext.HTTP_REQUEST_HEADERS);
  }
}

Use the following guidelines in your JWS file to access the runtime context of the Web service, as shown in the code in bold in the preceding example:

  • Import the @javax.annotation.Resource JWS annotation:

    import javax.annotation.Resource;
    
  • Import the javax.xml.ws.WebServiceContext API, as well as any other related APIs that you might use:

    import java.util.Map;
    import javax.xml.ws.WebServiceContext;
    import javax.xml.ws.handler.MessageContext;
    
  • Annotate a private variable, of data type javax.xml.ws.WebServiceContext, with the field-level @Resource JWS annotation:

    @Resource
    private WebServiceContext ctx; 
    
  • Use the methods of the WebServiceContext class to access runtime information about the Web service. The following example shows how to get the message context for the current service request and subsequently access the HTTP request headers:

    MessageContext context=ctx.getMessageContext();
    Map requestHeaders = (Map)context.get(MessageContext.HTTP_REQUEST_HEADERS)
    

    For more information about the MessageContext property values, see Using the MessageContext Property Values.

The following table summarizes the methods of the javax.xml.ws.WebServiceContext that you can use in your JWS file to access runtime information about the Web service. For more information, see http://download.oracle.com/javaee/5/api/javax/xml/ws/WebServiceContext.html.

Table 4-5 Methods of the WebServiceContext

Method Returns Description

getMessageContext()

MessageContext

Returns the MessageContext for the current service request. You can access properties that are application-scoped only, such as HTTP_REQUEST_HEADERS, MESSAGE_ATTACHMENTS, and so on, as defined in Using the MessageContext Property Values.

getUserPrincipal()

java.security.Principal

Returns the Principal that identifies the sender of the current service request. If the sender has not been authenticated, the method returns null.

isUserInRole(java.lang.String role)

boolean

Returns a boolean value specifying whether the authenticated user is included in the specified logical role. If the user has not been authenticated, the method returns false.


Using the MessageContext Property Values

The following table defined the javax.xml.ws.handler.MessageContext property values that you can access from a message handler—from the client application or Web service—or directly from the WebServiceContext from the Web service. For more information, see the javax.xml.ws.handler.MessageContext Javadocs at http://download.oracle.com/javaee/5/api/javax/xml/ws/handler/MessageContext.html.

Table 4-6 Properties of MessageContext

Property Type Description

HTTP_REQUEST_HEADERS

java.util.Map

Map of HTTP request headers for the request message.

HTTP_REQUEST_METHOD

java.lang.String

HTTP request method for example GET, POST, or PUT.

HTTP_RESPONSE_CODE

java.lang.Integer

HTTP response status code for the last invocation.

HTTP_RESPONSE_HEADERS

java.util.Map

HTTP response headers.

INBOUND_MESSAGE_ATTACHMENTS

java.util.Map

Map of attachments for the inbound messages.

MESSAGE_OUTBOUND_PROPERTY

java.lang.Boolean

Message direction. This property is true for outbound messages and false for inbound messages.

OUTBOUND_MESSAGE_ATTACHMENTS

java.util.Map

Map of attachments for the outbound messages.

PATH_INFO

java.lang.String

Request path information.

QUERY_STRING

java.lang.String

Query string for request.

REFERENCE_PARAMETERS

java.awt.List

WS-Addressing reference parameters. The list must include all SOAP headers marked with the wsa:IsReferenceParameter="true" attribute.

SERVLET_CONTEXT

javax.servlet.ServletContext

Servlet context object associated with request.

SERVLET_REQUEST

javax.servlet.http.HttpServletRequest

Servlet request object associated with request.

SERVLET_RESPONSE

javax.servlet.http.HttpServletResponse

Servlet response object associated with request.

WSDL_DESCRIPTION

org.xml.sax.InputSource

Input source (resolvable URI) for the WSDL document.

WSDL_INTERFACE

javax.xml.namespace.QName

Name of the WSDL interface or port type.

WSDL_OPERATION

javax.xml.namespace.QName

Name of the WSDL operation to which the current message belongs.

WSDL_PORT

javax.xml.namespace.QName

Name of the WSDL port to which the message was received.

WSDL_SERVICE

javax.xml.namespace.QName

Name of the service being invoked.


Should You Implement a Stateless Session EJB?

The jwsc Ant task always chooses a plain Java object as the underlying implementation of a Web service when processing your JWS file.

Sometimes, however, you might want the underlying implementation of your Web service to be a stateless session EJB so as to take advantage of all that EJBs have to offer, such as instance pooling, transactions, security, container-managed persistence, container-managed relationships, and data caching. If you decide you want an EJB implementation for your Web service, then follow the programming guidelines in the following section.

EJB 3.0 introduced metadata annotations that enable you to automatically generate, rather than manually create, the EJB Remote and Home interface classes and deployment descriptor files needed when implementing an EJB. For more information about EJB 3.0, see Programming WebLogic Enterprise JavaBeans, Version 3.0 for Oracle WebLogic Server.

To implement an EJB in your JWS file, perform the following steps:

  • Import the EJB 3.0 annotations, all of which are in the javax.ejb package. At a minimum you need to import the @Stateless annotation. You can also specify additional EJB annotations in your JWS file to specify the shape and behavior of the EJB, see the javax.ejb Javadoc at http://download.oracle.com/javaee/5/api/javax/ejb/package-summary.html for more information.

    For example:

    import javax.ejb.Stateless;
    
  • At a minimum, use the @Stateless annotation at the class level to identify the EJB:

    @Stateless
    public class SimpleEjbImpl {
    

The following example shows a simple JWS file that implement a stateless session EJB. The relevant code is shown in bold.

package examples.webservices.jaxws;

import weblogic.transaction.TransactionHelper;
import javax.ejb.Stateless;
import javax.ejb.SessionContext;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.transaction.SystemException;
import javax.transaction.Status;
import javax.transaction.Transaction;
import javax.xml.ws.WebServiceContext;

/**
* A transaction-awared stateless EJB-implemented JWS
*/

// Standard JWS annotation that specifies that the portName,serviceName and
// target Namespace of the Web Service.
@WebService(
      name = "Simple",
      portName = "SimpleEJBPort",
      serviceName = "SimpleEjbService",
      targetNamespace = "http://wls/samples")

//Standard EJB annotation
@Stateless
public class SimpleEjbImpl {

   @Resource
   private WebServiceContext context;
   private String constructed = null;

   // The WebMethod annotation exposes the subsequent method as a public
   // operation on the Web Service.
   @WebMethod()
   @TransactionAttribute(TransactionAttributeType.REQUIRED)
   public String sayHello(String s) throws SystemException {
      Transaction transaction =     
         TransactionHelper.getTransactionHelper().getTransaction();
      int status = transaction.getStatus();
      if (Status.STATUS_ACTIVE != status)
           throw new IllegalStateException("transaction did not start, 
           status is: " + status + ", check ejb annotation processing");

   return constructed + ":" + s;
}

Programming the User-Defined Java Data Type

The methods of the JWS file that are exposed as Web service operations do not necessarily take built-in data types (such as Strings and integers) as parameters and return values, but rather, might use a Java data type that you create yourself. An example of a user-defined data type is TradeResult, which has two fields: a String stock symbol and an integer number of shares traded.

If your JWS file uses user-defined data types as parameters or return values of one or more of its methods, you must create the Java code of the data type yourself, and then import the class into your JWS file and use it appropriately. The jwsc Ant task will later take care of creating all the necessary data binding artifacts.

Follow these basic requirements when writing the Java class for your user-defined data type:

  • Define a default constructor, which is a constructor that takes no parameters.

  • Define both getXXX() and setXXX() methods for each member variable that you want to publicly expose.

  • Make the data type of each exposed member variable one of the built-in data types, or another user-defined data type that consists of built-in data types.

Note:

You can use JAXB to provide custom mapping. For more information, see "Customizing Java-to-XML Schema Mapping Using JAXB Annotations".

The jwsc Ant task can generate data binding artifacts for most common XML and Java data types. For the list of supported user-defined data types, see Supported User-Defined Data Types. See Supported Built-In Data Types for the full list of supported built-in data types.

The following example shows a simple Java user-defined data type called BasicStruct:

package examples.webservices.complex;
/**
 * Defines a simple JavaBean called BasicStruct that has integer, String,
 * and String[] properties
 */
public class BasicStruct {
  // Properties
  private int intValue;
  private String stringValue;
  private String[] stringArray;
  // Getter and setter methods
  public int getIntValue() {
    return intValue;
  }
  public void setIntValue(int intValue) {
    this.intValue = intValue;
  }
  public String getStringValue() {
    return stringValue;
  }
  public void setStringValue(String stringValue) {
    this.stringValue = stringValue;
  }
  public String[] getStringArray() {
    return stringArray;
  }
  public void setStringArray(String[] stringArray) {
    this.stringArray = stringArray;
  }
}

The following snippets from a JWS file show how to import the BasicStruct class and use it as both a parameter and return value for one of its methods; for the full JWS file, see Sample ComplexImpl.java JWS File:

package examples.webservices.complex;
// Import the standard JWS annotation interfaces
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
// Import the WebLogic-specific JWS annotation interface
// Import the BasicStruct JavaBean
import examples.webservices.complex.BasicStruct;
@WebService(serviceName="ComplexService", name="ComplexPortType",
            targetNamespace="http://example.org")
...
public class ComplexImpl {
  @WebMethod(operationName="echoComplexType")
  public BasicStruct echoStruct(BasicStruct struct)
  {
    return struct;
  }
}

Invoking Another Web Service from the JWS File

From within your JWS file you can invoke another Web service, either one deployed on WebLogic Server or one deployed on some other application server, such as .NET. The steps to do this are similar to those described in Invoking a Web Service from a Java SE Application, except that rather than running the clientgen Ant task to generate the client stubs, you include a <clientgen> child element of the jwsc Ant task that builds the invoking Web service to generate the client stubs instead. You then use the standard JAX-WS APIs in your JWS file, the same as you do for a Java SE client application.

See Invoking a Web Service from a WebLogic Web Service for detailed instructions.

Using SOAP 1.2

WebLogic Web services use, by default, Version 1.1 of Simple Object Access Protocol (SOAP) as the message format when transmitting data and invocation calls between the Web service and its client. WebLogic Web services support both SOAP 1.1 and the newer SOAP 1.2, and you are free to use either version.

To specify that the Web service use Version 1.2 of SOAP, use the class-level @javax.xml.ws.BindingTyp annotation in your JWS file and set its single attribute to the value SOAPBinding.SOAP12HTTP_BINDING, as shown in the following example (relevant code shown in bold):

package examples.webservices.soap12;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.BindingType;
import javax.xml.ws.SOAPBinding;
@WebService(name="SOAP12PortType",
            serviceName="SOAP12Service",
            targetNamespace="http://example.org")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
/**
 * This JWS file forms the basis of simple Java-class implemented WebLogic
 * Web Service with a single operation: sayHello.  The class uses SOAP 1.2
 * as its binding.
 *
 */
public class SOAP12Impl {
  @WebMethod()
  public String sayHello(String message) {
    System.out.println("sayHello:" + message);
    return "Here is the message: '" + message + "'";
  }
}

Other than set this annotation, you do not have to do anything else for the Web service to use SOAP 1.2, including changing client applications that invoke the Web service; the WebLogic Web services runtime takes care of all the rest.

Validating the XML Schema

By default, SOAP messages are not validated against their XML schemas. You can enable XML schema validation for document-literal Web services on the server or client, as described in the following sections. In the event a SOAP message is invalid, a SOAP fault is returned.

Note:

This feature adds a small amount of extra processing to a Web service request.

By default, the stack trace is included in the details of the SOAP fault. To disable the stack trace, see "Disabling the Stack Trace" in Programming Advanced Features of JAX-WS Web Services for Oracle WebLogic Server.

Enabling Schema Validation on the Server

Note:

The com.sun.xml.ws.developer.SchemaValidation API is supported as an extension to the JDK 6.0. Because this API is not provided as part of the JDK 6.0 kit, it is subject to change.

To enable schema validation on the server, add the @SchemaValidation annotation on the endpoint implementation. For example:

import com.sun.xml.ws.developer.SchemaValidation;
import javax.jws.WebService;
@SchemaValidation
@WebService(name="HelloWorldPortType", serviceName="HelloWorldService")
public class HelloWorldImpl {
  public String sayHelloWorld(String message) {
    System.out.println("sayHelloWorld:" + message);
    return "Here is the message: '" + message + "'";
  }
}

You can pass your own validation error handler class as an argument to the annotation, if you want to manage errors within your application. For example:

@SchemaValidation(handler=ErrorHandler.class)

Enabling Schema Validation on the Client

Note:

The com.sun.xml.ws.developer.SchemaValidationFeature API is supported as an extension to the JDK 6.0. Because this API is not provided as part of the JDK 6.0 kit, it is subject to change.

To enable schema validation on the client, create a SchemaValidationFeature object and pass this as an argument when creating the PortType stub implementation.

package examples.webservices.hello_world.client;
import com.sun.xml.ws.developer.SchemaValidationFeature;
import javax.xml.namespace.QName;
import java.net.MalformedURLException;
import java.net.URL;
public class Main {
  public static void main(String[] args) {
    HelloWorldService service;
    try {
      service = new HelloWorldService(new URL(args[0] + "?WSDL"), 
                new QName("http://example.org", "HelloWorldService") );
    } catch (MalformedURLException murl) { throw new RuntimeException(murl); }
      SchemaValidationFeature feature = 
           new SchemaValidationFeature();
       HelloWorldPortType port = service.getHelloWorldPortTypePort(feature);
      String result = null;
      result = port.sayHelloWorld("Hi there!");
      System.out.println( "Got result: " + result );
  }
}

You can pass your own validation error handler as an argument to the SchemaValidationFeature object, if you want to manage errors within your application. For example:

      SchemaValidationFeature feature = 
           new SchemaValidationFeature(MyErrorHandler.class);
       HelloWorldPortType port = service.getHelloWorldPortTypePort(feature);

JWS Programming Best Practices

The following list provides some best practices when programming the JWS file:

  • When you create a document-literal-bare Web service, use the @WebParam JWS annotation to ensure that all input parameters for all operations of a given Web service have a unique name. Because of the nature of document-literal-bare Web services, if you do not explicitly use the @WebParam annotation to specify the name of the input parameters, WebLogic Server creates one for you and run the risk of duplicating the names of the parameters across a Web service.

  • In general, document-literal-wrapped Web services are the most interoperable type of Web service.

  • Use the @WebResult JWS annotation to explicitly set the name of the returned value of an operation, rather than always relying on the hard-coded name return, which is the default name of the returned value if you do not use the @WebResult annotation in your JWS file.