Reverse Engineer your DB schema using JBoss Forge

[Updated] In this article we will show a more advanced example of Java EE Application using JBoss Forge 3 capabilities to reverse engineer the Entities from the Database.

So this tutorial will use the Hibernate plugin for Forge and reverse engineer a MySQL database into the Java domain. Start by creating a database let’s say demoforge and add two tables in it, containing a One-To-Many relationship in it:

CREATE database demoforge;

USE demoforge;

CREATE TABLE department (
department_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
department_name VARCHAR(45) NOT NULL,
PRIMARY KEY (department_id)
);
 
CREATE TABLE employee (
employee_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
employee_name VARCHAR(45) NOT NULL,
employee_salary INTEGER UNSIGNED NOT NULL,
employee_department_id INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (employee_id),
CONSTRAINT FK_employee_1 FOREIGN KEY FK_employee_1 (employee_department_id)
REFERENCES department (department_id)
ON DELETE CASCADE
ON UPDATE CASCADE
);				

Here’s a view of our simple schema:

jboss forge hibernate

Now let’s start Forge:

/bin/forge					

Then, create a new project (params are optional though you might add them to automate the project creation):

project-new --named demo-forge --stack JAVA_EE_7 --type war

A Web project named jpa-demo will be created, using the Java EE 7 API and defaults to Maven project structure. In order to enable reverse engineering we need at first set up the JPA with the jpa addon:

jpa-setup --data-source-name MySQLDS --db-type MYSQL

Now let’s reverse engineer out schema: (customize the Path where the JDBC Driver is located):

jpa-generate-entities-from-tables --jdbc-url jdbc:mysql://localhost/demoforge --user-name jboss --user-password jboss --driver-location /tmp/mysql-connector-java-5.1.18-bin.jar --hibernate-dialect org.hibernate.dialect.org.hibernate.dialect.MySQL5Dialect --driver-class com.mysql.jdbc.Driver --database-tables *

So with the above command, we will reverse enginner all tables contained in the schema demoforge into Entities. Good, now add some faces scaffolding for the GUI:

scaffold-generate --targets org.demo.forge.model.* --web-root demo-forge --provider Faces

Here is the project structure generated:

forge reverse enginner

And this is the persistence.xml file that was automatically created:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="forge-default" transaction-type="JTA">
    <description>Forge Persistence Unit</description>
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/MySQLDS</jta-data-source>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
      <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="hibernate.transaction.flush_before_completion" value="true"/>
    </properties>
  </persistence-unit>
</persistence>

For the sake of completeness we include a sample JBoss MySQL datasource definition which can be dropped as it is into the deployments folder (since JBoss AS 7.1.1):

<datasources xmlns="http://www.jboss.org/ironjacamar/schema">
<datasource jndi-name="java:jboss/datasources/MySqlDB" pool-name="MySQLPool">
    <connection-url>jdbc:mysql://localhost:3306/demoforge</connection-url>
    <driver>mysql-connector-java-5.1.18-bin.jar</driver>
    <pool>
        <max-pool-size>30</max-pool-size>
    </pool>
    <security>
        <user-name>jboss</user-name>
        <password>jboss</password>
    </security>
</datasource>
</datasources>

Here are the generated classes for the Entities Department.java and Employee.java

import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "department", schema = "hibernate")
public class Department implements java.io.Serializable
{

   private Long departmentId;
   private String departmentName;
   private Set<Employee> employees = new HashSet<Employee>(0);

   public Department()
   {
   }

   public Department(String departmentName)
   {
      this.departmentName = departmentName;
   }

   public Department(String departmentName, Set<Employee> employees)
   {
      this.departmentName = departmentName;
      this.employees = employees;
   }

   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "department_id", unique = true, nullable = false)
   public Long getDepartmentId()
   {
      return this.departmentId;
   }

   public void setDepartmentId(Long departmentId)
   {
      this.departmentId = departmentId;
   }

   @Column(name = "department_name", nullable = false, length = 45)
   public String getDepartmentName()
   {
      return this.departmentName;
   }

   public void setDepartmentName(String departmentName)
   {
      this.departmentName = departmentName;
   }

   @OneToMany(fetch = FetchType.LAZY, mappedBy = "department")
   public Set<Employee> getEmployees()
   {
      return this.employees;
   }

   public void setEmployees(Set<Employee> employees)
   {
      this.employees = employees;
   }

}
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "employee", schema = "hibernate")
public class Employee implements java.io.Serializable
{

