Learn how to implement microservices using Thorntail in this guest post by Ram Kulkarni, a published author and an Eclipse expert.
Thorntail is the new name of the famous Wildfly Swarm (http://wildfly-swarm.io/). It allows you to assemble an application container for running microservices with just the specifications you need. It’s MicroProfile compatible, too
Creating a WildFly Swarm project
You can use WildFly Swarm Project Generator at http://wildfly-swarm.io/generator/ to select the specifications you’d want to include in your application and to create the starter project:
Enter Group ID and Artifact ID as shown in the previous screenshot. In the Dependencies textbox, start typing features such as JPA or JAX-RS and select them from the auto-suggested options. Make sure JPA EclipseLink , JAX-RS, and CDI are selected as dependencies. If you want to see all the available dependencies and select from them, click the View all available dependencies link.
Click the Generate Project button to create the project and download the ZIP file. This is a Maven project. Unzip the file in a folder and import the project as a Maven project in Eclipse. To do so, select the File | Import menu option and then select Existing Maven Projects in the Maven category.
Right-click on the Eclipse Project Explorer and select Run As|Maven Build. In the configuration window, type wildfly-swarm:run in the Goals field:
Click Run. Maven will download and install the dependencies and run the application (you will see a Wildfly Swarm is Ready message in the console when the application is ready). Open http://localhost:8080/hello to test the default endpoint created by the application generator. You should see the hello message.
If you look into the target folder of the project, you will see demo-swarm.jar and demo.war. When you execute the wildfly-swarm:run goal, Maven starts a JBoss container and deploys the WAR file. You can also run the microservice by executing demo-swarm.jar, the single JAR file. This JAR contains all the packages, including the application server, to run the microservice. Simply run this from the command line:
java –jar demo-swarm.jar
To change the name of the output file from demo to, say, coursemanagement, change the name in pom.xml in <filename> under the <build> tag.
Configuring JPA
Now, you need to add a dependency for MySQL in the project. Simply add the following dependency to pom.xml:
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.8-dmr</version> </dependency>
Convert the project to a JPA project so that we can use the JPA tooling provided by Eclipse. Right-click on the project in Project Explorer and select the Configure | Convert to JPA Project option. Make sure the following Project Facets are selected, along with the default facets:
- Dynamic Web Module
- JAX-RS (RESTful web services)
- JPA
Click the Next button:
Click Finish:
To configure the JDBC connection in persistence.xml, perform the following steps:
- Open persistence.xml in the editor.
- Click on the Connection tab and change Transaction type to Resource Local.
- Enter EclipseLink connection pool attributes as shown in the following screenshot and save the file:
Your persistence.xml should now have the following persistence unit:
<persistence-unit name="coursemanagement" transaction-type="RESOURCE_LOCAL"> <properties> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>packt.book.jeeeclipse.wildflyswarm.coursemanagement.rest.Course</class> <property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/course_management"/> <property name="javax.persistence.jdbc.user" value="<enter_your_user_name> "/> <property name="javax.persistence.jdbc.password" value="<enter_your_password> "/> </properties> </persistence-unit>
In the previous XML file, you specified the org.eclipse.persistence.jpa.PersistenceProvider class as the JPA provider and then set the properties for connecting to the MySQL database.
Next, create folders named resources/META-INF under src/main and copy persistence.xml into the src/main/resources folder. If Eclipse displays errors in JPA configuration, right-click on the project name in Project Explorer and select Maven | Update Project. The reason for doing this is that Maven expects files that you want to copy to the classes folder to be in the src/main/resources folder. You need to have META-INF/persistence.xml in the classes folder so that the JPA provider can load it.
Creating a course entity bean and a JPA factory
You’ll now create Course.java:
package packt.book.jeeeclipse.wildflyswarm.coursemanagement.rest; // skipping imports to save space @Entity @Table(name="\"Course\"") @NamedQuery(name="Course.findAll", query="SELECT c FROM Course c") public class Course implements Serializable { private static final long serialVersionUID = 2550281519279297343L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) @Column(name="id") private int id; @NotNull @Column(name="name") private String name; @Min(1) @Column(name="credits") private int credits; // skipping getter and setters to save space }
This is a simple JPA entity class with appropriate annotations. You need to tell JPA that this is a managed bean. To do this, open persistence.xml, and in the General tab of the editor, click the Add button in the Managed Classes section. Add the Course entity class to the list.
Create a JPA EntityManagerFactory class called CourseManagementJPAFactory:
package packt.book.jeeeclipse.wildflyswarm.coursemanagement.rest; // skipping imports to save space @ApplicationScoped public class CourseManagementJPAFactory { private EntityManager _entityManager; public EntityManager getEntityManager() { if (_entityManager != null) return _entityManager; EntityManagerFactory factory = Persistence.createEntityManagerFactory("coursemanagement"); _entityManager = factory.createEntityManager(); return _entityManager; } }
In this class, you created an instance of EntityManager from EntityManagerFactory. Note that name passed to the Persistence.createEntityManagerFactory method is the same as the name specified in persistence.xml.
Finally, you’ll need to create the main class, CourseManagementEndpoint, and the REST endpoint function to handle the/course_management/courses URL path:
package packt.book.jeeeclipse.wildflyswarm.coursemanagement.rest; // skipping imports to save space @ApplicationScoped @Path("/course_management") public class CourseManagementEndpoint { @Inject private CourseManagementJPAFactory jpaFactory; @GET @Path("/courses") @Produces(MediaType.APPLICATION_JSON) public List<Course> doGet() { EntityManager entityManager = jpaFactory.getEntityManager(); TypedQuery<Course> courseQuery = entityManager.createNamedQuery("Course.findAll", Course.class); List<Course> courses = courseQuery.getResultList(); return courses; } }
If the application is not already running, right-click on the project in Project Explorer and select Run As | Maven build. Open http://localhost:8080/course_managment/courses in the browser and you should see a JSON list of courses in the database.
To change the default server port from 8080 to any other port number, say 8000, set the swarm.http.port=8000 environment variable. You can set this in the run configuration for the project (select Run | Run Configurations from the main menu and look for the configuration for your project in the Maven Build section):
Click on the Environment tab and add the environment variable and its value.
You’ve now learnt how to implement microservices using Thorntail (WildFly Swarm). If you found this tutorial helpful and would like to learn more about Java EE 8 development with Eclipse, you can refer to the book, Java EE 8 Development with Eclipse – Third Edition by Ram Kulkarni. The book follows a step-by-step approach to developing, testing, debugging, and troubleshooting Java EE applications, complete with hands-on examples and tips.
Why do you need to run as a Maven build and wildfly:run where a Java micro-service should be run like a standalone Java app (at least it works with Spring Boot)
It’s just two different approaches with the same final results. 😉
Are you sure it is safe to reuse EntityManager like that ? Is it thread-safe ? I think it’s not.
You are right, this way it’s not thread-safe! Will work on fix the example… Thanks!