27
JAX-RPC The Java API for XML Remote Procedure Calls Notes from The J2EE Tutorial 1.4 From Sun Microsystems

JAX-RPC The Java API for XML Remote Procedure Calls Notes from The J2EE Tutorial 1.4 From Sun Microsystems

  • View
    226

  • Download
    3

Embed Size (px)

Citation preview

JAX-RPC

The Java API for XML Remote Procedure Calls

Notes from The J2EE Tutorial 1.4 From Sun Microsystems

JAX-RPC Notes

• 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 Server Side

package helloservice;

import java.rmi.Remote;

Import java.rmi.RemoteException;

public interface HelloIF extends Remote { public String sayHello(String s) throws RemoteException;

}

The serviceendpoint interface

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

1. compile-service

2. generate-wsdl

3. 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

1. Static stubs compiled by wscompile before runtime2. Dynamic stubs has an interface but fetches the WSDL at runtime 3. Dynamic Invocation Interface knows no interface - the method names and signatures4. A J2EE Application Client Locate the local web service with JNDI

Client Using a Static Stub

import javax.xml.rpc.Stub;

public class HelloClient {

private String endpointAddress;

public static void main(String[] args) {

System.out.println("Endpoint address = " + args[0]);

It almost looks like a local call.

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

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";

// We have more work to do

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);

The URL and service names are allspecified at runtime

“MyHelloService”

HelloIF

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);

Who we are calling and how is determined at runtime

SOAP details must be specified

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(); } }}

Very carefully prepare the call.

Make the call

Get the result

Harder to program but allowsfor a great deal of flexibility.There is a lot less hard codinggoing on here. A lot of this couldbe chosen by a sophisticated userat runtime

J2EE Application Clientimport 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 areference to astub 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); } } }

From The J2EE Tutorial

From The J2EE Tutorial

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

package helloservice;

import java.rmi.RemoteException;

import java.rmi.Remote;

public interface HelloIF extends Remote {

public String sayHello(String name)

throws RemoteException;

}

The client cannotsee that it’s interactingwith an EJB

The Web Service Session Beanpackage 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) {}}

If we added remote and homeInterfaces then this bean couldalso be called using in the traditionalmanner – with remote references. No change to the bean would be necessary.

WSDL can be generated and allof the previous clients will work.