Java SE 6 Web Services
Java Platform Standard Edition 6 (Java SE 6) is officially released towards the end of 2006. The list of the new features is quite long. To cite a few of them:
- Easy to use, end-to-end Web Services stack
- Built-in lightweight HTTP Server
- Scripting support
- Java DB
- JDBC 4.0
- Desktop GUI improvements
- New desktop GUI API
- jconsole enhancements
- jhat (Java Heap Analyser Tool)
- Programmatically controllable compiler
- Pluggable Annotations
Looking at the first item on the list, it is interesting to see that the standard edition now contains a full Web Services stack. The center piece of this stack is JAX-WS 2.0 (Java API for XML Web Service), which is designed to replace JAX-RPC (Java API for XML-based RPC). Java SE 6’s Web Services support also includes JAXB 2.0 (Java Architecture for XML Binding) and SAAJ 1.3 (SOAP with Attachments API for Java).
This new architecture provides an easy way to develop Web Services. Let’s see first how easy to create a service provider and a consumer in Java. Then we’ll see if this approach is really interoperable with a consumer created using .Net 3.0 WCF (Windows Communication Foundation).
Java Server
Let’s create two simple services that accept some parameters and returns a derived response. These services are provided by the methods of a class called StringUtils:
package test.ws;
import javax.jws.WebService;
@WebService
public class StringUtils { public String concatenate(String theFirst, String theSecond) {
return theFirst + theSecond;
}
public String subString(String theString, int theBeginIndex, int theEndIndex) {
return theString.substring(theBeginIndex, theEndIndex);
}
} The @WebService annotation supported by the javax.jws.WebService import indicates to the platform that this class provides Web Services endpoints. By default, both of the methods are deployed as separate operations however @WebMethod annotation can be used to declare methods selectively as Web Service operations.In order to publish the StringUtils class as a Web Service, we can use the new javax.xml.ws.Endpoint class’ publish() static method:
The @WebService annotation supported by the javax.jws.WebService import indicates to the platform that this class provides Web Services endpoints. By default, both of the methods are deployed as separate operations however @WebMethod annotation can be used to declare methods selectively as Web Service operations.In order to publish the StringUtils class as a Web Service, we can use the new javax.xml.ws.Endpoint class’ publish() static method:
package test.ws;
import javax.xml.ws.Endpoint;
public class Program {
public static void main(String[] args) {
Endpoint.publish(”http://localhost:8080/WSExample/StringUtils“, new StringUtils());
}
}
After compiling these classes, we need to use the wsgen tool on them. This tool is part of Java SE 6 Web Services tools and it reads a web service endpoint implementation class in order to generate all the required artifacts for web service deployment and invocation.
> wsgen -cp . -s ../src/java test.ws.StringUtils
-cp specifies where to find the input classes. -s specifies where to put the generated source files (the same way, you can use the -d option to tell wsgen where to create the class files).
Our web service is now ready to run with its two operations. When we run the Program application, we start to use Java SE 6’s built-in lightweight web application server. Then, we can see whether our web service is deployed properly by typing the following URL in our browser:
http://localhost:8080/WSExample/StringUtils?wsdl
This should show us the generated WSDL, which indicates a successful deployment.
Java Client
Now that we have a server (provider) let’s quickly develop a client (consumer). We’re going to use another Java SE 6 Web Services tool, called wsimport. This tool generates JAX-WS portable artifacts. We’re going to point it to our WSDL and let it generate and compile some classes for us:
> wsimport -keep -p test.ws.client -d classes -s src\java http://localhost:8080/WSExample/StringUtils?wsdl
-keep option tells the tool to keep the generated files. -p specifies the target package name. -d and -s indicate where to put, respectively, the generated class files and the generated source files.
Let’s create the client application using the auto-generated StringUtilsService:
package test.ws.client;
public class ClientApp {
public static void main(String[] args) {
//Create an instance of the generated service
StringUtilsService service = new StringUtilsService();
//Get the port
StringUtils proxy = service.getStringUtilsPort();
//Invoke the service operation
String concatString = proxy.concatenate(”It “, “worked!”);
System.out.println(concatString);
}
}
When we compile and run it, we get this self explanatory message:
> It worked!
.Net Client
This whole thing was pretty simple. Even without IDE support, it takes a few minutes to put together this example. But is it interoperable? Can I create a simple .Net client as easily?
For the following example, I’m going to use .Net Framework 3.0 Windows Communication Foundation (WCF). WCF, which was code named indigo, is a technology by which software entities can communicate with one another. It sits on top of .Net Framework 2.0 and adds new artifacts, which makes it 3.0.
In order to create a C# proxy class and an application configuration file, we use the svcutil tool and point it to our WSDL as we did earlier with our Java client:
> svcutil http://localhost:8080/WSExample/StringUtils?wsdl /out:ClientToJava.cs /config:app.config
This command generates the ClientToJava.cs C# file and the app.config configuration file. I edit the configuration file to change the name of the endpoint from StringUtilsPort to StringUtilsEndpoint as I find the term “endpoint” is more appropriate in this context. Then we create a console application to invoke our Web Service operation:
namespace ClientToJava
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine(”Press any key when the service is ready!”);
Console.ReadKey();
string result = null;
using (StringUtilsClient proxy = new StringUtilsClient(”StringUtilsEndpoint”))
{
result = proxy.concatenate(”It works with a”, ” .Net WCF client!”);
proxy.Close();
}
Console.WriteLine(string.Format(”Result: {0}”, result));
Console.WriteLine(”Press any key to exit!”);
Console.ReadKey();
}
}
}
When we run this application, we get:
Press any key when the service is ready!
Result: It works with a .Net WCF client!
Press any key to exit!
And voilà!
Summary
Java SE 6 now contains an easy-to-use Web Service stack. It is very good news to have the JAX-WS 2.0 support in the standard Java platform. And it’s very timely because recently Microsoft officially released .Net Framework 3.0 Windows Communication Foundation (WCF). Both platforms are committed to make developers’ lives easier by simplifying the Web Services development.
- Yagiz Erkan -
Technorati Tags: Java Platform Standard Edition 6, Java SE 6, JAX-WS 2.0, JAX-RPC, JAXB 2.0, SAAJ 1.3, .Net 3.0 WCF, @WebService, @WebMethod, @WebService, @WebMethod, wsgen, wsimport, svcutil, Windows Communication Foundation, WCF