[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:
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:
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;