<document>
<header>
  <product>resin</product>
  <title>Resin Remoting</title>
  <description>

<p>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
<a href="resin-ioc.xtp">Resin's IoC capabilities</a>,
including dependency injection, AOP interception, EJB transactions,
and event handling.</p>

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

  </description>
</header>

<body>

<localtoc/>

<s1 title="Example: Hello, World">

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

<ol>
<li>Creating the public API</li>
<li>Creating the Java implementation</li>
<li>Configuring the service in the resin-web.xml and choosing the protocol</li>
<li>Configuring and using the client</li>
</ol>

<s2 title="API - defining the protocol">

<p>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.</p>

<p>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.</p>

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

<example title="Example: Hello.java - API">
package qa;

public interface Hello {
  public String hello();
}
</example>

</s2>

<s2 title="Service - implementing the service">

<p>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.</p>

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

<example title="Example: MyService.java - Service">
package qa;

public class MyService implements Hello {
  public String hello()
  {
    return "hello, world";
  }
}
</example>

</s2>

<s2 title="Configuration - exporting the protocol">

<p>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.</p>

<p>Protocol drivers like Hessian or CXF create a class annotation
to expose the service.</p>

<p>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
&lt;servlet-mapping> definitions.</p>

<example title="Example: WEB-INF/resin-web.xml - Hessian Service">
&lt;web-app xmlns="http://caucho.com/ns/resin"
          xmlns:resin="urn:java:com.caucho.remote"
          xmlns:qa="urn:java:qa">

  &lt;qa:MyService>
    &lt;resin:HessianService urlPattern="/hello"/>
  &lt;/qa:MyService>

&lt;/web-app>
</example>

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

<example title="Example: WEB-INF/resin-web.xml - CXF Service">
&lt;web-app xmlns="http://caucho.com/ns/resin"
          xmlns:resin="urn:java:com.caucho.remote"
          xmlns:qa="urn:java:qa">

  &lt;qa:MyService>
    &lt;resin:CxfService urlPattern="/hello"/>
  &lt;/qa:MyService>

&lt;/web-app>
</example>

<example title="Example: WEB-INF/resin-web.xml - Hessian Client">
&lt;web-app xmlns="http://caucho.com/ns/resin"
         xmlns:resin="urn:java:com.caucho.resin"
         xmlns:qa="urn:java:qa">

  &lt;qa:Hello>
    &lt;resin:HessianClient url="http://localhost:8080/hello"/>
  &lt;/qa:Hello>

  &lt;servlet-mapping url-pattern="/demo"
                   servlet-class="qa.MyServlet"/>

&lt;/web-app>
</example>

<p>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:".</p>

<example title="Example: WEB-INF/resin-web.xml - CXF Client">
&lt;web-app xmlns="http://caucho.com/ns/resin"
         xmlns:resin="urn:java:com.caucho.resin"
         xmlns:qa="urn:java:qa">

  &lt;qa:Hello>
    &lt;resin:CxfClient url="http://localhost:8080/hello"/>
  &lt;/qa:Hello>

  &lt;servlet-mapping url-pattern="/demo"
                   servlet-class="qa.MyServlet"/>

&lt;/web-app>
</example>

</s2>

</s1>

<s1 title="Available Protocols">

<p>Resin 4.0.0 has the following protocol drivers available:</p>

<ul>
<li>HessianService: The <a href="http://hessian.caucho.com">Hessian</a>
protocol is a fast, compact binary protocol with implementations
available in a large number of languages including Flash, PHP
and C#.</li>
<li>BurlapService: The <a href="http://hessian.caucho.com">Burlap</a>
protocol is the XML-based cousin of Hessian.
</li>
<!--
<li>cxf: The <a href="http://wiki.caucho.com/CXF">CXF</a> driver
uses the Apache CXF project for SOAP client and server protocols.</li>
-->
</ul>

</s1>

<s1 title="Protocol Plugin Architecture">

<p>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.</p>

<s2 title="Server plugins">

<def title="com.caucho.remote.server.ProtocolServletFactory">
public interface ProtocolServletFactory {

  public Servlet createServlet(Class serviceClass, Object service)
    throws ServiceException;

}
</def>

<example title="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;
  }
}
</example>

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

<example title="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();
}
</example>

</s2>

<s2 title="Client plugins">

<def title="com.caucho.remote.client.ProtocolProxyFactory">
public interface ProtocolProxyFactory
{
  public Object createProxy(Class api);
}
</def>

<example title="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);
    }
  }
}
</example>

</s2>

</s1>

</body>
</document>
