Using Hessian to Remotely Call Services through HTTP

Hessian offers a binary HTTP-based remoting protocol. It is developed by Caucho, and you can find more information about Hessian itself at https://www.caucho.com/.

Hessian

Hessian communicates through HTTP and does so by using a custom servlet. By using Spring’s DispatcherServlet principles (see mvc-servlet), we can wire up such a servlet to expose your services. First, we have to create a new servlet in our application, as shown in the following excerpt from web.xml:

<servlet>
	<servlet-name>remoting</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>remoting</servlet-name>
	<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>

If you are familiar with Spring’s DispatcherServlet principles, you probably know that now you have to create a Spring container configuration resource named remoting-servlet.xml (after the name of your servlet) in the WEB-INF directory. The application context is used in the next section.

Alternatively, consider the use of Spring’s simpler HttpRequestHandlerServlet. Doing so lets you embed the remote exporter definitions in your root application context (by default, in WEB-INF/applicationContext.xml), with individual servlet definitions pointing to specific exporter beans. In this case, each servlet name needs to match the bean name of its target exporter.

Exposing Your Beans by Using HessianServiceExporter

In the newly created application context called remoting-servlet.xml, we create a HessianServiceExporter to export our services, as the following example shows:

<bean id="accountService" class="example.AccountServiceImpl">
	<!-- any additional properties, maybe a DAO? -->
</bean>

<bean name="/AccountService" class="org.springframework.remoting.caucho.HessianServiceExporter">
	<property name="service" ref="accountService"/>
	<property name="serviceInterface" value="example.AccountService"/>
</bean>

Now we are ready to link in the service at the client. No explicit handler mapping is specified (to map request URLs onto services), so we use BeanNameUrlHandlerMapping used. Hence, the service is exported at the URL indicated through its bean name within the containing DispatcherServlet instance’s mapping (as defined earlier): https://HOST:8080/remoting/AccountService.

Alternatively, you can create a HessianServiceExporter in your root application context (for example, in WEB-INF/applicationContext.xml), as the following example shows:

<bean name="accountExporter" class="org.springframework.remoting.caucho.HessianServiceExporter">
	<property name="service" ref="accountService"/>
	<property name="serviceInterface" value="example.AccountService"/>
</bean>

In the latter case, you should define a corresponding servlet for this exporter in web.xml, with the same end result: The exporter gets mapped to the request path at /remoting/AccountService. Note that the servlet name needs to match the bean name of the target exporter. The following example shows how to do so:

<servlet>
	<servlet-name>accountExporter</servlet-name>
	<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>accountExporter</servlet-name>
	<url-pattern>/remoting/AccountService</url-pattern>
</servlet-mapping>

Linking in the Service on the Client

By using the HessianProxyFactoryBean, we can link in the service at the client. The same principles apply as with the RMI example. We create a separate bean factory or application context and mention the following beans where the SimpleObject is by using the AccountService to manage accounts, as the following example shows:

<bean class="example.SimpleObject">
	<property name="accountService" ref="accountService"/>
</bean>

<bean id="accountService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
	<property name="serviceUrl" value="https://remotehost:8080/remoting/AccountService"/>
	<property name="serviceInterface" value="example.AccountService"/>
</bean>

Applying HTTP Basic Authentication to a Service Exposed through Hessian

One of the advantages of Hessian is that we can easily apply HTTP basic authentication, because both protocols are HTTP-based. Your normal HTTP server security mechanism can be applied through using the web.xml security features, for example. Usually, you need not use per-user security credentials here. Rather, you can use shared credentials that you define at the HessianProxyFactoryBean level (similar to a JDBC DataSource), as the following example shows:

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
	<property name="interceptors" ref="authorizationInterceptor"/>
</bean>

<bean id="authorizationInterceptor"
		class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor">
	<property name="authorizedRoles" value="administrator,operator"/>
</bean>

In the preceding example, we explicitly mention the BeanNameUrlHandlerMapping and set an interceptor, to let only administrators and operators call the beans mentioned in this application context.

The preceding example does not show a flexible kind of security infrastructure. For more options as far as security is concerned, have a look at the Spring Security project at https://projects.spring.io/spring-security/.