Develop Java EE applications on WildFly

In this tutorial we will learn how to develop a basic Java EE 8 application on WildFly which uses Maven to compile and deploy your project.
The prerequisites to run this tutorial are:

  • JDK 1.8 or higher
  • Maven
  • WildFly Application Server

The technology we are going to use in this basic demo are:

  • JSF: for the front-end layer
  • CDI: as glue between the front-end layer and the database
  • JPA: to manage CRUD operation on a Database

We will use JBoss Developer Studio to code our application, but you can use any environment which is able to manage Maven Projects.
So, from the File Menu create a New Maven Project and, as archetype choose any web application archetype, like the following one:

develop java ee applications wildfly

Next enter the project GroupId, ArtifactId and Package:

develop java ee applications wildfly

We will start from the front-end which consists only of an index.xhtml page where you can add a new “SimpleProperty” object, display the existing ones, and delete them.

<h:body>
	<h2>Example Java EE 8 Application</h2>
	<h:form id="jsfexample">
		<h:panelGrid columns="2" styleClass="default">

			<h:outputText value="Enter key:" />
			<h:inputText value="#{property.key}" />

			<h:outputText value="Enter value:" />
			<h:inputText value="#{property.value}" />

			<h:commandButton actionListener="#{manager.save}"
				styleClass="buttons" value="Save key/value" />

			<h:messages />


		</h:panelGrid>


		<h:dataTable value="#{propertyList}" var="item" styleClass="table"
			headerClass="table-header" rowClasses="table-odd-row,table-even-row">
			<h:column>
				<f:facet name="header">Key</f:facet>
				<h:outputText value="#{item.key}" />
			</h:column>
			<h:column>
				<f:facet name="header">Value</f:facet>
				<h:outputText value="#{item.value}" />
			</h:column>
			<h:column>
				<f:facet name="header">Delete</f:facet>
				<h:commandButton actionListener="#{manager.clear(item)}"
					styleClass="buttons" value="Delete" />
			</h:column>

		</h:dataTable>
	</h:form>
</h:body>
</html>

As you can see, basically this Web page is split into two parts:
1) The top section contains a form where you can insert a Key/Value for the SimpleProperty Object
2) The bottom section contains a dataTable JSF Object where the list of SimpleProperty are displayed. You can as well Delete them by clicking on the Delete button

The Controller for this application is the “manager” Bean which reflects in the following CDI Bean:

package com.mastertheboss.bean;


import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.enterprise.inject.Produces;
 
import javax.inject.Inject;
import javax.inject.Named;

 
import com.mastertheboss.ejb.ServiceBean;
import com.mastertheboss.model.SimpleProperty;
import com.mastertheboss.producer.Producer;

@Model
public class Manager {
  
	@Inject
	ServiceBean ejb;
	
	@Produces
	@Named
	SimpleProperty property;
	
	@Inject
	Producer producer;
	
	@PostConstruct
	public void initNewProperty() {
		property = new SimpleProperty();
	}
	 
	public void save() {
		ejb.put(property);
		initNewProperty();
	}

	public void clear(SimpleProperty property) {
		ejb.delete(property);
		 
	}
 
}

As you can see, this Bean is defined as @Model, which is simply a stereotype for @RequestScoped and @Named. The Bean uses an EJB, ServiceBean, to handle the transactional operation (save and delete of Objects).

Here is the definition of the ServiceBean class:

package com.mastertheboss.ejb;

import javax.ejb.Stateless;
import javax.enterprise.event.Event;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import com.mastertheboss.model.SimpleProperty;

@Stateless
public class  ServiceBean   {

	@Inject
	private Event<SimpleProperty> propEventSrc;
	
	@Inject
	private EntityManager em;

	
	public void put(SimpleProperty p){
		 
	      em.persist(p);
	      propEventSrc.fire(p);
	}
	 
	public void delete(SimpleProperty p){

		Query query = em.createQuery("delete FROM SimpleProperty p where p.key='"+p.getKey()+"'");
		query.executeUpdate();
		propEventSrc.fire(p);	 	      
	}

}

So, this bean saves new entries in the put method and deletes in the delete method. What is peculiar in this EJB is the injection of the Event object.

Events allow beans to communicate without any compile-time dependency. One bean can define an event, another bean can fire the event, yet another bean can handle the event. The beans can be also in separate packages and even in separate layers of the application. The class which is responsible to handle the event is a Producer class, which is in charge to retrieve the list of SimpleProperty objects every time a change in the list happens:

