34.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;
}
}