Caucho Technology
  • resin 4.0
  • resin remoting


    Resin's remoting lets applications write services as plain Java objects and export them with a choice of protocols, including Hessian, Burlap, CXF (SOAP), XFire. Because Resin activates the service as an IoC singleton, the service can use any of Resin's IoC capabilities, including dependency injection, AOP interception, EJB transactions, and event handling.

    For applications which need to use a custom protocol, making a new driver for a protocol is also straightforward.

    Example: Hello, World

    The Hello, World example shows the primary steps involved in creating a Resin remoting service:

    1. Creating the public API
    2. Creating the Java implementation
    3. Configuring the service in the resin-web.xml and choosing the protocol
    4. Configuring and using the client

    API - defining the protocol

    Defining the protocol cleanly and clearly is the most critical aspect of designing a remote service. Because you will be sharing the protocol API among many other developers using different languages, it's critical to create a good design.

    The API classes are used for both the client and the server, ensuring compatibility. Even when the clients are expected to be written in a different language, e.g. Flash, C# or JavaScript, the API serves both as documentation and validation of the protocol. In the case of C#, the API can be translated automatically using reflection for strict compile-time validation.

    In this example, the API is easy. It's just a single method call hello returning a greeting string.

    Example: Hello.java - API
    package qa;
    
    public interface Hello {
      public String hello();
    }
    

    Service - implementing the service

    The service implementation is a plain Java object that can optionally use Resin-IoC capabilities for dependency injection. The service is multithreaded, so it's the service-developer's responsibility to handle any synchronization or transaction issues, just like writing a servlet.

    In this example, the implementation is trivial, just returning the "hello, world" string. More complicated services might delegate to Java Injection or EJB services.

    Example: MyService.java - Service
    package qa;
    
    public class MyService implements Hello {
      public String hello()
      {
        return "hello, world";
      }
    }
    

    Configuration - exporting the protocol

    Web-based remoting protocols are exported using the HTTP protocol with well-known URLs; they're essentially fancy servlets. Resin lets you configure your services just like a servlet. The only additional configuration necessary is choosing the protocol.

    Protocol drivers like Hessian or CXF create a class annotation to expose the service.

    In the example, we'll use Hessian, since it's a fast binary protocol with several language implementations. If you want to export multiple protocol bindings, you can just add new <servlet-mapping> definitions.

    Example: WEB-INF/resin-web.xml - Hessian Service
    <web-app xmlns="http://caucho.com/ns/resin"
              xmlns:resin="urn:java:com.caucho.remote"
              xmlns:qa="urn:java:qa">
    
      <qa:MyService>
        <resin:HessianService urlPattern="/hello"/>
      </qa:MyService>
    
    </web-app>
    

    We can easily change the protocol to use CXF instead of Hessian by changing the service from @HessianService to @CxfService.

    Example: WEB-INF/resin-web.xml - CXF Service
    <web-app xmlns="http://caucho.com/ns/resin"
              xmlns:resin="urn:java:com.caucho.remote"
              xmlns:qa="urn:java:qa">
    
      <qa:MyService>
        <resin:CxfService urlPattern="/hello"/>
      </qa:MyService>
    
    </web-app>
    
    Example: WEB-INF/resin-web.xml - Hessian Client
    <web-app xmlns="http://caucho.com/ns/resin"
             xmlns:resin="urn:java:com.caucho.resin"
             xmlns:qa="urn:java:qa">
    
      <qa:Hello>
        <resin:HessianClient url="http://localhost:8080/hello"/>
      </qa:Hello>
    
      <servlet-mapping url-pattern="/demo"
                       servlet-class="qa.MyServlet"/>
    
    </web-app>
    

    Since the client code only depends on the proxy API, changing to use CXF (SOAP) just requires changing the protocol scheme from "hessian:" to "cxf:".

    Example: WEB-INF/resin-web.xml - CXF Client
    <web-app xmlns="http://caucho.com/ns/resin"
             xmlns:resin="urn:java:com.caucho.resin"
             xmlns:qa="urn:java:qa">
    
      <qa:Hello>
        <resin:CxfClient url="http://localhost:8080/hello"/>
      </qa:Hello>
    
      <servlet-mapping url-pattern="/demo"
                       servlet-class="qa.MyServlet"/>
    
    </web-app>
    

    Available Protocols

    Resin 4.0.0 has the following protocol drivers available:

    • HessianService: The Hessian protocol is a fast, compact binary protocol with implementations available in a large number of languages including Flash, PHP and C#.
    • BurlapService: The Burlap protocol is the XML-based cousin of Hessian.

    Protocol Plugin Architecture

    You can extend Resin's remoting protocols by adding a plugin for either the server or client. In either case, the required API is deliberately kept simple.

    Server plugins

    com.caucho.remote.server.ProtocolServletFactory
    public interface ProtocolServletFactory {
    
      public Servlet createServlet(Class serviceClass, Object service)
        throws ServiceException;
    
    }
    
    Example: HessianProtocolServletFactory
    package com.caucho.remote.hessian;
    
    import com.caucho.hessian.server.*;
    import com.caucho.remote.*;
    import com.caucho.remote.server.*;
    
    import javax.servlet.*;
    
    public class HessianProtocolServletFactory
      extends AbstractProtocolServletFactory
    {
      public Servlet createServlet(Class serviceClass, Object service)
        throws ServiceException
      {
        HessianServlet servlet = new HessianServlet();
    
        servlet.setHome(service);
        servlet.setHomeAPI(getRemoteAPI(serviceClass));
        
        return servlet;
      }
    }
    

    Resin's URI aliases are configured by property files in WEB-INF/services/com.caucho.config.uri. Each interface has its property file specifying the implementation class for each URI scheme. In this case, the interface is com.caucho.remote.server.ProtocolServletFactory, so it the scheme mappings are added to a file with the same name:

    com.caucho.remote.HessianService
    
    package com.caucho.remote;
    
    import static java.lang.annotation.ElementType.*;
    import static java.lang.annotation.RetentionPolicy.RUNTIME;
    import java.lang.annotation.*;
    
    import com.caucho.remote.annotation.ServiceType;
    import com.caucho.remote.hessian.HessianProtocolServletFactory;
    
    @Documented
    @Target({TYPE})
    @Retention(RUNTIME)
    @ServiceType(defaultFactory=HessianProtocolServletFactory.class)
    public @interface HessianService {
      public String urlPattern();
    }
    

    Client plugins

    com.caucho.remote.client.ProtocolProxyFactory
    public interface ProtocolProxyFactory
    {
      public Object createProxy(Class api);
    }
    
    Example: HessianProtocolProxyFactory.java
    package com.caucho.remote.hessian;
    
    import com.caucho.hessian.client.*;
    import com.caucho.remote.*;
    import com.caucho.remote.client.*;
    
    public class HessianProtocolProxyFactory
      extends AbstractProtocolProxyFactory
    {
      private HessianProxyFactory _factory = new HessianProxyFactory();
    
      private String _url;
    
      public void setURL(String url)
      {
        _url = url;
      }
      
      public Object createProxy(Class api)
      {
        try {
          return _factory.create(api, _url);
        } catch (Exception e) {
          throw ServiceException(e);
        }
      }
    }
    

    Copyright © 1998-2009 Caucho Technology, Inc. All rights reserved.
    Resin ® is a registered trademark, and Quercustm, Ambertm, and Hessiantm are trademarks of Caucho Technology.