Title: JAX-RPC
1JAX-RPC
- The Java API for XML Remote Procedure Calls
- Notes from The J2EE Tutorial 1.4 From Sun
Microsystems
2JAX-RPC Notes
- Based on W3C Technologies
- SOAP
- WSDL
- HTTP
- Java types are mapped to XML/WSDL
- String to xsdstring
- BigDecimal
- and more
- Primitive types
3JAX-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
-
4Implement the service
package helloservice public class HelloImpl
implements HelloIF public String message
"Hello" public String sayHello(String s)
return message s
5Provide a config-interface.xml
- lt?xml version"1.0" encoding"UTF-8"?gt
- ltconfiguration
- xmlns"http//java.sun.com/xml/ns/jax-rpc/ri/con
fig"gt - ltservice
- name"MyHelloService"
- targetNamespace"urnFoo"
- typeNamespace"urnFoo"
- packageName"helloservice"gt
- ltinterface name"helloservice.HelloIF"/gt
- lt/servicegt
- lt/configurationgt
6Three steps to build
- compile-service
- generate-wsdl
- 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
7Behind the Scenes
- The JAX-RPC web service is actually a servlet and
placed in the web tier
8On the client side
- Well 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
-
9Client 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 "
args0) -
-
10try Stub stub createProxy()
stub._setProperty
(javax.xml.rpc.Stub.ENDPOINT_ADDRESS_PROPERTY,
args0) // 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()
11private static Stub createProxy() //
MyHelloService_Impl is created by wscompile
return (Stub) (new MyHelloService_Impl(
).getHelloIFPort())
12Using a Dynamic Stub
// We have more work to do
- public class HelloClient
- public static void main(String args)
- try
- String UrlString args0 "?WSDL"
- String nameSpaceUri "urnFoo"
- String serviceName
"MyHelloService" - String portName "HelloIFPort"
-
13 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
14 dynamicproxy.HelloIF myProxy
(dynamicproxy.Hello
IF)
helloService.getPort( new
QName(nameSpaceUri, portName),
dynamicproxy.HelloIF.clas
s) System.out.println(myProxy.sa
yHello("Buzz")) catch (Exception ex)
ex.printStackTrace()
15Client 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
16public class HelloClient private static
String qnameService "MyHelloService"
private static String qnamePort "HelloIF"
private static String BODY_NAMESPACE_VALUE
"urnFoo" 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/"
17public static void main(String args)
System.out.println("Endpoint address "
args0) 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
18Who we are calling and how is determined at
runtime
Call call service.createCall(port)
call.setTargetEndpointAddress(args0)
call.setProperty(Call.SOAPACTIO
N_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
19Very 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
20J2EE 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 "
args0) - try
- Context ic new InitialContext()
- MyHelloService myHelloService
(MyHelloService) - ic.lookup("javacomp/env/service/M
yJAXRPCHello") -
Ask JNDI for a reference to a stub for the object
21 HelloIF helloPort
myHelloService.getHelloIFPort()
((Stub)helloPort)._setProperty
(Stub.ENDPOINT_ADDRESS_PROPERTY,args0)
System.out.println(helloPort.sayHello("
Jake!")) System.exit(0)
catch (Exception ex)
ex.printStackTrace()
System.exit(1)
22From The J2EE Tutorial
23From The J2EE Tutorial
24The 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.
25A 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
26The Web Service Endpoint Interface
The client cannot see that its 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
-
27The 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.RemoteExcept
ion 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.