You are on page 1of 27

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 Java types are
Technologies mapped to
SOAP XML/WSDL
WSDL String to xsd:string
HTTP BigDecimal[]
and more
Primitive types
JAX-RPC Server Side
The service
endpoint
package helloservice; interface

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
1. compile-service
2. generate-wsdl
3. generate-mapping from service classes
package names to namespace URIs 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
Well examine four options

1. Static stubs
compiled by wscompile before runtime
2. Dynamic stubs
has an interface but fetches the WSDL at runtime
3. Dynamic Invocation Interface
knows no interface - the method names
and signatures
4. A J2EE Application Client
Locate the local web service with JNDI
Client Using a Static Stub
import javax.xml.rpc.Stub; It almost looks like a local call.

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
public class HelloClient { // We have more work to do

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 = MyHelloService


factory.createService(
new QName(qnameService)); HelloIF

QName port = new QName(qnamePort);

The URL and service names are all


specified at runtime
Who we
Call call = service.createCall(port); are calling and
call.setTargetEndpointAddress(args[0]); how is
determined at
call.setProperty(Call.SOAPACTION_USE_PROPERTY, runtime
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);
Make the call
} catch (Exception ex) {
ex.printStackTrace(); 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) {


Ask JNDI for a
reference to a
System.out.println("Endpoint address = " + args[0]);
stub for the object
try {
Context ic = new InitialContext();
MyHelloService myHelloService = (MyHelloService)
ic.lookup("java:comp/env/service/MyJAXRPCHello");
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
The client cannot
package helloservice; see that its interacting
with an EJB
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
package helloservice; also be called using in the traditional
import java.rmi.RemoteException; manner with remote references.
import javax.ejb.SessionBean; No change to the bean would be
import javax.ejb.SessionContext; necessary.

public class HelloServiceBean implements SessionBean {

public String sayHello(String name) {

return "Hello " + name + "from HelloServiceEJB";


}
public HelloServiceBean() {} WSDL can be generated and all
public void ejbCreate() {} of the previous clients will work.
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext sc) {}
}

You might also like