Engineering Full Stack Apps with Java and JavaScript
In this example we will use bottom up approach to develop a simple SOAP based web service and then publish it using a Java SE Endpoint publisher.
We will not be using any server like Glassfish in this example. Note that all the examples can be executed using an application server like Glassfish or a web container like Tomcat or using only core Java as in this example. I wanted to show the different possibilities.
We will create an interface called Service Endpoint Interface (SEI) and an implementation class called Service Implementation Bean (SIB) that implements this interface. This was how web services were created traditionally. However, current standard allows us to create web services using just a POJO with annotations without a separate interface (as we have seen in the Glassfish example).
In this example, we will write a simple example web service for getting the time from server.
Create the Service Endpoint Interface (SEI)
Create the Service Implementation Bean (SIB)
Create a Publisher class using Endpoint publisher
Compile the classes and run the publisher
Create a client to test the web service using the generated wsdl and run the client
In client, first you need create an URL object for the wsdl url.
Then you need to create a QName object (qualified name of the service) using QName constructor
1st argument is the service url, which is the value of targetNamespace attribute of the definitions element in WSDL and
2nd argument is the service name published, which is the value of ‘name’ attribute of the definitions element in the WSDL.
The Service.create() method returns a Service instance.
Calling getPort() on the Service instance (service.getPort()) extract the endpoint interface, the service port, from the service.
The returned port object type is the SEI type and hence you can invoke the portType operations on it.
TimeService.java
package com.javajee.ws.tsexample1;
import javax.jws.WebService;
import javax.jws.WebMethod;
@WebService
public interface TimeService
{
@WebMethod
String getTimeFromServer();
}
TimeServiceImpl.java
package com.javajee.ws.tsexample1;
import java.util.Date;
import javax.jws.WebService;
@WebService(endpointInterface =
"com.javajee.ws.tsexample1.TimeService")
public class TimeServiceImpl implements TimeService{
public String getTimeFromServer(){
return new Date().toString();
}
}
TimeServicePublisher.java
package com.javajee.ws.tsexample1;
import javax.xml.ws.Endpoint;
public class TimeServicePublisher {
public static void main(String[] args)
{
Endpoint endpoint = Endpoint.create(new TimeServiceImpl());
endpoint.publish("http://127.0.0.1:8888/ts");
}
}
You can compile all classes as:
javac com\javajee\ws\tsexample1\*.java
You can execute as:
java com.javajee.ws.tsexample1.TimeServicePublisher
You can now see the generated wsdl by typing below in browser:
You can see the style=document and use=literal in the wsdl denoting that this is a document / literal web service. You can also check the ‘targetNamespace’ and ‘name’ attributes of the definitions element which are needed for configuring a client manually.
TimeClient.java
package com.javajee.ws.tsexample1;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import java.net.URL;
import java.net.MalformedURLException;
class TimeClient {
public static void main(String[] args) throws MalformedURLException
{
URL url = new URL("http://127.0.0.1:8888/ts?wsdl");
QName qname = new
QName("http://tsexample1.ws.javajee.com/","TimeServiceImplService");
Service service = Service.create(url,qname);
TimeService port = service.getPort(TimeService.class);
System.out.println("Current Time = "
+ port.getTimeFromServer());
}
}
You can execute the client class and see the result:
java com.javajee.ws.tsexample1.TimeClient
Try out these and verify the results.
Result:
All classes will compile fine, but execution of the publisher will result in an error:
… com.sun.xml.internal.ws.model.RuntimeModelerException: The Endpoint Interface: … does not have WebService Annotation
Result:
All classes will compile fine, but execution of the publisher will result in an error:
java.lang.IllegalArgumentException: … TimeServiceImpl has neither @WebService nor @WebServiceProvider annotation
Result:
Classes will compile and run fine.
Explanation:
It is not required for the SIB to implement the SEI, after linking SIB to SEI through the webservice annotation’s endpointInterface parameter.
However, it is unsafe not to implement. By having the implements clause, compiler checks whether the SIB implements the methods declared in the SEI.
Result:
Same behaviour
Explanation:
@WebMethod is optional for a method exposed as a web service, but can be used to make a method as not exposed as a web method.
The java.xml.Endpoint class can be used to publish a web service from a simple java application.
Out of the box, the Endpoint publisher handles one request at a time, but can be made multithreaded using an Executor.
The single threaded endpoint publisher is suited for development and the multithreaded one can be used in light production mode.
However a web container such as tomcat is better suited to publish multiple web services in actual production.