• No results found

Create a client application using these artifacts

In document OCEWSD6_StudyGuide_MikalaiZaikin (Page 39-43)

Chapter 6. Create a web service client for a SOAP based web service 6.1. Create a standalone client

6.1.2. Create a client application using these artifacts

Int egers are defined as basic t ypes provided w it h XML Schema; t hey are not cust om t ypes t hat you have w rit t en t hat require somet hing special. T he complex t ype t hat w raps t hese t w o int egers is creat ed in order t o mat ch your W SDL, w hich uses t he document/literal st yle. Here is t he port ion of t he W SDL t hat t ells you t his:

<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"></soap:binding>

<operation name="add">

<soap:operation soapAction=""></soap:operation>

<input>

<soap:body use="literal"></soap:body>

</input>

...

</operation>

Had you been using RPC and not document , t he values w ould have been passed separat ely t o t he operat ion invocat ion just like met hod paramet ers.

T he @RequestWrapper and @ResponseWrapper annot at ions capt ure informat ion t hat JAXB needs t o perform t he marshaling and unmarshaling operat ions. If your service is defined as using document/literal mode, t his annot at ion also serves t o resolve overloading conflict s.

6.1.2. Create a client application using these artifacts.

Here are t he st eps in t heir simplest form.

First , w rit e t he invoker called CalculatorInvoker.java. Navigat e t o t he t op-level direct ory t hat you passed t o t he wsimport t ool earlier. T his w as "/home/mz". You w ill w rit e your client t here.

import org.me.calculator.*;

public class CalculatorInvoker {

public static void main(String... arg) {

CalculatorWSService service = new CalculatorWSService();

CalculatorWS port = service.getCalculatorWSPort();

int result = port.add(2, 3);

System.out.println("Result: " + result);

} }

T he class in ecxample above simply creat es a service inst ance, uses it t o get t he port , and uses t he port t o call t he business met hod, add. Let 's compile it , making sure t he generat ed classes in t he current direct ory are on your classpat h:

>javac -cp . CalculatorInvoker.java

T hen you can run it :

>java -cp . CalculatorInvoker Result: 5

T here are a few considerat ions t o keep in mind w it h using generat ed client s:

T he client cannot creat e or dest roy w eb service implement at ions and has no view int o it s life cycle, w hich is handled ent irely on t he server.

A port object has no ident it y. It cannot meaningfully be compared t o ot her port object s. You cannot ask for a specific inst ance of a port . Treat service invocat ions as st at eless. T here is no mechanism w it hin Service t o handle st at e across request s.

All dat a binding is performed by JAXB.

6.1.2.1. Invoke web service synchronously or asynchronously.

Synchronous client s

By using t he synchronous model, you can develop SOAP-based w eb service client code w it hout w orrying about t he underlying prot ocol det ails. Example below show s generat ed Service subclass:

package by.boot.java;

import java.net.MalformedURLException;

import java.net.URL;

import javax.xml.namespace.QName;

name = "HelloMessengerService",

targetNamespace = "http://java.boot.by/",

wsdlLocation = "http://localhost:9999/Hello?wsdl") public class HelloMessengerService extends Service {

private final static URL HELLOMESSENGERSERVICE_WSDL_LOCATION;

static {

HELLOMESSENGERSERVICE_WSDL_LOCATION = url;

}

public HelloMessengerService(URL wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName);

}

public HelloMessengerService() {

super(HELLOMESSENGERSERVICE_WSDL_LOCATION,

new QName("http://java.boot.by/", "HelloMessengerService"));

}

@WebEndpoint(name = "HelloMessengerPort") public HelloMessenger getHelloMessengerPort() { return (HelloMessenger) super.getPort(

new QName("http://java.boot.by/", "HelloMessengerPort"), HelloMessenger.class);

}

@WebEndpoint(name = "HelloMessengerPort")

public HelloMessenger getHelloMessengerPort(WebServiceFeature... features) { return (HelloMessenger) super.getPort(

new QName("http://java.boot.by/", "HelloMessengerPort"), HelloMessenger.class,

features);

} }

You can t ell t hat class above is a JAX-W S-generat ed client because of it s class-level @WebServiceClient annot at ion. T he class has t w o const ruct ors:

T he first const ruct or is t he default const ruct or. It configures t he service so t hat any dynamic proxies creat ed from it are produced by using t he W SDL document t hat w as used t o generat e t he client code.

