<document>
<localtoc/>

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

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.

package qa; public interface Hello { public String hello(); }

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 WebBeans or EJB services.

package qa; public class MyService implements Hello { public String hello() { return "hello, world"; } }

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

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.

<web-app xmlns="http://caucho.com/ns/resin"> <servlet-mapping url-pattern="/hello" servlet-class="qa.MyService"> <protocol uri="hessian:"/> </servlet-mapping> </web-app>

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

<web-app xmlns="http://caucho.com/ns/resin"> <servlet-mapping url-pattern="/hello" servlet-class="qa.MyService"> <protocol uri="cxf:"/> </servlet-mapping> </web-app>

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.

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.

The `@javax.webbeans.In` annotation asks Resin to lookup the `qa.Hello` 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.

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()); } }

Although most clients will just have a single `Hello` proxy and can use the `@In` tag, more complicated applications can use the `@Named` tag or even custom `@BindingTag` annotations to select the right proxy. The Resin IoC documentation has more details.

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

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

<web-app xmlns="http://caucho.com/ns/resin"> <remote-client class="qa.Hello" uri="hessian:url=http://localhost:8080/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:".

<web-app xmlns="http://caucho.com/ns/resin"> <remote-client class="qa.Hello" uri="cxf:url=http://localhost:8080/hello"/> <servlet-mapping url-pattern="/demo" servlet-class="qa.MyServlet"/> </web-app>

Resin 3.1.5 has the following protocol drivers available:

- hessian: The Hessian protocol is a fast, compact binary protocol with implementations available in a large number of languages including Flash, PHP and C#.
- burlap: The Burlap protocol is the XML-based cousin of Hessian.
- cxf: The CXF driver uses the Apache CXF project for SOAP client and server protocols.

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.

public interface ProtocolServletFactory { public Servlet createServlet(Class serviceClass, Object service) throws ServiceException; } 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:

burlap=com.caucho.remote.burlap.BurlapProtocolServletFactory hessian=com.caucho.remote.hessian.HessianProtocolServletFactory public interface ProtocolProxyFactory { public Object createProxy(Class api); } 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); } } }
</document>