package com.mastertheboss.producer;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.event.Reception;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Named;

import com.mastertheboss.model.SimpleProperty;
import com.mastertheboss.repository.RepositoryManager;

@RequestScoped
public class Producer {
    @Inject
    RepositoryManager db;

    private List<SimpleProperty> propertyList;

    public void onMemberListChanged(@Observes(notifyObserver = Reception.IF_EXISTS) final SimpleProperty member) {
        retrieveData();
    }

    @Produces
    @Named
    public List<SimpleProperty> getPropertyList() {
        return propertyList;
    }

    public void setProperty(List<SimpleProperty> property) {
        this.propertyList = propertyList;
    }

    @PostConstruct
    public void retrieveData() {

        propertyList = db.queryCache();

    }

}

In order to keep this logical layer separated from the Database access, we are using another class named RepositoryManager to perform the actual queries against the Database:

package com.mastertheboss.repository;

import java.util.List;

import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import com.mastertheboss.model.SimpleProperty;

public class RepositoryManager {
 
	@Inject
	private EntityManager em;

	public List<SimpleProperty>  queryCache(){
		Query query = em.createQuery("FROM SimpleProperty");

		List <SimpleProperty> list =  query.getResultList();
		return list;	      
	}
}

Finally, have you noticed all back-end class @Inject the EntityManager class? We can then define a GenericProducer class which is useful if you want to provide a custom PersistenceContext for our application. In our case, we will just use the default one:

package com.mastertheboss.producer;

import javax.enterprise.inject.Produces;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class GenericProducer {
	@SuppressWarnings("unused")
	@Produces
	@PersistenceContext
	private EntityManager em;
}

You can connect your application to any datasource available in your WildFly configuration. To keep it easy, we have linked it to the ExampleDS database which is available out of the box. Also, by using the hibernate.hbm2ddl.auto property, you won’t need to create/drop table when using your application:

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0"
	xmlns="http://java.sun.com/xml/ns/persistence"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
	<persistence-unit name="primary">

		<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>

		<properties>
			<!-- Properties for Hibernate -->
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
			<property name="hibernate.show_sql" value="false" />
		</properties>
	</persistence-unit>
</persistence>

Here is the full pom.xml we have used to compile and deploy this application:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.mastertheboss</groupId>
	<artifactId>javaee8example</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>Java EE 8 webapp project</name>
	<description>A starter Java EE 8 webapp project for use on WildFly 14 or later</description>

	<properties>

		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.build.timestamp.format>yyyyMMdd'T'HHmmss</maven.build.timestamp.format>
		<version.wildfly.maven.plugin>1.0.2.Final</version.wildfly.maven.plugin>
	</properties>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.wildfly.bom</groupId>
				<artifactId>wildfly-javaee8-with-tools</artifactId>
				<version>14.0.1.Final</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.jboss.spec.javax.faces</groupId>
			<artifactId>jboss-jsf-api_2.3_spec</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>javax.persistence-api</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.jboss.spec.javax.ejb</groupId>
			<artifactId>jboss-ejb-api_3.2_spec</artifactId>
			<scope>provided</scope>
		</dependency>

	</dependencies>

	<build>
		<!-- Maven will append the version to the finalName (which is the name 
			given to the generated war, and hence the context root) -->
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<!-- Compiler plugin enforces Java 1.6 compatibility and activates annotation 
				processors -->
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.1</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.1.1</version>
				<configuration>
					<!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.wildfly.plugins</groupId>
				<artifactId>wildfly-maven-plugin</artifactId>
				<version>${version.wildfly.maven.plugin}</version>
			</plugin>
		</plugins>
	</build>

</project>

As you might have noticed, we have included Maven’s wildfly plugin so you can do compilation and deployment in one shot with:

$ mvn clean install wildfly:deploy

And here’s our application in action!

 

The source code for this application is available here: https://github.com/fmarchioni/mastertheboss/tree/master/javaee/javaee8example

Java EE 7 users ?

The source code, using Java EE 6 dependencies is available here: https://github.com/fmarchioni/mastertheboss/tree/master/javaee/javaee7example . This example is designed to run on WildFly 10 using Java EE 7 dependencies

Java EE 6 users ?

The source code, using Java EE 6 dependencies is available here: https://github.com/fmarchioni/mastertheboss/tree/master/javaee/javaee6example

Found the article helpful? if so please follow us on Socials