<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 WebBeans 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 register the
protocol implementation with a URI scheme
like "hessian:" or "cxf:".  Your service configuration will
just select the appropriate protocol in a &lt;protocol>
configuration tag.</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">

  &lt;servlet-mapping url-pattern="/hello" servlet-class="qa.MyService">
    &lt;protocol uri="hessian:"/>
  &lt;/servlet-mapping>

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

<p>We can easily change the protocol to use CXF instead of
Hessian by changing the scheme from "hessian:" to "cxf:".</p>

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

  &lt;servlet-mapping url-pattern="/hello" servlet-class="qa.MyService">
    &lt;protocol uri="cxf:"/>
  &lt;/servlet-mapping>

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

</s2>

<s2 title="Client servlet - using the protocol">

<p>On the client side, the application needs a proxy to
invoke the server methods.  Since the protocols themselves are
generic, the client will work with any server even if written
in a different language like C#, as long as the protocol is
compatible.</p>

<p>The client uses Resin's dependency injection to get a client proxy
for the protocol.  By using dependency injection, the client code
remains independent of the protocol choice or any protocol-setup
housekeeping.  The only dependency is on the client API itself.
Because the client uses the type-safe API, the Java compiler
validates the protocol, making compatibility as certain as
possible.</p>

<p>The <code>@javax.webbeans.In</code> annotation asks Resin to
lookup the <code>qa.Hello</code> client stub that's been configured
and gives it to the servlet.  Since the client stub is thread-safe
it can be safely used in the servlet code.</p>

<example title="Example: qa/MyServlet.java - Servlet Client">
package qa;

import java.io.*;
import javax.servlet.*;
import javax.webbeans.*;

public class MyServlet extends GenericServlet {
  @In private Hello _hello;

  public void service(ServletRequest request,
                      ServletResponse response)
    throws IOException
  {
    out.println("hello: " + _hello.hello());
  }
}
</example>

<p>Although most clients will just have a single <code>Hello</code>
proxy and can use the <code>@In</code> tag, more complicated
applications can use the <code>@Named</code> tag or even custom
<code>@BindingTag</code> annotations to select the right proxy.
The <a href="resin-ioc.xtp">Resin IoC</a> documentation has more
details.</p>

</s2>

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

<p>To configure the client, you need to specify the protocol
type, the URL, and the API class in a
<code>&lt;remote-client></code> tag in the resin-web.xml.
Since the client code uses injection to get the proxy, we can switch
protocols if necessary.</p>

<p>The example uses Hessian, so the <code>uri</code> attribute
uses a "hessian:" scheme with Hessian's <code>url</code>
parameter.  The API class is <code>qa.Hello</code>.</p>

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

  &lt;remote-client class="qa.Hello"
                 uri="hessian:url=http://localhost:8080/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">

  &lt;remote-client class="qa.Hello"
                 uri="cxf:url=http://localhost:8080/hello"/>

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

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

</s2>

</s1>

<s1 title="Available Protocols">

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

<ul>
<li>hessian: 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>burlap: 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.server.ProtocolServletFactory">
burlap=com.caucho.remote.burlap.BurlapProtocolServletFactory
hessian=com.caucho.remote.hessian.HessianProtocolServletFactory
</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>
