Micro Java EE application with Wildfly Swarm

Microservices are here already for a while. They came with cloud solutions, RESTful services, Backbone.js , AngularJS and other javascript frameworks, however only recently they got a new keyword - "microservices". And of course they will stay. Due to the nature of nowadays software architecture, cloud hosting and client rendering. I you want to be pragmatic and lean - you do not need microservices. If your software is complex, it needs easy support, fast deployment, easy clustering and serving for a single module (e.g. finance module within huge CRM) then you might thing about going into microservices. And here Wildfly Swarm comes in.

What is Wildfly Swarm?

You can think about Wildfly Swarm as a micro application server with features which are required for your applications only. And these features are embedded into one single jar together with your module. Yes, coupling with application server does not smell well, but useful in some cases. That's why I always say that you need to stick with your requirements and check if need such type of architecture.

Example

The easiest example to provide is REST + DB as a single microservice for a single module. You define data entities and expose them via REST endpoint. UI may be created as a separate microservice.

What you need?

Wildfly Swarm Alpha3-SNAPSHOT. Alpha1 did not support JPA and Alpha2 still has some issues which are already fixed in latest SNAPSHOT version. This means that you need to grab it from github and build yourself. Or wait for Alpha3 release.

Then you need some wildfly dependencies.

<dependency>
	<groupId>org.wildfly.swarm</groupId>
	<artifactId>wildfly-swarm-jpa</artifactId>
	<version>${wildfly-swarm.version}</version>
</dependency>
<dependency>
	<groupId>org.wildfly.swarm</groupId>
	<artifactId>wildfly-swarm-weld-jaxrs</artifactId>
	<version>${wildfly-swarm.version}</version>
</dependency>

And wildfly plugins...

<plugin>
	<groupId>org.wildfly.swarm</groupId>
	<artifactId>wildfly-swarm-plugin</artifactId>
	<version>${wildfly-swarm.version}</version>
	<configuration>
		<mainClass>org.aracrown.blog.s01e04.Main</mainClass>
	</configuration>
	<executions>
		<execution>
			<goals>
				<goal>package</goal>
			</goals>
		</execution>
	</executions>
</plugin>

And some code... Ok, source is in Git repository, I will not repeat myself here :)

And the main thing, which comes to Wildfly swarm - configuration! So far you need a Java class with main method in order to be able to start it as a regular jar archive. That's the place where nasty things happen :)

package org.aracrown.blog.s01e04;

import org.aracrown.blog.s01e04.dao.BlogEntryDao;
import org.aracrown.blog.s01e04.model.BlogEntry;
import org.aracrown.blog.s01e04.query.BlogEntryQueryImpl;
import org.aracrown.blog.s01e04.resources.BlogEntriesResource;
import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset;
import org.wildfly.swarm.container.Container;
import org.wildfly.swarm.datasources.Datasource;
import org.wildfly.swarm.datasources.DatasourceDeployment;
import org.wildfly.swarm.datasources.DriverDeployment;
import org.wildfly.swarm.jaxrs.JAXRSDeployment;

public class Main {
	public static void main(String[] args) throws Exception {
		Container container = new Container();
		container.start();

		DriverDeployment driverDeployment = new DriverDeployment(container, "com.h2database:h2", "h2");
		container.deploy(driverDeployment);

		// Create a DS deployment
		DatasourceDeployment dsDeployment = new DatasourceDeployment(container, new Datasource("ExampleDS")
				.connectionURL("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE").driver("h2").authentication("sa", "sa"));
		container.deploy(dsDeployment);

		JAXRSDeployment deployment = new JAXRSDeployment(container);
		deployment.getArchive().addClasses(BlogEntryDao.class, BlogEntryQueryImpl.class);
		deployment.getArchive().addPackage(BlogEntry.class.getPackage());
		deployment.getArchive().addPackage(BlogEntriesResource.class.getPackage());
		deployment.getArchive().addAsWebInfResource(new ClassLoaderAsset("META-INF/persistence.xml", Main.class.getClassLoader()),
				"classes/META-INF/persistence.xml");
		deployment.getArchive().addAsWebInfResource(new ClassLoaderAsset("META-INF/load.sql", Main.class.getClassLoader()),
				"classes/META-INF/load.sql");
		deployment.getArchive().addAsWebInfResource(new ClassLoaderAsset("META-INF/beans.xml", Main.class.getClassLoader()),
				"classes/META-INF/beans.xml");

		container.deploy(deployment);
	}
}

You tell the container to use JAX-RS and datasource modules only. You can expose your configuration properties to external properties file, but what you need is adding classes and resources into archive manually. Executing maven goal mvn package will create you a single jar containing all required dependencies with a suffix "-swarm".

And at the end you have a single jar file and you can distribute it onto as many servers as you need. and run with just a single line:

java -jar target/s01e04-1.0.0-SNAPSHOT-swarm.jar

REST resource call would look like

curl -v http://localhost:8080/blogs/

And result:

* Hostname was NOT found in DNS cache
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /blogs/ HTTP/1.1
> User-Agent: curl/7.37.1
> Host: localhost:8080
> Accept: */*
> 
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/json
< Content-Length: 755
< Date: Wed, 10 Jun 2015 18:37:26 GMT
< 
* Connection #0 to host localhost left intact
{"total":12,"count":10,"pageSize":10,"currentPage":0,"items":[{"id":1,"title":"Wildfly Swarm with JPA and REST1","author":"Penny"},{"id":2,"title":"Wildfly Swarm with JPA and REST2","author":"Penny"},{"id":3,"title":"Wildfly Swarm with JPA and REST3","author":"Penny"},{"id":4,"title":"Wildfly Swarm with JPA and REST4","author":"Penny"},{"id":5,"title":"Wildfly Swarm with JPA and REST5","author":"Penny"},{"id":6,"title":"Wildfly Swarm with JPA and REST6","author":"Penny"},{"id":7,"title":"Wildfly Swarm with JPA and REST7","author":"Penny"},{"id":8,"title":"Wildfly Swarm with JPA and REST8","author":"Penny"},{"id":9,"title":"Wildfly Swarm with JPA and REST9","author":"Penny"},{"id":10,"title":"Wildfly Swarm with JPA and REST10","author":"Penny"}]}

Resources

Talks and discussions

Happy designing and coding!

vytas

Senior software engineer, software architect for java enterprise based solutions