This example will lead you through creating your first service with doing "code first" development with JAX-WS.

This example corresponds to the java_first_jaxws example in the CXF distribution.

Setting up your build

The use of Apache Maven is recommended for your web service projects, as it will automatically bring in all necessary dependencies for your web service project. See the Maven pom.xml for this sample for the configuration needed. All samples provided by CXF use Apache Maven, except for the antbuild sample which shows how you can build CXF projects with Apache Ant instead.

The mvn dependency:list and mvn dependency:tree commands from the Maven Dependency Plugin will show all dependencies used by your project.

Writing your Service

First we'll write our service interface. It will have one operation called sayHi which says "Hello" to whoever submits their name.

HelloWorld
@WebService
public interface HelloWorld {

    String sayHi(String text);

    /* Advanced usecase of passing an Interface in.  JAX-WS/JAXB does not
     * support interfaces directly.  Special XmlAdapter classes need to
     * be written to handle them
     */
    String sayHiToUser(User user);

    /* Map passing
     * JAXB also does not support Maps.  It handles Lists great, but Maps are
     * not supported directly.  They also require use of a XmlAdapter to map
     * the maps into beans that JAXB can use.
     */
    @XmlJavaTypeAdapter(IntegerUserMapAdapter.class)
    Map<Integer, User> getUsers();
} 

To make sure your parameter is named correctly in the xml you should use:

@WebService public interface HelloWorld { String sayHi(@WebParam(name="text") String text); }

The @WebParam annotation is necessary as java interfaces do not store the Parameter name in the .class file. So if you leave out the annotation your parameter will be named arg0.

Our implementation will then look like this:

HelloWorldImpl
package demo.hw.server;

import java.util.LinkedHashMap;
import java.util.Map;
import javax.jws.WebService;

@WebService(endpointInterface = "demo.hw.server.HelloWorld",
            serviceName = "HelloWorld")
public class HelloWorldImpl implements HelloWorld {

    Map<Integer, User> users = new LinkedHashMap<Integer, User>();

    public String sayHi(String text) {
        System.out.println("sayHi called");
        return "Hello " + text;
    }

    public String sayHiToUser(User user) {
        System.out.println("sayHiToUser called");
        users.put(users.size() + 1, user);
        return "Hello "  + user.getName();
    }

    public Map<Integer, User> getUsers() {
        System.out.println("getUsers called");
        return users;
    }
}

 

The @WebService annotation on the implementation class lets CXF know which interface we want to create our WSDL with. In this case its simply our HelloWorld interface.

Publishing your service

Server
HelloWorldImpl implementor = new HelloWorldImpl();
String address = "http://localhost:9000/helloWorld";
Endpoint.publish(address, implementor);

whole code at https://github.com/apache/cxf/blob/master/distribution/src/main/release/samples/java_first_jaxws/src/main/java/demo/hw/server/Server.java

Alternatively you can use the following code. This gives you more control over the behaviour. For example you can add a logging interceptor:

ServerFactoryBean
HelloWorldImpl implementor = new HelloWorldImpl(); 
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); 
svrFactory.setServiceClass(HelloWorld.class); 
svrFactory.setAddress("http://localhost:9000/helloWorld"); 
svrFactory.setServiceBean(implementor); 
svrFactory.create();

You could leave out the ServiceClass. But it is better to use it so the server and the client are created from the same interface. If you instead only use the implementation class subtle problems may occur.

Pointing your browser at http://localhost:9000/helloWorld?wsdl will display the wsdl for this service

Accessing your service

and client code to see it working is at https://github.com/apache/cxf/blob/master/distribution/src/main/release/samples/java_first_jaxws/src/main/java/demo/hw/client/Client.java

For the client there is also the alternative approach that gives you more flexibility:

Client
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 
factory.setServiceClass(HelloWorld.class); 
factory.setAddress("http://localhost:9000/helloWorld"); 
HelloWorld client = (HelloWorld) factory.create(); 
String reply = client.sayHi("HI"); 
System.out.println("Server said: " + reply); 
  • No labels

5 Comments

  1. Using the @WebParam annotation in HelloWorld#sayHi() requires the import javax.jws.WebParam.

  2. "Publishing your service" is not clear to me. The sample code contains a main(). Is it to be run stand alone? Should the Service class be deployed in the application container? Is it a servlet? An explanation WHAT is being done would be very helpful. This is very much on the HOW level.

    Thanks, Rainer

    1. Answering my question, I realized that one has to look for JAX-WS endpoint deployment. Still, an explanation of the necessities regarding the deployment, like what has to go into web.xml, and how the classes and resources are related would be very helpful.

        1. I will try that tutorial as well. However, two basic problems are shared by most tutorials:
          a) Focus on how to do stuff, not the what and why. Figuring out the (config) prerequisites, cross references and dependencies is quite laborious. E.g. I would like to know the mechanics of a SOAP client that instantiates a Service, and creates an object with getPort().
          b) Most tutorials have dependencies, like maven, ant, eclipse, spring, OSGi. To understand the very topic, it would be good not to have that in the way.