One Jar To Rule Them All: Apache TomEE + Shrinkwrap == JavaEE Boot
WARNING: I am not an expert of Spring Boot. There are a lot of things that I find really interesting about it and of course that can really improve your day-to-day work. Moreover I don’t have anything against Spring Boot nor people who develop it or use it. But I think that community are overestimating/overvenerating this product.
A year ago I started to receive a lot links about blogposts, tweets, information about Spring Boot. From his website you can read:
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that can you can “just run”.
And it seems that this thing has just revolutionized the Java world.
For example a Spring MVC (RESTful as well) application in Spring Boot looks like:
@Controller @EnableAutoConfiguration public class SampleController { @RequestMapping("/") @ResponseBody String home() { return "Hello World!"; } public static void main(String[] args) throws Exception { SpringApplication.run(SampleController.class, args); } }
As you can see the magic happens inside SpringApplication class which starts an embedded Tomcat or Jetty and using Spring thing it registers this controller. Pretty impressive I know with a few lines you can have an endpoint ready to be used.
But I wonder to myself if it is possible to use the same approach in JavaEE world and with the same low-level and light requirements. And the answer is absolutely. I have just created a really small protoype/proof-of-concept to prove that it is possible.
Also please don’t misunderstand me, Spring boot offers a lot of more things apart from self-contained application like monitoring, actuators, or artifact dependency resolution. But these things are only integration with other technologies, my example has been developed from zero in 1 hour and a half so don’t expect to have a Spring boot ready to be used.
The first thing to choose is the application server to be used, and in this case there is no doubt that the best one for this task is Apache TomEE. It is a certified web profile Java EE server which takes 1 second to start up and works with default Java memory parameters.
So I added tomee dependencies in my pom.xml file.
<dependencies> <dependency> <groupId>org.apache.openejb</groupId> <artifactId>tomee-embedded</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>org.apache.openejb</groupId> <artifactId>openejb-cxf-rs</artifactId> <version>4.7.1</version> </dependency> <dependency> <groupId>org.apache.openejb</groupId> <artifactId>tomee-jaxrs</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>org.jboss.shrinkwrap</groupId> <artifactId>shrinkwrap-depchain</artifactId> <version>1.2.2</version> <type>pom</type> </dependency> </dependencies>
In used tomee embedded version (1.7.1) you can only deploy applications contained inside a file, you cannot add for example a Servlet programmatically like it is done in Tomcat. This may change in near future of embedded tomee API, but for now we are going to use ShrinkWrap to create these deployment files in a programmatic way.
This is what we want to do:
import javax.ejb.Stateless; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; @Stateless @Path("/sample") public class SampleController { @GET @Produces("text/plain") public String sample() { return "Hello World"; } public static void main(String args[]) { TomEEApplication.run(HelloWorldServlet.class, SampleController.class); } }
Notice that we are only importing JavaEE classes and it is as reduced as Spring Boot one. In only 2 seconds the application is ready to be used. Keep in mind that you can use any feature provided by web profile spec as well as JAX-RS or JMS. So for example you can use JPA, Bean Validation, EJBs, CDI, …
And what’s inside TomEEApplication? You will be surprised a class with only 70 lines:
public class TomEEApplication { private static void startAndDeploy(Archive> archive) { Container container; try { Configuration configuration = new Configuration(); String tomeeDir = Files.createTempDirectory("apache-tomee").toFile().getAbsolutePath(); configuration.setDir(tomeeDir); configuration.setHttpPort(8080); container = new Container(); container.setup(configuration); final File app = new File(Files.createTempDirectory("app").toFile().getAbsolutePath()); app.deleteOnExit(); File target = new File(app, "app.war"); archive.as(ZipExporter.class).exportTo(target, true); container.start(); container.deploy("app", target); container.await(); } catch (Exception e) { throw new IllegalArgumentException(e); } registerShutdownHook(container); } private static void registerShutdownHook(final Container container) { Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { try { if(container != null) { container.stop(); } } catch (final Exception e) { throw new IllegalArgumentException(e); } } }); } public static void run(Class> ... clazzes) { run(ShrinkWrap.create(WebArchive.class).addClasses(clazzes)); } public static void run(WebArchive archive) { startAndDeploy(archive); } }
As you may see it is really simple piece of code and for example configuration or name of the application is hardcoded, but see that with several small easy changes you may start configuring server, application and so on.
In summary, of course Spring Boot is cool, but with really simple steps you can start having the same in JavaEE world. We (Apache TomEE contributors) are going to start to work on this and expand this idea.
So don’t underestimate Java EE because of Spring Boot.
Reference: | One Jar To Rule Them All: Apache TomEE + Shrinkwrap == JavaEE Boot from our JCG partner Alex Soto at the One Jar To Rule Them All blog. |
Spring Boot is not limited to the startup of a servlet container and the auto-configuration of Spring MVC, which is indeed the best simple use case to demonstrate its capabilities. It’s nice to see that Tomcat continues to offer the ability to programmatically start an instance, this is clearly something interesting when working with JavaEE specs, for instance to create a faster way for developers to test the changes made to the application. For areas where Spring and JavaEE “compete”, I guess there will be little difference in the resulting ‘business code’, like you are demonstrating, but for other use… Read more »