(Admittedly, we had experience with Spring IOC: this is not a tutorial.)
We were fully experimenting with the sandbox in 75 minutes. This may not seem fast but it was astonishing: some days, it seems I can't empty my Recycle Bin in 75 minutes.
Partly for my own reference, but also for CtJ readers, here is a recap of the RMI portion. No Hibernate here. And an extremely "toy" project structure (e.g. no Ant, no packages). But the key idea is there, and it will showcase the power of Spring.
We used Spring 2.5. To be honest, I don't know if this is in Version 1.x. It may well be.
Here is the contract between the client and server. This would be in a
common
package:
interface EasyServer {
Message exchangeMessage(String user);
}
Here is a simple
Message
class. Of course, for RMI, being Serializable
is vital:
import java.io.Serializable;
public class Message implements Serializable {
private final String message;
public Message(String message) { this.message = message; }
public String getMessage() { return message; }
}
So far, so good. Now the server implementation:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EasyServerImpl implements EasyServer {
public Message exchangeMessage(String user) {
return new Message(user + ", Spring rocks!");
}
public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("server_config.xml");
context.getBean("easyServer");
System.out.println("server ready");
}
}
It defines an easy
exchangeMessage
method and a starting main method. Spring takes care of the rest, as shown in the server_config.xml
file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!-- EasyServerImpl is the implementation -->
<bean id="easyServer" class="EasyServerImpl">
</bean>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- register the impl as the 'easyServerService' -->
<property name="serviceName" value="easyServerService"/>
<property name="service" ref="easyServer"/>
<property name="serviceInterface" value="EasyServer"/>
<!-- defaults to 1099 -->
<property name="registryPort" value="1199"/>
</bean>
</beans>
For running and compiling the server, simply ensure that these are in the CLASSPATH:
SPRING_HOME/dist/spring.jar
SPRING_HOME/lib/jakarta-commons/commons-logging.jar
Then it is up and away:
$ java EasyServerImpl
[ Spring magic dust snipped ]
server ready
The client is even simpler:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class EasyClient {
private EasyServer easyServer;
public void setEasyServer(EasyServer easyServer) {
this.easyServer = easyServer;
}
public Message exchangeMessage(String user) {
return easyServer.exchangeMessage(user);
}
public static void main(String[] args) {
ApplicationContext context = new
ClassPathXmlApplicationContext("client_config.xml");
EasyClient easyClient =
(EasyClient) context.getBean("easyClient");
String output =
easyClient.exchangeMessage("CtJ Reader").getMessage();
System.out.println( output );
}
}
The client-side configuration XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="easyClient" class="EasyClient">
<property name="easyServer" ref="easyServer"/>
</bean>
<bean id="easyServer"
class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="serviceUrl"
value="rmi://localhost:1199/easyServerService"/>
<property name="serviceInterface" value="EasyServer"/>
</bean>
</beans>
Using the same
CLASSPATH
, but with a separate window, we establish contact like so:
$ java EasyClient
[ Spring noise snipped ]
CtJ Reader, Spring rocks!
This trivial example uses approximately 50 lines of Java, with no knowledge of RMI. Amazing. It an easy exercise for the reader to package it up into a more formal project, using Ant etc. It is more challenging to add Hibernate, but still tractable: the basic wiring for a client-server playground is right here.
I'm curious as to how many lines of code this would take in Groovy. I think 40 would be easy to attain.
That's cool. I *heart* Spring!
ps. I lifted "*heart*" from Eric.
Just a side-note: exception handling is extremely simple. If your interface throws SomeException, you don't need to think about wrapping exceptions via java.rmi.RemoteException. Instead, you simply define and throw your exceptions, as with the rest of your classes, Spring simply gets your throwable across.
ReplyDeleteGreat point, Jay... thanks for the note
ReplyDeleteNice and easy tutorial :)
ReplyDeleteI googled a lot but failed to find a good tutorial or Spring-RMI on Eclipse IDE.
I am trying to implement your tutorial in eclipse, I am able to run the server side code, but client side code is not able to get the proxy.
Can you please help? Both client and server are in different projects but in same workspace.