   private Long employeeId;
   private Department department;
   private String employeeName;
   private int employeeSalary;

   public Employee()
   {
   }

   public Employee(Department department, String employeeName, int employeeSalary)
   {
      this.department = department;
      this.employeeName = employeeName;
      this.employeeSalary = employeeSalary;
   }

   @Id
   @GeneratedValue(strategy = IDENTITY)
   @Column(name = "employee_id", unique = true, nullable = false)
   public Long getEmployeeId()
   {
      return this.employeeId;
   }

   public void setEmployeeId(Long employeeId)
   {
      this.employeeId = employeeId;
   }

   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "employee_department_id", nullable = false)
   public Department getDepartment()
   {
      return this.department;
   }

   public void setDepartment(Department department)
   {
      this.department = department;
   }

   @Column(name = "employee_name", nullable = false, length = 45)
   public String getEmployeeName()
   {
      return this.employeeName;
   }

   public void setEmployeeName(String employeeName)
   {
      this.employeeName = employeeName;
   }

   @Column(name = "employee_salary", nullable = false)
   public int getEmployeeSalary()
   {
      return this.employeeSalary;
   }

   public void setEmployeeSalary(int employeeSalary)
   {
      this.employeeSalary = employeeSalary;
   }

}

Deploying the project to WildFly can be easily achieved by adding to your pom.xml the Maven’s WildFly plugin

<plugin>
    <groupId>org.wildfly.plugins</groupId>
    <artifactId>wildfly-maven-plugin</artifactId>
    <version>1.0.2.Final</version>
    <configuration>
        <filename>${project.build.finalName}.war</filename>
    </configuration>
</plugin>

Otherwise, you can do it directly from Forge, but you have to install a couple of adds-on first:

addon-install-from-git --url https://github.com/forge/as-addon  --coordinate org.jboss.forge.addon:as
addon-install-from-git --url https://github.com/forge/jboss-as-addon  --coordinate org.jboss.forge.addon:jboss-as-wf

Now you will need to set up at first the application server version to be used with:

as-setup --server wildfly --version 10.1.0.Final

And finally, you can deploy it with:

as-deploy

Thanks to George Gastaldi, the Forge Project lead for his precious hints on the reverse engineers process!

Forge 1

If you are using Forge 1 the syntax of reverse engineer command is a bit different. Let’s include it for your reference. At first  you have to install the hibernate plugin for Forge with the following command:

forge install-plugin hibernate-tools					

Then, create a new project (params are optional though you might add them to automate the project creation)

new-project --named as7demo --topLevelPackage com.sample --projectFolder C:\forge-distribution-1.0.5.Final\projects\as7demo

Next add persistence to it:

persistence setup --provider HIBERNATE --container JBOSS_AS7 ;

Now let’s reverse engineer out schema: (customize user/database/url to your case):

generate-entities configure-settings --dialect  org.hibernate.dialect.MySQLDialect \
--driver com.mysql.jdbc.Driver --url jdbc:mysql://localhost/hibernate --pathToDriver \
C:\forge-distribution-1.0.5.Final\lib\mysql-connector-java-5.1.18-bin.jar --user jboss

***INFO*** The command [generate-entities] takes [0] unnamed argument(s), but found [1].
***INFO*** Swallowed unknown token [configure-settings] for command [generate-entities].
 ? Enter the password for JDBC connection.

Found 2 tables in datasource
Generated java at C:\forge-distribution-1.0.5.Final\bin\as7forge\as7demo\src\main\java\com\sample\model\Department.java
Generated java at C:\forge-distribution-1.0.5.Final\bin\as7forge\as7demo\src\main\java\com\sample\model\Employee.java
Generated 2 java files.

Once entered the password for the JDBC Connection the Tables will be added. Good, now add some faces scaffolding for the GUI:

scaffold setup --scaffoldType faces;

And generate the CRUD view for each view using scaffold from-entity command:

scaffold from-entity com.sample.model.* --overwrite;