Red Hat Training

A Red Hat training course is available for Red Hat Fuse

35.2. Define SEI and Related Classes

Overview

The Service Endpoint Interface (SEI) is the starting point for implementing a Web service in the Java-first approach. The SEI represents the Web service in Java and it is ultimately used as the basis for generating the WSDL contract. This section describes how to create a sample SEI, the CustomerService interface, which enables you to access the details of a customer's account.

The CustomerService SEI

A JAX-WS service endpoint interface (SEI) is essentially an ordinary Java interface, augmented by certain annotations (which are discussed in the next section). For example, consider the following CustomerService interface, which defines methods for accessing the Customer data type:
// Java
package com.fusesource.demo.wsdl.customerservice;

// NOT YET ANNOTATED!
public interface CustomerService {

    public com.fusesource.demo.customer.Customer lookupCustomer(
        java.lang.String customerId
    );

    public void updateCustomer(
        com.fusesource.demo.customer.Customer cust
    );

    public void getCustomerStatus(
        java.lang.String customerId,
        javax.xml.ws.Holder<java.lang.String> status,
        javax.xml.ws.Holder<java.lang.String> statusMessage
    );
}
After adding the requisite annotations to the CustomerService interface, this interface provides the basis for defining the CustomerService Web service.

javax.xml.ws.Holder<?> types

The getCustomerStatus method from the CustomerService interface has parameters declared to be of javax.xml.ws.Holder<String> type. These so-called holder types are needed in order to declare the OUT or INOUT parameters of a WSDL operation.
The syntax of WSDL operations allows you to define any number of OUT or INOUT parameters, which means that the parameters are used to return a value to the caller. This kind of parameter passing is not natively supported by the Java language. Normally, the only way that Java allows you to return a value is by declaring it as the return value of a method. You can work around this language limitation, however, by declaring parameters to be holder types.
For example, consider the definition of the following method, getStringValues(), which takes a holder type as its second parameter:
// Java
public void getStringValues(
    String wrongWay,
    javax.xml.ws.Holder<String> rightWay
) {
    wrongWay = "Caller will never see this string!";
    rightWay.value = "But the caller *can* see this string.";
}
The caller can access the value of the returned rightWay string as rightWay.value. For example:
// Java
String wrongWay = "This string never changes";
javax.xml.ws.Holder<String> rightWay.value =  "This value *can* change.";

sampleObject.getStringValues(wrongWay, rightWay);

System.out.println("Unchanged string: " + wrongWay);
System.out.println("Changed string: " + rightWay.value);
It is, perhaps, slightly unnatural to use Holder<> types in a Java-first example, because this is not a normal Java idiom. But it is interesting to include OUT parameters in the example, so that you can see how a Web service processes this kind of parameter.

Related classes

When you run the Java-to-WSDL compiler on the SEI, it converts not only the SEI, but also the classes referenced as parameters or return values. The parameter types must be convertible to XML, otherwise it would not be possible for WSDL operations to send or to receive those data types. In fact, when you run the Java-to-WSDL compiler, it is typically necessary to convert an entire tree of related classes to XML using the standard JAXB encoding.
Normally, as long as the related classes do not require any exotic language features, the JAXB encoding should be quite straightforward.

Default constructor for related classes

There is one simple rule, however, that you need to keep in mind when implementing related classes: each related class must have a default constructor (that is, a constructor without arguments). If you do not define any constructor for a class, the Java language automatically adds a default constructor. But if you define a class's constructors explicitly, you must ensure that one of them is a default constructor.

The Customer class

For example, the Customer class appears as a related class in the definition of the CustomerService SEI (the section called “The CustomerService SEI”). The Customer class consists of a collection of String fields and the only special condition it needs to satisfy is that it includes a default constructor:
// Java
package com.fusesource.demo.customer;

public class Customer {
    protected String firstName;
    protected String lastName;
    protected String phoneNumber;
    protected String id;

    // Default constructor, required by JAX-WS
 public Customer() { }
    
    public Customer(String firstName, String lastName, String phoneNumber,
            String id) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.phoneNumber = phoneNumber;
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String value) {
        this.firstName = value;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String value) {
        this.lastName = value;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String value) {
        this.phoneNumber = value;
    }

    public String getId() {
        return id;
    }

    public void setId(String value) {
        this.id = value;
    }
}