copyright 2009 Trainologic LTD
Abstracting the Protocols
Spring Remoting
copyright 2009 Trainologic LTD
Spring Remoting
Introduction
Remoting by RMI
Remoting by Hessian or Burlap
Remoting by HTTP Invokers
Web Services
Remoting by JMS
Introduction
3
copyright 2009 Trainologic LTD
Spring Remoting
Remoting is an application feature by which an object is
exposed for remote invocations.
As we are going to see, Spring supports several
remoting protocols (e.g., RMI, JMS).
Remoting is easily done with Spring; it usually requires
changes only in the xml configuration file.
Remoting
3
4
copyright 2009 Trainologic LTD
Spring Remoting
Without Spring, the remoting logic is mixed with the
business logic.
For example, when using RMI, the remote object needs
to implement the Remote interface.
It also needs to be exposed by using the
UnicastRemoteObject.
The same goes for the other protocols.
Remoting without Spring
4
5
copyright 2009 Trainologic LTD
Spring Remoting
Using the Spring framework for remoting introduces the
following benefits:
Protocol associated code doesnt appear in the source
code.
The wiring logic appears solely in the XML
configuration files.
It is possible to switch between different remoting
protocols without changing the source code!
Using Springs Remoting
5
copyright 2009 Trainologic LTD
Spring Remoting
Introduction
Remoting by RMI
Remoting by Hessian or Burlap
Remoting by HTTP Invokers
Web Services
Remoting by JMS
Remoting by RMI
77
copyright 2008 trainologic LTD
Spring Remoting
RMI stands for: Remote Method Invocation.
RMI is used for making invocations on a remote object.
A remote object is an object which resides on a different
JVM than the calling object.
Hence, we cant have a direct reference to this object.
RMI Recap
7
77
copyright 2008 trainologic LTD
Spring Remoting
Making remote invocations is not a simple task.
You have to manage socket connections, serialization of
method parameters, deserialization and the same for the
returned value.
Moreover, an object sent as a parameter may be a large
object graph.
RMI eliminates the need to handle serialization &
networking for remote invocations.
Motivation for RMI
8
77
copyright 2008 trainologic LTD
Spring Remoting
The RMI architecture:
Diagram
9
Client Server
Interface Interface
Remote Object
S
k
e
l
e
t
o
n
S
t
u
b
77
copyright 2008 trainologic LTD
Spring Remoting
As you can see, two classes implement the business
interface:
The remote object implementation (the business
object).
The stub.
What is this stub anyway?
Discussion
10
77
copyright 2008 trainologic LTD
Spring Remoting
The Stub represents the remote object on the client
machine.
The stub is responsible for the network transportation of
the invocation.
From the clients point-of-view, it invokes a local
method.
The Stub communicates with the skeleton which is a
server-side proxy responsible for network management
& serialization at the server side.
They are automatically generated.
Stubs & Skeletons
11
77
copyright 2008 trainologic LTD
Spring Remoting
How can the client get hold of the Stub?
By the use of rmiregistry.
The server should bind the remote object to the
rmiregistry under a specific name.
Then, the client will lookup the object by the name.
Lets see how it works
The Registry
12
77
copyright 2008 trainologic LTD
Spring Remoting
The Server Side (without Spring)
13
// This is the remote object's interface
public interface Greeter extends Remote {
// / all methods must declared throwing RemoteException
String greet(User user) throws RemoteException;
}
// Extending the UnicastRemoteObject for network handling
public class GreeterImpl extends UnicastRemoteObject implements
Greeter {
// Must explicitly declare the constructor because of exception
// handling.
protected GreeterImpl() throws RemoteException {
super();
}
public String greet(User user) {
return "Hello " + user.getName();
}
}
77
copyright 2008 trainologic LTD
Spring Remoting
The Server Side (without Spring)
14
// Must be Serializable
public class User implements Serializable {
private String name;
private int age;
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
public static void main(String[] args) throws Exception {
Greeter greet = new GreeterImpl();
Naming.bind("greeter", greet);
}
77
copyright 2008 trainologic LTD
Spring Remoting
As you can see, RMI has some rules:
The remote interface must extend java.rmi.Remote.
All remote interface methods must declare throwing
RemoteException.
The parameter classes must be Serializable.
The implementation class must either extend
UnicastRemoteObject (as shown) or, when creating
the object, the static method exportObject() should
be invoked.
Discussion
15
77
copyright 2008 trainologic LTD
Spring Remoting
The Client Side (without Spring)
16
public static void main(String[] args) throws Exception {
Greeter greeter = (Greeter) Naming.lookup("greeter");
User user = new User();
user.setAge(31);
user.setName("Shimi");
System.out.println(greeter.greet(user));
}
The client is very simple:
17
copyright 2009 Trainologic LTD
Spring Remoting
Spring allows you to expose a POJO by RMI.
This is done only in the xml configuration file.
Spring provides the RmiServiceExporter class which
exports the POJO over RMI.
Lets see an example
RMI with Spring
17
18
copyright 2009 Trainologic LTD
Spring Remoting
We are going to expose the following POJO:
The Remote Object
18
public interface Crier {
String cry();
}
public class CrierImpl implements Crier {
private String cry;
public void setCry(String cry) {
this.cry = cry;
}
@Override
public String cry() {
return cry;
}
}
19
copyright 2009 Trainologic LTD
Spring Remoting
The Configuration File
19
<beans >
<bean name="crier"
class="com.trainologic.examples.spring.remoting.CrierImpl">
<property name="cry" value="Wolf Wolf" />
</bean>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<property name="serviceName" value="CrierService" />
<property name="service" ref="crier" />
<property name="serviceInterface"
value="com.trainologic.examples.spring.remoting.Crier" />
<property name="registryPort" value="1199" />
</bean>
</beans>
20
copyright 2009 Trainologic LTD
Spring Remoting
The RmiServiceExporter has the following configuration
properties:
serviceName the name of the remote object by
which the binding in the rmiregistry will be done.
service a reference to the Spring bean that is to be
exported.
serviceInterface specifies which interface to
expose.
registryPort the port on which the rmiregistry
listens.
RmiServiceExporter
20
21
copyright 2009 Trainologic LTD
Spring Remoting
Wait a sec.
Do I need to start a rmiregisty in order for the example
to work?
Well, no!
If Spring doesnt find a rmiregistry it will create a new
one (you will see it in the log).
The default rmiregistry port is: 1099.
The rmiregistry
21
22
copyright 2009 Trainologic LTD
Spring Remoting
We finished writing the server.
When the ApplicationContext is created, the POJO will be
available by RMI.
RMI clients can now safely work with the object.
However, if you are using Spring on the client side, it
becomes very easy to consume the service.
Lets see how its done
The Client
22
23
copyright 2009 Trainologic LTD
Spring Remoting
The Client Configuration File
23
<beans >
<bean id="crierService"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"
value="rmi://localhost:1199/CrierService" />
<property name="serviceInterface"
value="com.trainologic.examples.spring.remoting.Crier" />
</bean>
</beans>
24
copyright 2009 Trainologic LTD
Spring Remoting
The client code is simplicity itself:
The Client Code
24
public static void main(String[] args) {
BeanFactory factory = new FileSystemXmlApplicationContext(
"applicationContext.xml");
Crier c = (Crier) factory.getBean("crierService");
System.out.println(c.cry());
}
copyright 2009 Trainologic LTD
Spring Remoting
Introduction
Remoting by RMI
Remoting by Hessian or Burlap
Remoting by HTTP Invokers
Web Services
Remoting by JMS
Remoting by Hessian or Burlap
26
copyright 2009 Trainologic LTD
Spring Remoting
Hessian is a binary web services protocol.
It was developed by Caucho.
The Hessian protocol is very compact and simple. Its
well suited for applications that need high performance.
Burlap is the XML equivalent for the Hessian protocol.
Burlap is a simple subset of XML and its main purpose is
to allow EJBs to interoperable with non-Java servers.
The Hessian & Burlap Protocols
26
27
copyright 2009 Trainologic LTD
Spring Remoting
Because they work on HTTP, both Hessian and Burlap
require a Servlet container.
For exporting beans over the Hessian or Burlap
protocols, you need to use Spring MVC
DispatcherServlet (covered in the Spring MVC chapter).
Lets see an example of this definition in the web.xml
The Hessian & Burlap Protocols
27
28
copyright 2009 Trainologic LTD
Spring Remoting
Configuring the DispatcherServlet
28
<web-app ...>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
</web-app>
29
copyright 2009 Trainologic LTD
Spring Remoting
In this example, the application context file will be
named: dispatcher-servlet.xml.
Now, we can export a bean in this file over the Hessian/
Burlap protocols.
Lets see an example of exporting a bean over both
protocols
Exporting our Beans
29
30
copyright 2009 Trainologic LTD
Spring Remoting
dispatcher-servlet.xml
30
<?xml version="1.0" encoding="UTF-8"?>
<beans >
<bean name="echo" class="com.trainologic...EchoImpl" />
<bean name="/remoting/samplehessian.do"
class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="echo" />
<property name="serviceInterface" value="com.trainologicEcho" />
</bean>
<bean name="/remoting/sampleburlap.do"
class="org.springframework.remoting.caucho.BurlapServiceExporter">
<property name="service" ref="echo" />
<property name="serviceInterface" value="com.trainologicEcho" />
</bean>
</beans>
31
copyright 2009 Trainologic LTD
Spring Remoting
The same as with RMI, we use Springs proxy factory
beans to connect to Hessian/Burlap services:
Client Side
31
<bean id="echoService1"
class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<property name="serviceUrl"
value="http://remotehost:8080/remoting/samplehessian.do" />
<property name="serviceInterface" value="...Echo" />
</bean>
<bean id="echoService2"
class="org.springframework.remoting.caucho.BurlapProxyFactoryBean">
<property name="serviceUrl"
value="http://remotehost:8080/remoting/sampleburlap.do" />
<property name="serviceInterface" value="...Echo" />
</bean>
copyright 2009 Trainologic LTD
Spring Remoting
Introduction
Remoting by RMI
Remoting by Hessian or Burlap
Remoting by HTTP Invokers
Web Services
Remoting by JMS
Remoting by HTTP Invokers
33
copyright 2009 Trainologic LTD
Spring Remoting
Hessian and Burlap are lightweight protocols.
They do not support serialization of complex object
graphs.
Springs HTTP Invokers rely on the standard Java
serialization and provides the serialization over HTTP.
Exposing the service and connecting from the client is
very similar to the previously shown protocols
HTTP Invokers
33
34
copyright 2009 Trainologic LTD
Spring Remoting
Example
34
<bean name="/remoting/samplehttpinvoker.do class="org
remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="service" ref="echo" />
<property name="serviceInterface" value="com.trainologicEcho" />
</bean>
Server side:
Client side:
<bean id="echoService3"
class="orgremoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl"
value="http://remotehost:8080/remoting/samplehttpinvoker.do" />
<property name="serviceInterface" value="...Echo" />
</bean>
35
copyright 2009 Trainologic LTD
Spring Remoting
Note that Http Invokers mandate not only a Java-to-Java
architecture, but also Spring on both sides.
Note that there are known issues in using Hessian/
Burlap with Hibernate objects that contain lazy-
initialized collections. Prefer Http Invokers in these
cases.
Discussion
35
copyright 2009 Trainologic LTD
Spring Remoting
Introduction
Remoting by RMI
Remoting by Hessian or Burlap
Remoting by HTTP Invokers
Web Services
Remoting by JMS
Web Services
37
copyright 2009 Trainologic LTD
Spring Remoting
Spring supports both JAX-RPC and JAX-WS standards.
JAX-RPC is the old Java standard which focuses on the
RPC aspect of web services.
In JavaEE 5 and JavaSE 6 it was replaced by JAX-WS.
We will focus on JAX-WS in this section.
For more information about Springs integration with
JAX-RPC, please consult the documentation.
Web Service & Spring
37
38
copyright 2009 Trainologic LTD
Spring Remoting
In order to export your bean as a JAX-WS Web Service,
you need to provide a dedicated endpoint class.
Lets see it by an example.
Were going to export the following class as a Web
Service:
Exporting a Service
38
public class EchoImpl implements Echo {
public String echo(String msg) {
System.out.println(msg);
return msg;
}
39
copyright 2009 Trainologic LTD
Spring Remoting
The Endpoint Class
39
@WebService(serviceName = "echoService")
public class WSSample extends SpringBeanAutowiringSupport {
@Autowired
private Echo echoImpl;
@WebMethod
public String echo(String msg) {
return echoImpl.echo(msg);
}
}
Spring provides a convenience utility class for providing
autowiring for your endpoint classes:
40
copyright 2009 Trainologic LTD
Spring Remoting
All that is left to do now is to start the Web Service.
Note that Spring doesnt come with its own JAX-WS
implementation.
So, whether you use JAX-WS RI, AXIS2, Apache CXF,
etc., you must consult the documentation regarding how
to start the Web Service.
It is important to remember that the JAX-WS framework
will manage the life-cycle of the Web Service.
Spring will provide the dependencies.
Exposing the Service
40
41
copyright 2009 Trainologic LTD
Spring Remoting
Like before, accessing a Web Service is done by a
dedicated ProxyFactorybean.
Example:
Accessing a Web Service
41
<bean id="echoService4"
class="orgremoting.jaxws.JaxWsPortProxyFactoryBean ">
<property name=wsdlDocumentUrl"
value="http://remotehost:8080/remoting/samplews?wsdl" />
<property name="serviceInterface" value="...Echo" />
<property name=namespaceURI"
value=http://www.trainologic.com/examples/ws" />
<property name="serviceName" value=EchoService" />
<property name=portName" value=EchoPort" />
</bean>
copyright 2009 Trainologic LTD
Spring Remoting
Introduction
Remoting by RMI
Remoting by Hessian or Burlap
Remoting by HTTP Invokers
Web Services
Remoting by JMS Remoting by JMS
43
copyright 2009 Trainologic LTD
Spring Remoting
Springs support for JMS is discussed in a separate
chapter.
Here well focus on JMS remoting.
The main advantages of using JMS for remoting is the
clustering support and load-balancing that is native to
the messaging software.
Note that Springs support is pretty basic and sending
and receiving is done on the same thread in the same
non-transactioned session.
JMS Remoting
43
44
copyright 2009 Trainologic LTD
Spring Remoting
Server Side Configuration
44
<!-- exporting the bean through JMS protocol -->
<bean id="sampleJMSService"
class="org.springframework.jms.remoting.JmsInvokerServiceExporter">
<property name="serviceInterface" value="...Echo" />
<property name="service">
<bean class="...EchoImpl" />
</property>
</bean>
<!--
creating the JMS listener container (elaborated in the JMS chapter)
-->
<bean class="orgjms.listener.SimpleMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queue" />
<property name="concurrentConsumers" value="3" />
<property name="messageListener" ref="sampleJMSService" />
</bean>
45
copyright 2009 Trainologic LTD
Spring Remoting
Client Side Configuration
45
<bean id=sampleJMSService"
class="orgjms.remoting.JmsInvokerProxyFactoryBean">
<property name="serviceInterface" value=Echo" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="queue" ref="queue" />
</bean>