Let's go basic but realistic and implement a "contact us" web service. The idea is that lots of different applications and/or web sites need to have a web-based form to allow end users to contact an admin team (business, tech support, development, whatever) responsible for monitoring such communications. We'll implement a web service so that multiple applications can share it easily. There will be two operations:
As we want to explore more than the barest "Hello, World" functionality, let's create a
Message class that we can pass to the service and that we can get from the
service. This will allow us to play a bit with Java/XML databindings.
Here's the Message class:
package contactus;
import org.apache.cxf.aegis.type.java5.IgnoreProperty;
public final class Message {
private String firstName;
private String lastName;
private String email;
private String text;
public Message() {
}
public Message(String firstName, String lastName, String email, String text) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.text = text;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@IgnoreProperty
public String getLastNameFirstName() {
return lastName + ", " + firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
In real life I might have a bunch of Hibernate annotations in there (I'm a fan of annotation-based configuration), and I would create a DAO. But as this is a tutorial, we'll keep it simple.
If you look carefully, however, you can see that I did in fact include an annotation.
The @IgnoreProperty annotation is part of the Aegis databinding mechanism,
which comes with CXF but is not the default. (JAXB is the default.) I ended up using
Aegis instead of JAXB because JAXB was giving me trouble when I tried to return complex
data types like Message from a web service. Maybe it works and maybe
it doesn't—I don't know—but when I plugged Aegis in it worked immediately and
now I intend to use Aegis. (More on JAXB/Aegis a little later.) Anyway, @IgnoreProperty
tells Aegis that I don't want getLastNameFirstName() to show up in the auto-generated
WSDL. It's just a read-only convenience method.
Now we define a service interface.
package contactus;
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebService;
@WebService
public interface ContactUsService {
List<Message> getMessages();
void postMessage(@WebParam(name = "message") Message message);
}
The @WebService and @WebParam are
JAX-WS
annotations. The first indicates that the interface defines a web service interface
(we'll use it to autogenerate a WSDL) and the second allows us to use an HTTP parameter
called "message" to reference the operation's argument instead of having to call it
"arg0", which is the default.
Here's our simple implementation of the ContactUsService interface.
package contactus;
import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;
@WebService(endpointInterface = "contactus.ContactUsService")
public final class ContactUsServiceImpl implements ContactUsService {
@Override
public List<Message> getMessages() {
List<Message> messages = new ArrayList<Message>();
messages.add(new Message(
"Willie", "Wheeler", "willie.wheeler@xyz.com", "Great job"));
messages.add(new Message(
"Dardy", "Chen", "dardy.chen@xyz.com", "I want my money back"));
return messages;
}
@Override
public void postMessage(Message message) {
System.out.println(message);
}
}
Here the @WebService annotation is marking this class as a web service
implementation, and also specifying that the WSDL should be generated using the
ContactUsService interface.
With that, we have the Java backend for the web service. Let's move on to configuration.