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