Zero to RMI with Groovy and Spring
In a recent post, I leveraged Spring to write a simple client-server app using 50 lines of Java.
I've moved it to Groovy. I've included the code below, but here are some fast facts:
- I used
groovycto compile the Groovy toclassfiles, then used thejavacommand. - I could only reduce the code by an
importor two. However, I did save 220+ characters (notice how clean the Groovy is). Groovy gurus might be able to improve on this. - Note that the Spring config files have more namespaces for Groovy support. Discovering this was the hardest part of the exercise.
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
class Message implements Serializable {
private final String message
Message(String message) { this.message = message }
String getMessage() { return message }
}
So far, so good. Now the server implementation:
import org.springframework.context.support.ClassPathXmlApplicationContext
class EasyServerImpl implements EasyServer {
Message exchangeMessage(String user) {
return new Message(user + ", Spring with Groovy rocks!")
}
static void main(String[] args) {
def context =
new ClassPathXmlApplicationContext("server_config.xml")
context.getBean("easyServer")
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"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
<lang:groovy id="easyServer" script-source="classpath:EasyServerImpl.groovy"/>
<bean class="org.springframework.remoting.rmi.RmiServiceExporter">
<!-- does not necessarily have to be the same name as the bean to be exported -->
<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.jarSPRING_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.support.ClassPathXmlApplicationContext
class EasyClient {
private EasyServer easyServer
void setEasyServer(EasyServer easyServer) { this.easyServer = easyServer }
Message exchangeMessage(String user) {
return easyServer.exchangeMessage(user)
}
static void main(String[] args) {
def context =
new ClassPathXmlApplicationContext("client_config.xml")
def easyClient = context.getBean("easyClient")
String output =
easyClient.exchangeMessage("CtJ Reader").getMessage()
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"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">
<lang:groovy id="easyClient" script-source="classpath:EasyClient.groovy">
<lang:property name="easyServer" ref="easyServer"/>
</lang:groovy>
<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 with Groovy rocks!
Cool stuff...