In t he HelloMessenger example, t he t ool w as not inst ruct ed t o creat e a local copy of t he W SDL document . T his is w hy t here is an absolut e reference t o t he act ual URL at w hich t he Endpoint publisher makes t he W SDL document available. Because t his is not recommended, make sure t hat you generat e t he w eb service client code so t hat it is copied t o t he client .

One of t he implicat ions of not having a local W SDL document is t hat t he const ruct or t hrow s an except ion in cases w here t he JAX-W S run t ime cannot connect t o t he server t hat is exposing t he document .

T he second const ruct or init ializes t he service by using a specified W SDL document .

In addit ion t o t hese t w o const ruct ors, t he generat ed client has a couple of getHelloMessenger met hods w it h w hich you can get a dynamic proxy t hat binds t o t he specified w eb service endpoint . T he client uses t he default const ruct or t o connect t o inst ant iat e t he w eb service:

HelloMessengerService service = new HelloMessengerService();

T his approach can present a problem w hen you w ant t he client applicat ion t o sw it ch from t he t est environment 's w eb service endpoint t o t he product ion environment 's w eb service endpoint . T here are a couple of w ays t o override t his endpoint locat ion from your client code:

Use t he overloaded const ruct or of t he generat ed javax.xml.ws.Service subclass t hat t akes anot her W SDL document locat ion. T his supplied W SDL document can, in t urn, specify t he service endpoint locat ion of int erest .

Use t he default const ruct or, but specify t he endpoint locat ion on t he dynamic proxy ret urned by t he service.

Aft er t he HelloClient applicat ion has obt ained a HelloMessengerService inst ance, it uses t hat inst ance t o obt ain a dynamic st ub, w hich binds t o t he act ual w eb service endpoint . Example below show s t he generat ed w eb service client t ype t hat is implement ed by t he st ub:

import javax.xml.bind.annotation.XmlSeeAlso;

@WebResult(targetNamespace = "") @RequestWrapper(localName = "sayHello", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHello")

@ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHelloResponse") public String sayHello(

@WebParam(name = "arg0", targetNamespace = "") String arg0);

}

T he HelloMessenger t ype is an ordinary Java int erface w it h some JAX-W S-specific annot at ions. Alt hough t he ret urn t ype of t he HelloMessengerService is of t his int erface t ype, in realit y w hat is ret urned is a dynamic st ub t hat implement s t his int erface.

Example below show s a HelloMessenger client applicat ion t hat explicit ly specifies, on t he dynamic st ub, a new w eb service endpoint locat ion:

import by.boot.java.HelloMessenger;

import by.boot.java.HelloMessengerService;

import javax.xml.ws.BindingProvider;

public class HelloClientCustomEndpoint {

public static void main(String... args) throws Exception { HelloMessengerService service = new HelloMessengerService();

HelloMessenger port = service.getHelloMessengerPort();

((BindingProvider)port).getRequestContext().put(

BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://hello.com:69693/Hello"

);

String message = port.sayHello("Mikalai");

System.out.println(message);

} }

T he client -relevant code is highlight ed in bold. T he applicat ion cast s t he dynamic w eb service port proxy t o a javax.xml.ws.BindingProvider. T he BindingProvider is implement ed by t he dynamic client proxies and gives you access t o t he request and t he response cont ext s. T he applicat ion specifies t he endpoint address on t he request cont ext using t he BindingProvider.ENDPOINT_ADDRESS_PROPERTY propert y.

Asynchronous client s

T he asynchronous client programming model in JAX-W S is merely a convenient funct ionalit y for developing w eb service client s. It does not refer t o real asynchronous message exchanges. You can creat e asynchronous client s by configuring t he t ool t hat you use t o generat e JAX-W S w eb service client code.

JAX-W S offers t w o asynchronous programming models:

Polling client s.

Callback client s.

T hese approaches merely different iat e, in t he Java met hod, signat ures t hat are generat ed on t he client -side w eb service port int erface. W hen you enable asynchronous client s in your t ool, JAX-W S generat es t hree met hods for every operat ion t hat is defined in t he w eb service portType:

One-w ay asynchronous met hod.

An asynchronous polling met hod.

An asynchronous callback met hod.

Example below show s t he HelloMessenger client -side endpoint int erface t hat is generat ed w hen asynchronous met hod generat ion is act ivat ed by t he JAX-W S t ool:

package by.boot.java;

@WebService(name = "HelloMessenger", targetNamespace = "http://java.boot.by/")

@XmlSeeAlso({

ObjectFactory.class })

