Create WildFly Swarm applications from existing war files
Have you heard about WildFly Swarm?
It's a new sidecar project to WildFly which helps you create self-contained Java microservices based upon the normal WildFly application-server.
Sounds interesting?
We had different use-cases for such a product. Our VisionX creates war files and desktop applications. It would be nice to have a microservice option. Our idea was to create a WildFly Swarm application based on our pre-created war files. Could be useful.
We made some experience with bundeling an embedded Tomcat with our applications because we use this variant for our desktop applications to add browser based help systems. We thought that a replacement of embedded Tomcat could reduce complexity...
The documentation was simple and maven based. The info:
We do aim to add support for other build-systems in the near future.
was nice but the relevant information wasn't available for ANT. We found some gradle tasks, but nothing for ANT - because ANT isn't supported.
What's the problem with maven? We don't like downloading the Internet for simple dependency management. This happened during our first tests with WildFly Swarm. Before we built our first "fat" jar, the "whole JBoss repository" was downloaded.
Test: Phase 1
We tried to follow the documentation and started with a new Maven "war" project. Our application was a simple JVx application with vaadin UI. The application code:
@Widgetset(value = "com.sibvisions.rad.ui.vaadin.ext.ui.Widgetset")
@Configuration({@Parameter(name = "main", value = "com.sibvisions.demos.swarm.EmbeddedApplication$MyApplication")})
@SuppressWarnings("serial")
public class EmbeddedApplication extends VaadinUI
{
@WebServlet(value = {"/minimal/*", "/VAADIN/*"}, asyncSupported = true)
@VaadinServletConfiguration(productionMode = false, ui = EmbeddedApplication.class)
public static class Servlet extends VaadinServlet
{
} // Servlet
public static class MyApplication extends Application
{
public MyApplication(UILauncher pLauncher)
{
super(pLauncher);
setName("Simple application");
setLayout(new UIBorderLayout());
UILabel lblHello = new UILabel("Hello JVx' vaadinUI");
lblHello.setFont(UIFont.getDefaultFont().deriveFont(UIFont.BOLD, 16));
lblHello.setHorizontalAlignment(IAlignmentConstants.ALIGN_CENTER);
//example CSS without custom css file
((VaadinLabel)lblHello.getUIResource()).getCssExtension().addAttribute("margin-top", "100px");
add(lblHello, UIBorderLayout.CENTER);
}
}
}
We found an intro from vaadin about their tests with WildFly Swarm. The last link contains redirects to a github project with many examples and a ready-to-use maven configuration.
But, we had bad luck because no example was working with our setup. The build wasn't a problem, but we got some Exceptions at runtime. We tried to find documentation in the Internet, but we didn't find a solution because the project is in Alpha status and documentation is not yet ready... So we tried to build WildFly Swarm on our own to be able to add debug messages.
After a long maven fight (once again) everything was working. We had some problems with JDK 8 and Eclipse Kepler because Kepler didn't support JDK8 without a Patch and bundled maven was too old. Latest maven didn't work with Eclipse but 3.2.1 was working...
WildFly Swarm test artifacts didn't work without problems and we had to fix some autoboxing errors (because of our custom compiler settings). Horrible but we won the fight!
The problem with our "fat" jar was that two dependencies were missing or weren't resolved correctly. After we manually set two more dependencies:
<groupId>org.jboss.msc</groupId>
<artifactId>jboss-msc</artifactId>
<version>1.2.6.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.sql</groupId>
<artifactId>jboss-javax-sql-api_7.0_spec</artifactId>
<version>1.1.0.Final</version>
</dependency>
our "fat" jar was working without problems.
BUT... the jar had about 100 MB! Our war file had about 40MB. The overhead was about 60MB - WTF?
Our applications with embedded Tomcat had an overhead of 4MB.
The problem was/is that all maven dependencies were added to the war and the jar file. It was handled by the swarm-plugin and the issue #107 explains the problem.
After one day! we had a working Hello world example as Maven project. Sure, we built our own WildFly Swarm version too.
Test: Phase 2
The Maven project was working and maven built a war for our sources and bundled all dependencies for us, but what about existing war files? Our initial plan was the creation of WildFly Swarm applications for existing war files. This wasn't possible without hacking because it wasn't implemented... for us.
I told you that we built our own WildFly Swarm version and also the swarm-plugin. The plugin had a PackageMojo class. This mojo had enough documentation (= source code) for us, to create a simple test case for our use-case.
The test class is about 100 LoC with minimal logic but it's tricky. The relevant calls:
for (File jar : findMinimalDependencies())
{
//read groupid, artifactid, version from jar
tool.dependency("compile", sGroupId, sArtifactId, sVersion, "jar", null, jar);
}
tool.artifactResolvingHelper(new Resolver(tool));
tool.projectArtifact("com.sibvisions.demos", "swarm", "0.2-SNAPSHOT", "war", war);
tool.build("swarm-0.2-SNAPSHOT", target);
The Resolver was a simply code copy of BuildTool findArtifact method:
{
private BuildTool tool;
public Resolver(BuildTool pTool)
{
tool = pTool;
}
@Override
public ArtifactSpec resolve(ArtifactSpec pSpec) throws Exception
{
for (ArtifactSpec each : tool.dependencies())
{
if (each.file == null) {
continue;
}
if (pSpec.artifactId != null && !pSpec.artifactId.equals(each.artifactId)) {
continue;
}
if (pSpec.version != null && !pSpec.version.equals(each.version)) {
continue;
}
if (pSpec.packaging != null && !pSpec.packaging.equals(each.packaging)) {
continue;
}
if (pSpec.classifier != null && !pSpec.classifier.equals(each.classifier)) {
continue;
}
return each;
}
return null;
}
}
(Sure, not the best solution - but it was good enough for our tests)
With our test class, it was possible to create a WildFly Swarm application for an existing war file, without problems and without maven. And the best: The "fat" jar file had about 83MB and the original war file was about 60MB. The overhead was 23MB, but awesome for a basic WildFly installation.
The example project of Phase 1 is available on github.
Conclusion
WildFly Swarm is a nice product but it's not ready-to-use. If you have time to play around with it, just do it because it creates a back to the roots feeling - back to hacking. The "fat" jars are a nice idea, but microservice is just a buzzword.
WildFly is not comparable to embedded Tomcat, but if you need a simple application server for your servlets, an embedded Tomcat or Jetty are good enough. We won't replace our embedded Tomcat with WildFly Swarm because we misunderstood the concept and both products are for different use-cases.... but a new export Option for VisionX should be possible!