|
|
||
Doug Kohlert's BlogJanuary 2006 ArchivesEasier Web Service client development with JAX-WSPosted by kohlert on January 31, 2006 at 11:04 AM | Permalink | Comments (0)JAX-WS has simplified the development of Web Service clients when compared to JAX-RPC. Both technologies have a tool for importing a WSDL to generate client side artifacts. JAX-RPC's tool is wscompile, JAX-WS' tool is wsimport.
To use wscompile a config.xml file must be created to
pass to wscompile. A simple config.xml file would look something like:
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl location="http://localhost:8080/helloservice?wsdl"
packageName="helloservice" />
</configuration>
This config.xml would import the WSDL located at http://localhost:8080/helloservice?wsdl"
and place the generated artifacts in the helloservice package.
You would then run wscompile with the following command-line:
wscompile -gen:client config.xmlTo do the same thing with JAX-WS' wsimport
the command-line would be:
wsimport -p helloservice http://localhost:8080/helloservice?wsdlSo with wsimport there is no need for the config.xml file.
The biggest advantage of JAX-WS clients over JAX-RPC clients is portability. JAX-WS generates 100% portable artifacts, while JAX-RPC generated artifacts are not all portable. Also, since JAX-WS is now included in Java SE 6 (Mustang), client applications are much smaller. For a more complete instructions on how to use JAX-WS check out Bobby's articles on Building Web JAX-WS 2.0 Services with NetBeans and Building JAX-WS 2.0 Services with NetBeans and Glassfish. You can get more information about JAX-WS on the JAX-WS project on java.net. JAX-WS is part of the Glassfish Community. Publishing a RESTful Web Service with JAX-WSPosted by kohlert on January 17, 2006 at 12:11 PM | Permalink | Comments (12)The EA3 version of JAX-WS or the JAX-WS released in JWSDP 2.0, supports the publishing and use RESTful Web Services. Here is an example that shows how to publish a RESTful Web Service using JAX-WS. Publishing a RESTful Web Service with JAX-WS starts by creating an implementation of the javax.xml.ws.Provider<T> interface. The Provider interface is the dynamic alternative to a standard endpoint implementation class. It is analogous to the javax.xml.ws.Dispatch interface used on the client. You will notice that Provider<T> is a generic class. It can support Provider<javax.xml.transform.Source> and
Provider<javax.xml.soap.SOAPMessage> with the SOAP/HTTP binding, or Provider<javax.activation.DataSource> and
Provider<javax.xml.transform.Source> with XML/HTTP binding. When creating an
implementation of Provider you choose which form the requests and response messages will be processed by your implementation.
The example Web Service we are going to create is very simple, it will add two numbers and return the result ad we will use Provider<Source> for our Provider implementation and we will use the XML/HTTP binding.
The first step in writing a the AddNumbers Provider implementation is to declare the AddNumbers class.
public class AddNumbersImpl implements ProviderThe next step is to declare a @Resource annotation that will be used by the JAX-WS runtime to inject a WebServiceContext into our AddNumbersImpl instance.
public class AddNumbersImpl implements ProviderThe next step is to implement the T Provider.invoke(T request) method. To do this we will first declared the following method declaration which has a simple try-catch block to handle exceptions. Notice that this method takes a Source object as the request and returns a Source object as the response. This corresponds to the type of Provider that we created.
public class AddNumbersImpl implements ProviderFor this example, the AddNumbers web service will accept requests by extracting the numbers to be added from either the the URL path or from an HTTP query. The query string and path string can be retrieved from the MessageContext which is retrieved from the WebServiceContext wsContext that will be injected into our AddNumbers object. The following code can be used to retrieve the PATH_INFO from the URL and check to see if it is in the proper format.
String path = (String)mc.get(MessageContext.PATH_INFO);
if (path != null && path.contains("/num1") &&
path.contains("/num2")) {
return createResultSource(path);
}
The createResultSource(String str) method simply creates a Source object from a properly formatted MessageContext.PATH_INFO string, by extracting the two numbers to be added from the path and adding them together and calling the createResultSource(int sum)method. The source for these two methods are:
private Source createResultSource(String str) {
StringTokenizer st = new StringTokenizer(str, "=&/");
String token = st.nextToken();
int number1 = Integer.parseInt(st.nextToken());
st.nextToken();
int number2 = Integer.parseInt(st.nextToken());
int sum = number1+number2;
return createResultSource(sum);
}
private Source createResultSource(int sum) {
String body =
"<ns:addNumbersResponse xmlns:ns=\"http://java.duke.org\"><ns:return>"
+sum
+"</ns:return></ns:addNumbersResponse>";
Source source = new StreamSource(
new ByteArrayInputStream(body.getBytes()));
return source;
}
So our example invoke method looks like the following.
public Source invoke(Source source) {
try {
MessageContext mc = wsContext.getMessageContext();
// check for a PATH_INFO request
String path = (String)mc.get(MessageContext.PATH_INFO);
if (path != null && path.contains("/num1") &&
path.contains("/num2")) {
return createResultSource(path);
}
throw new HTTPException(404);
} catch(Exception e) {
e.printStackTrace();
throw new HTTPException(500);
}
}
You will notice that if the proper MessageContext.PATH_INFO is not found, the example throws a HTTPException(404). Instead of throwing this exception, our example endpoint can instead check the query string for the method arguments. Like the MessageContext.PATH_INFO, the query string can be retrieved from the MessageContext with the following code.
String query = (String)mc.get(MessageContext.QUERY_STRING);
Given this we can either pass the query string to the
createResultSource(String str) method which will parse the parameters from the query string or we
can use the standard ServletRequest object to extract the query arguments if we are deploying to a servlet container as we are for this example. If we were to deploy a Java SE based endpoint we would have to use the MessageContext.QUERY_STRING.The following code extracts the num1 and num2 query values, adds them together and invokes the createResultSource(int sum) method to create the Source object that will be returned from the invoke method.
ServletRequest req = (ServletRequest)mc.get(MessageContext.SERVLET_REQUEST);
int num1 = Integer.parseInt(req.getParameter("num1"));
int num2 = Integer.parseInt(req.getParameter("num2"));
return createResultSource(num1+num2);
So far, our AddNumbers class looks like the following.
public class AddNumbersImpl implements ProviderTo finish off the AddNumbers, we need to declare some annotions on the class that instruct the JAX-WS runtime how to use this class. The @WebServiceProvider annotation specifies that this class is a Provider based endpoint rather than a service endpoint implementation class that would be annotated with @WebService. The final annotation we add is @BindingType(value=HTTPBinding.HTTP_BINDING). This annotation specifies that AddNumbers endpoint should be published using the HTTPBinding.HTTP_BINDING as opposed to a
SOAPBinding.SOAP11HTTP_BINDING or a | ||
|
|