public interface HelloMessenger {

@WebMethod(operationName = "sayHello") @RequestWrapper(localName = "sayHello", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHello")

@ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHelloResponse") public Response<SayHelloResponse> sayHelloAsync(

@WebParam(name = "arg0", targetNamespace = "") String arg0);

@WebMethod(operationName = "sayHello") @RequestWrapper(localName = "sayHello", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHello")

@ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHelloResponse") public Future<?> sayHelloAsync(

@WebParam(name = "arg0", targetNamespace = "") String arg0,

@WebParam(name = "asyncHandler", targetNamespace = "") AsyncHandler<SayHelloResponse> asyncHandler);

@WebMethod

@WebResult(targetNamespace = "") @RequestWrapper(localName = "sayHello", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHello")

@ResponseWrapper(localName = "sayHelloResponse", targetNamespace = "http://java.boot.by/", className = "by.boot.java.SayHelloResponse") public String sayHello(

@WebParam(name = "arg0", targetNamespace = "") String arg0);

}

T he met hod signat ures are highlight ed in bold. T he first signat ure is used t o creat e asynchronous polling client s. T he second signat ure is used t o creat e asynchronous callback client s. T he t hird signat ure is used t o creat e synchronous client s and is t he signat ure t hat is used by t he HelloClient applicat ion.

Polling clients

T he polling client programming model refers t o t he usage of t he asynchronous met hod t hat ret urns a t yped javax.xml.ws.Response. Example below show s an asynchronous HelloMessenger w eb service client applicat ion:

import javax.xml.ws.Response;

import by.boot.java.HelloMessenger;

import by.boot.java.HelloMessengerService;

import by.boot.java.SayHelloResponse;

public class HelloAsyncPollingClient {

public static void main(String... args) throws Exception { HelloMessengerService service = new HelloMessengerService();

HelloMessenger port = service.getHelloMessengerPort();

Response<SayHelloResponse> sayHelloAsync = port.sayHelloAsync("Mikalai");

while ( ! sayHelloAsync.isDone() ) { // Do something useful for now }

// Web service endpoint has now responded:

SayHelloResponse sayHelloResponse = sayHelloAsync.get();

String message = sayHelloResponse.getReturn();

System.out.println(message);

} }

T he relevant code is highlight ed in bold. T he client applicat ion invokes t he sayHelloAsync met hod, w hich ret urns a response object . T his object provides met hods t o query for response arrival, cancel a response, and get t he act ual response. T he applicat ion, in t his case, performs a busy w ait , looping unt il t he Response.isDone() met hod ret urns true, w hich indicat es t hat t he response has been received. T he applicat ion t hen fet ches t he response by using t he get() met hod. T his met hod ret urns t he response w rapper element t hat cont ains t he act ual met hod ret urn value, w hich in t his case is a simple java.lang.String object . If an endpoint t hrow s a service except ion, t he get() met hod can t hrow a java.util.concurrent.ExecutionException, w hich can t hen be queried for t he cause.

Callback clients

T he callback client programming model refers t o t he usage of t he asynchronous met hod t hat accept s an input paramet er of a t yped javax.xml.ws.AsyncHandler. Example below show s an asynchronous callback HelloMessenger w eb service client applicat ion:

import by.boot.java.HelloMessenger;

import by.boot.java.HelloMessengerService;

import by.boot.java.SayHelloResponse;

import javax.xml.ws.AsyncHandler;

import javax.xml.ws.Response;

public class HelloAsyncCallbackClient {

public static void main(String... args) throws Exception { HelloMessengerService service = new HelloMessengerService();

HelloMessenger port = service.getHelloMessengerPort();

port.sayHelloAsync("Mikalai", new AsyncHandler<SayHelloResponse>() { public void handleResponse(Response<SayHelloResponse> res) { try {

SayHelloResponse response = res.get();

String message = response.getReturn();

System.out.println(message);

} catch (Exception e) { e.printStackTrace();

} } });

} }

T he applicat ion passes in an anonymous inner class of t ype AsyncHandler. T his class has a met hod called handleResponse t hat is invoked by t he JAX-W S runt ime w hen t he message is received. T he argument t o t his met hod is of t he same t ype t hat is used for t he polling met hod, a t yped response object .

Example above does not show t hat you can save t he ret urn value of t he asynchronous met hod invocat ion int o a java.util.concurrent.Future:

Future<?> future = port.sayHelloAsync("Mikalai", ...);

As is t he case w it h t he polling response object , you can query t his object t o obt ain st at us and possibly cancel t he operat ion.

In document OCEWSD6_StudyGuide_MikalaiZaikin (Page 39-43)