resin Hessian with Dependency Injection

Using Hessian with Dependency Injection pattern creates services which are simpler, protocol-independent and more easily tested. The Dependency Injection pattern (aka inversion of control) gives Resin the responsibility of configuring and assembling the service, protocol, and client.

tutorial client/greeting
Interface for the greeting service. The service implementation as a Java object Configures the environment Client Servlet
package example; public interface GreetingAPI { public String hello(); }

The Greeting implementation is a plain Java class that implements the MatchService API. Making the service a plain class offers a number of advantages:

  • Simplicity: It can concentrate on its business logic because it doesn't need to implement any protocol-dependent code.
  • Independence: It can be reused more easily because it isn't tied to a distributed framework (e.g. in contrast to EJB).
  • Testability: It is more easily tested since the test harness doesn't need to implement the protocol or its stubs. The harness can just test the service as a plain old Java object.
package example; public class GreetingImpl implements GreetingAPI { private String _greeting = "Hello, world"; public void setGreeting(String greeting) { _greeting = greeting; } public String greeting() { return _greeting; } }
<resource jndi-name="service/greeting" type="example.GreetingImpl"> <init> <greeting>Hello, web.xml</greeting> </init> </resource> <servlet url-pattern="/hessian/greeting" servlet-class="com.caucho.hessian.server.HessianServlet"> <init> <home>\${jndi("service/greeting")}</home> <home-api>example.GreetingAPI</home-api> </init> </servlet>

Configuring the client servlet with Dependency Injection allows for a simpler and more general client. The following client can use any proxy/stub which implements the GreetingAPI without change, for example:

  • Hessian proxy
  • Burlap proxy
  • EJB local object stub
  • JMX proxy
  • Java bean instance

Using the Dependency Injection patter, the servlet doesn't care how the proxy is implemented, or how the greeting service is discovered.

public class GreetingClientServlet extends GenericServlet { private String _name = "generic"; private GreetingAPI _greeting; public void setName(String name) { _name = name; } public void setGreeting(GreetingAPI greeting) { _greeting = greeting; } public void service(ServletRequest req, ServletResponse res) throws IOException, ServletException { PrintWriter out = res.getWriter(); out.println(_name + ": " + _greeting.greeting()); } }

The following example stores a <reference> to the Hessian proxy in JNDI for the service. The servlet configuration looks up the Hessian proxy in JNDI.

<reference jndi-name="client/greeting" factory="com.caucho.hessian.client.HessianProxyFactory"> <init-param url="\${app.getURL()}/hessian/greeting"/> <init-param type="example.GreetingAPI"/> </reference> <servlet-mapping url-pattern="/client/greeting" servlet-class="example.GreetingClientServlet"> <init> <name>Hessian Client</name> <greeting>\${jndi("client/greeting")}</greeting> </init> </servlet-mapping>

The following JMX configuration shows the flexibility of the Dependency Injection pattern. With no changes to either the Greeting service or its client, the Greeting service can change to a JMX bean used by and the client to use a JMX proxy.

<resource mbean-name="type=Greeting" mbean-interface="example.GreetingAPI" type="example.GreetingImpl"> <init> <greeting>Hello, web.xml</greeting> </init> </resource> <servlet-mapping url-pattern="/client/greeting" servlet-class="example.GreetingClientServlet"> <init> <name>JMX Client</name> <greeting>\${jndi("mbean:type=Greeting")}</greeting> </init> </servlet-mapping>