280 likes | 395 Views
JAX-RPC. The Java API for XML Remote Procedure Calls Notes from The J2EE Tutorial 1.4 From Sun Microsystems. Based on W3C Technologies SOAP WSDL HTTP. Java types are mapped to XML/WSDL String to xsd:string BigDecimal[] and more… Primitive types. JAX-RPC Notes. JAX-RPC Server Side.
E N D
JAX-RPC The Java API for XML Remote Procedure Calls Notes from The J2EE Tutorial 1.4 From Sun Microsystems
Based on W3C Technologies SOAP WSDL HTTP Java types are mapped to XML/WSDL String to xsd:string BigDecimal[] and more… Primitive types JAX-RPC Notes
JAX-RPC Server Side The service endpoint interface package helloservice; import java.rmi.Remote; Import java.rmi.RemoteException; public interface HelloIF extends Remote { public String sayHello(String s) throws RemoteException; }
Implement the service package helloservice; public class HelloImpl implements HelloIF { public String message ="Hello"; public String sayHello(String s) { return message + s; } }
Provide a config-interface.xml <?xml version="1.0" encoding="UTF-8"?> <configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config"> <service name="MyHelloService" targetNamespace="urn:Foo" typeNamespace="urn:Foo" packageName="helloservice"> <interface name="helloservice.HelloIF"/> </service> </configuration>
Three steps to build • compile-service • generate-wsdl • generate-mapping from service classes package names to namespace URI’s in the WSDL and create ties (skeletons) J2EE1.4 provides an ant task to perform all three steps
Behind the Scenes • The JAX-RPC web service is actually a servlet and placed in the web tier
On the client side We’ll examine four options • Static stubs compiled by wscompile before runtime • Dynamic stubs has an interface but fetches the WSDL at runtime • Dynamic Invocation Interface knows no interface - the method names and signatures • A J2EE Application Client Locate the local web service with JNDI
Client Using a Static Stub It almost looks like a local call. import javax.xml.rpc.Stub; public class HelloClient { private String endpointAddress; public static void main(String[] args) { System.out.println("Endpoint address = " + args[0]);
try { Stub stub = createProxy(); stub._setProperty (javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY, args[0]); // cast the stub to the proper interface HelloIF hello = (HelloIF)stub; // call the methods defined there System.out.println(hello.sayHello("Duke!")); } catch (Exception ex) { ex.printStackTrace(); } }
private static Stub createProxy() { // MyHelloService_Impl is created by wscompile return (Stub) (new MyHelloService_Impl().getHelloIFPort()); } }
Using a Dynamic Stub // We have more work to do public class HelloClient { public static void main(String[] args) { try { String UrlString = args[0] + "?WSDL"; String nameSpaceUri = "urn:Foo"; String serviceName = "MyHelloService"; String portName = "HelloIFPort";
System.out.println("UrlString = " + UrlString); URL helloWsdlUrl = new URL(UrlString); ServiceFactory serviceFactory = ServiceFactory.newInstance(); Service helloService = serviceFactory.createService(helloWsdlUrl, new QName(nameSpaceUri, serviceName)); WSDL is fetched at runtime
dynamicproxy.HelloIF myProxy = (dynamicproxy.HelloIF) helloService.getPort( new QName(nameSpaceUri, portName), dynamicproxy.HelloIF.class); System.out.println(myProxy.sayHello("Buzz")); } catch (Exception ex) { ex.printStackTrace(); } } }
Client Using a Dynamic Invocation Interface import javax.xml.rpc.Call; import javax.xml.rpc.Service; import javax.xml.rpc.JAXRPCException; import javax.xml.namespace.QName; import javax.xml.rpc.ServiceFactory; import javax.xml.rpc.ParameterMode;
public class HelloClient { private static String qnameService = "MyHelloService"; private static String qnamePort = "HelloIF"; private static String BODY_NAMESPACE_VALUE = "urn:Foo"; private static String ENCODING_STYLE_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri"; private static String NS_XSD = "http://www.w3.org/2001/XMLSchema"; private static String URI_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
public static void main(String[] args) { System.out.println("Endpoint address = " + args[0]); try { ServiceFactory factory = ServiceFactory.newInstance(); Service service = factory.createService( new QName(qnameService)); QName port = new QName(qnamePort); “MyHelloService” HelloIF The URL and service names are all specified at runtime
Who we are calling and how is determined at runtime Call call = service.createCall(port); call.setTargetEndpointAddress(args[0]); call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(true)); call.setProperty(Call.SOAPACTION_URI_PROPERTY ""); call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING); QName QNAME_TYPE_STRING = new QName(NS_XSD, "string"); call.setReturnType(QNAME_TYPE_STRING); SOAP details must be specified
Very carefully prepare the call. call.setOperationName( new QName(BODY_NAMESPACE_VALUE,"sayHello")); call.addParameter("String_1", QNAME_TYPE_STRING, ParameterMode.IN); String[] params = { "Murph!" }; String result = (String)call.invoke(params); System.out.println(result); } catch (Exception ex) { ex.printStackTrace(); } } } Make the call Get the result Harder to program but allows for a great deal of flexibility. There is a lot less hard coding going on here. A lot of this could be chosen by a sophisticated user at runtime
J2EE Application Client import javax.xml.rpc.Stub; import javax.naming.*; public class HelloClient { private String endpointAddress; public static void main(String[] args) { System.out.println("Endpoint address = " + args[0]); try { Context ic = new InitialContext(); MyHelloService myHelloService = (MyHelloService) ic.lookup("java:comp/env/service/MyJAXRPCHello"); Ask JNDI for a reference to a stub for the object
HelloIF helloPort = myHelloService.getHelloIFPort(); ((Stub)helloPort)._setProperty (Stub.ENDPOINT_ADDRESS_PROPERTY,args[0]); System.out.println(helloPort.sayHello("Jake!")); System.exit(0); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } } }
The Web Service as an EJB • A Web service client can access J2EE applications in two ways. • First, the client can access a Web service created with JAX-RPC. Behind the scenes, JAX-RPC uses a servlet to implement the Web service. • Second, a Web service client can access a stateless session bean through the service endpoint interface of the bean. Other types of enterprise beans cannot be accessed by Web service clients.
A Stateless Session Bean as a Web Service • The client need not know that its interacting with a Java EJB • It calls the bean like it calls any other web service
The Web Service Endpoint Interface The client cannot see that it’s interacting with an EJB package helloservice; import java.rmi.RemoteException; import java.rmi.Remote; public interface HelloIF extends Remote { public String sayHello(String name) throws RemoteException; }
The Web Service Session Bean If we added remote and home Interfaces then this bean could also be called using in the traditional manner – with remote references. No change to the bean would be necessary. package helloservice; import java.rmi.RemoteException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class HelloServiceBean implements SessionBean { public String sayHello(String name) { return "Hello " + name + "from HelloServiceEJB"; } public HelloServiceBean() {} public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {} public void setSessionContext(SessionContext sc) {} } WSDL can be generated and all of the previous clients will work.