I remember when I first started using EJBs, there was a lot of talk about physical separation of the presentation and business tiers via remote interfaces and RMI. So, technically you could have your business logic sitting on a different server than you web application. It sounds great but I cannot remember actually doing that.
My web and business tiers have always been packaged into a single EAR and deployed as a one, monolithic application. When I moved away from EJBs and started using the Struts/Spring/Hibernate combination I didn’t give much thought about this until recently when on my latest project someone (thanks Shine) reminded me how you can achieve the same separation of tiers using Spring remoting. After all, this is still a great enterprise design pattern and I’m surprised I haven’t encountered it more often. Allow me to share it…
OK, to start with we need to break our application into three components: 1). the web app, 2). the back-end app, and 3). the common library that will define the interfaces that the web app can use to talk to the back-end and the DTOs that they will use to exchange data. This library will be listed as a dependency in each app.
This library defines the interfaces and classes that will be shared between the business and the web applications (but not the communication interfaces as Spring remoting will handle that for us). So for example:
I think both the
ServiceResultDto and the
IService definitions are self explanatory. Basically, we are
expecting our business tier to provide the implementation of the
IService interface, which, when invoked will return
an instance of the
ServiceResultDto class containing results data. At this stage we are not interested in how this
service will be exposed to a remote web application. We will leave that to the business app and Spring.
Business (back-end) Application
Funny enough the actual implementation of the
IService interface is not important. What is important is how we wire
it together with Spring remoting so that it is accessible from the Web application (which, remember is deployed on a separate
application server, potentially on a different machine).
Here is a simple implementation of this service interface. Note the
@Service annotation which tells Spring that
this class is our service.
Since our business tier needs to run independently of the front-end web application, let’s make the back-end a web app in its own right as well. To do this, it needs to be packaged as a WAR file and have a web.xml configuration. Here is a web.xml extract that contains the DispatcherServlet definition that will do the work of dispatching incoming requests to our service instance.
Pay attention to the servlet name as it is important. Spring framework will look for the application context configuration file whose name starts with the servlet name and appended with “-context.xml” (we’ll define this configuration file next).
The following is a complete definition of the services-context.xml Spring application context configuartion file.
<context:component-scan> tells Spring to find bean definitions by scanning the source code, loading the
@Service annotated classes into its application context.
/service bean definition, is the one that exposes our service to the outside world using Spring Remoting,
HttpInvokerServiceExporter class. In essence it wraps the real service implementation within
this bean exposing it using its interface.
Package (as a WAR file) and deploy the back-end application to your favourite application server (I normally just use Tomcat) and it is ready for use by the front-end web application.
Do whatever you normally do to create your web application (with Spring support of course). The key is it should be no different to any other web application that you’ve developed in the past, with one small difference.
At some point you will want to access the remote service that we’ve defined and deployed in the previous step. Assuming that you’ve imported the common library JAR file, you will need to define the following application context (either in a separate file or within an existing configuration file if you are using Spring for other purposes).
We are using the Spring Remoting API, specifically, the
HttpInvokerProxyFactoryBean class to help us interface with
a remote service. The serviceUrl attribute defines the remote service location to which the invoker will forward HTTP requests
and whose responses will be marshalled into the appropriate Java objects (in our case
When Spring creates the above bean it will use the serviceInterface value to ensure that the created instance implements the IService inteface. This means that when it is injected into your web action classes, the fact that the calls are made to a remote service is completely abstracted. Remoting is handled for you so you are left with worrying about implementing your business logic. Nice.
I doubt that I’m telling you anything that new. This technology has existed for a while now but perhaps, just like me, you haven’t properly thought about using it for separating the web and business tiers. I think this is a great way of implementing a reusable back-end subsystem and I ’m sure I’ll find lots of uses for it in the future.