JBoss Modules Example – Modular Web Application
I’ve started with the following goal in mind – to create a web application using some service defined by my own JBoss module. The service prepared by me was pretty simple. I named it Echo Service:
package warlock.echo; public interface EchoService { String echo(String param); }
and placed into a separate jar file, named echo-api. Then I implemented this service:
package warlock.echo.impl; import warlock.echo.EchoService; public class DefaultEchoService implements EchoService { public String echo(String param) { return param; } }
and placed the implementation in a new jar file, named echo-module. Having in mind that my web application should have knowledge of the service API only, not the specific implementation, I decided to go with the way described in Creating Extensible Applications With the Java Platform – that choice required adding to echo-module jar special file under: META-INF/services/warlock.echo.EchoService, holding the “pointer” to the service implementation (fully qualified name of implementing class).
At this point, I retrieved and unpacked JBoss Application Server 7, stepped into the unpacked JBoss, and then into the modules directory. In this directory I’ve added the following structure:
Two jar files visible here are mentioned above, module.xml file is the definition of my JBoss Module – named ‘warlock.echo’, and has the following content:
<?xml version="1.0" encoding="UTF-8"?> <module xmlns="urn:jboss:module:1.0" name="warlock.echo"> <resources> <resource-root path="echo-module-1.0.0-SNAPSHOT.jar" /> <resource-root path="echo-api-1.0.0-SNAPSHOT.jar" /> </resources> </module>
After the completion of the JBoss Module definition, I’ve prepared a simple Spring Framework based application (which uses echo-api jar only during the compilation of project and doesn’t use the echo-module jar at all) with only one Controller:
package warlock; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import warlock.echo.EchoService; @Controller @RequestMapping("/echo.html") public class EchoController { @Autowired private EchoService service; @RequestMapping(method = RequestMethod.GET) @ResponseBody public String handleGet() { return service.echo("It workzzzzz!"); } }
As you can see, the Controller returns as response body the result of Echo Service call for some string. Now to the most important part – Echo Service definition in Web Application:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> ... <bean class="org.springframework.beans.factory.serviceloader.ServiceFactoryBean"> <property name="serviceType" value="warlock.echo.EchoService" /> </bean> ... </beans>
I know, one thing is bothering you :) – how the hell will Echo Service implementation be found if we don’t add either echo-api and echo-module jars to the Web Application?!
Well, this is the beauty itself ;) – We just need one more thing – WEB-INF/jboss-deployment-structure.xml file:
<jboss-deployment-structure> <deployment> <dependencies> <module name="warlock.echo" services="export" /> </dependencies> </deployment> </jboss-deployment-structure>
This way we tell JBoss that this application depends on the ‘warlock.echo’ module and the services defined in this module. The rest is pure JBoss Module magic ;)
Lectures for the dessert:
Reference: Modular Web Application based on JBoss Modules from our JCG partner Warlock at the “Warlock’s Thoughts” blog.
Related Articles :
If I package the sample application in an ear file. The modules are not working. It is throwing ClassNotFound Exception. Any idea how to get modules working with ear?