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.
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.
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.
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 JAX-B encoding.
Normally, as long as the related classes do not require any exotic language features, the JAX-B encoding should be quite straightforward.
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.
For example, the Customer class appears as a related class in the
definition of the CustomerService SEI (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;
}
}







