Archetype Tutorial
In this tutorial we will create a simple Java EE application from scratch using Sculptors Maven archetypes. We will start with a simple war, deployed in Jetty and using HSQLDB in-memory database. Later on it is illustrated how it can be converted to use MySQL and be deployed in JBoss.
Before you start you must follow the instructions in the Installation Guide.
Table of Contents:
- Part 1 - Setup Maven projects
- Part 2 - Generate Code
- Part 3 - Deploy in JBoss
- Part 4 - Use MySQL Database
Part 1 - Setup Maven projects
In this first part we will setup the project structure for Maven and Eclipse.
Create Maven projects
Our Java EE application consists of the following projects:
helloworld-parent- Only a Maven project for building the other parts.helloworld- Business tier. Containing the services and domain objects.helloworld-web- Presentation tier. Web application with REST resources (as described in the REST Tutorial) for the services defined in the business tier.
We start with creating a script that calls the Sculptor Maven archetypes to generate the project structures and Maven build files. It also defines the environment variables (as described in the installation guide) and does an initial build. Of course you can execute these commands one by one from the command prompt, but the script is useful when doing this several times.
Copy one of the following scripts into the root of your Eclipse workspace.
-
Windows script
sculptor-archetypes.cmd:set JAVA_HOME=c:\Program Files\Java\jdk1.7.0_25\ set M2_HOME=C:\devtools\apache-maven-3.0.5\ set MAVEN_OPTS=-Xms128m -Xmx1024m -XX:MaxPermSize=128m set path=%JAVA_HOME%\bin;%M2_HOME%\bin set PACKAGE=%1 set SYS_NAME=%2 set VERSION=3.1.0 mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.sculptorgenerator -DarchetypeArtifactId=sculptor-maven-archetype-parent -DarchetypeVersion=%VERSION% -DgroupId=%PACKAGE% -DartifactId=%SYS_NAME%-parent -Dpackage=%PACKAGE% -Dversion=1.0-SNAPSHOT -Dweb=true mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.sculptorgenerator -DarchetypeArtifactId=sculptor-maven-archetype -DarchetypeVersion=%VERSION% -DgroupId=%PACKAGE% -DartifactId=%SYS_NAME% -Dpackage=%PACKAGE% -Dversion=1.0-SNAPSHOT -Djboss=false mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.sculptorgenerator -DarchetypeArtifactId=sculptor-maven-archetype-web -DarchetypeVersion=%VERSION% -DgroupId=%PACKAGE% -DartifactId=%SYS_NAME%-web -Dpackage=%PACKAGE% -Dversion=1.0-SNAPSHOT -Drest=true -Djboss=false pause call mvn install -f %SYS_NAME%-parent\pom.xml -
Unix bash script
sculptor-archetypes.sh:#!/bin/bash if [ -z $1 ] || [ -z $2 ]; then echo -e "Usage: $0 PACKAGEID ARTIFACTID\n\tPACKAGEID - name of Java package, for example org.helloworld" echo -e "\tARTIFACTID - project base name, for example helloworld" exit 1 fi JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/ M2_HOME=/opt/apache-maven-3.0.5 MAVEN_OPTS="-Xms128m -Xmx1024m -XX:MaxPermSize=128m" path=$path:$JAVA_HOME/bin:$M2_HOME/bin export JAVA_HOME M2_HOME MAVEN_OPTS path PACKAGE=$1 SYS_NAME=$2 VERSION=3.1.0 mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.sculptorgenerator -DarchetypeArtifactId=sculptor-maven-archetype-parent \ -DarchetypeVersion=$VERSION -DgroupId=$PACKAGE -DartifactId=$SYS_NAME-parent \ -Dpackage=$PACKAGE -Dversion=1.0-SNAPSHOT -Dweb=true mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.sculptorgenerator -DarchetypeArtifactId=sculptor-maven-archetype \ -DarchetypeVersion=$VERSION -DgroupId=$PACKAGE -DartifactId=$SYS_NAME \ -Dpackage=$PACKAGE -Dversion=1.0-SNAPSHOT -Djboss=false mvn archetype:generate -DinteractiveMode=false -DarchetypeGroupId=org.sculptorgenerator -DarchetypeArtifactId=sculptor-maven-archetype-web \ -DarchetypeVersion=$VERSION -DgroupId=$PACKAGE -DartifactId=$SYS_NAME-web \ -Dpackage=$PACKAGE -Dversion=1.0-SNAPSHOT -Drest=true -Djboss=false sleep 1 mvn install -f $SYS_NAME-parent/pom.xmlTo make the script executable use run the command
chmod +x sculptor-archetypes.sh.
You have to adjust the paths used in the variables of this scripts to your environment.
Run this script by defining the package name as the first parameter and the application id (artifact id of business tier) as the second parameter:
sculptor-archetypes org.helloworld helloworld
Import Maven projects into Eclipse
Open Eclipse and import the newly created Maven projects with m2e (Maven Integration for Eclipse) via “File > Import… > Existing Maven Projects”.
Then create the following m2e launch configurations via context menu “Run As > Maven build…” on the corresponding projects POM:
- For the project
helloworld-parentuse the Maven goalsclean installto rebuild all projects. - For the projects
helloworldandhelloworld-webuse the Maven goalgenerate-sourcesto start Sculptors code generator.
To refresh the Eclipse workspace after Sculptors code generator created new code enable the option “Refresh > Refresh resources upon completion > The project containing the selected resource” in the launch configurations.
After executing a Maven build from the commandline the corresponding projects in Eclipse have to be refreshed manually (via “File > Refresh” or F5)
Sometimes, validation errors in code generation files (.xtend) must be cleaned manually as well. This can be done with a “clean build” (using “Project > Clean…”) of the corresponding Eclipse project.
Part 2 - Generate Code
In this part we will write a Sculptor DSL file and generate code from it.
Complete Business Tier
To allow us using the module with the business tier from within the presentation tier we have to create several model files (see Advanced Tutorial).
Open model.btdesign located in src/main/resources of the helloworld project and replace the content with the folowing model:
import "classpath:/model-planet.btdesign"
Application Universe {
basePackage=org.helloworld
}
Here the actual model of the business tier is imported (as ApplicationPart) from a model file we’re creating next.
Create the file model-person.btdesign in src/main/resources of the helloworld project and add something like this to the design file:
ApplicationPart Planet {
Module planet {
Service PlanetService {
findById => PlanetRepository.findById;
findAll => PlanetRepository.findAll;
save => PlanetRepository.save;
delete => PlanetRepository.delete;
}
Entity Planet {
scaffold
String name
int diameter
int population
Repository PlanetRepository {
findById;
save;
delete;
findAll;
}
}
}
}
Note the scaffold feature of Planet. It will result in automatically generated domain objects PlanetRepository and PlanetService with CRUD operations for the entity Planet.
Complete Presentation Tier
For the presentation we’re using a simple CRUD gui generated from the REST resources defined for business services. For details refer to the REST Tutorial.
In the presentation tier model we’re referencing the model of the business tier which is already generated in the project helloworld. To skip generation of a module you define the module (planet in this example) in sculptor-generator.properties (as described in the Advanced Tutorial):
generate.module.planet=false
Now let’s add the REST resources for the CRUD gui. Open model.btdesign located in src/main/resources of the helloworld-web project and add something like this to the design file:
import "classpath:/model-planet.btdesign"
Application Universe {
basePackage=org.helloworld
Module planetweb {
Resource FrontResource {
String front return="redirect:/rest/planet";
}
Resource PlanetResource {
String createForm;
create => PlanetService.save;
show => PlanetService.findById;
showAll => PlanetService.findAll;
delete => PlanetService.delete;
}
}
}
Note the Resource operation front in the FrontResource. It represents the link named “Home” in the generated JSPs. In this case we’re redirecting to the operation showAll in the ‘PlanetResource’.
Launch Maven build
Start the Maven build from within Eclipse via “Run As > Maven Build” on the helloworld-parent project.
We skip the JUnit tests in this tutorial. See part 3 of the Hello World Tutorial for more information on fixing the failing JUnit tests.
Run in Jetty
Start Jetty with mvn jetty:run in the helloworld-web project. Note that no installation is needed. Jetty is launched by Maven.
Open the URL http://localhost:8888/ in your browser. Try the CRUD GUI and create some favourite Planets. The features of the generated web application are explained in the REST Tutorial.
By default an in memory database, hsqldb, is bundled with the the application. Of course, when you restart the application or server all data added will be lost. Jetty is an excellent development server, and you can stop here if you don’t need to run in JBoss. You can also convert to JBoss later if you like.
Part 3 - Deploy in JBoss
In this final part we’re going to deploy our WAR in JBoss.
Start JBoss
-
Download JBoss AS 7.2 from here or here and unpack the archive.
-
From within
JBOSS_HOMEstart JBoss in “standalone” mode, e.g../bin/standalone.sh. -
Test your JBoss AS installation by pointing your browser to http://localhost:8080 which brings you to the Welcome Screen
Configure JBoss
Before we can deploy our WAR we have to prepare some resources within JBoss first:
-
JBoss AS 7 doesn’t come with HSQLDB anymore (instead JBoss uses H2 as in-memory database). So we have to install the HSQLDB JDBC driver first. For this we’re using the JBoss Command Line Client (CLI) as described here. Locate the latest version of the HSQLDB JDBC driver JAR in you local Maven repository and fire up JBoss CLI:
./bin/jboss-cli.sh [disconnected /] connect [standalone@localhost:9999 /] module add --name=org.hsqldb --resources=/Users/torsten/Develop/maven-repos/org/hsqldb/hsqldb/2.2.9/hsqldb-2.2.9.jar --dependencies=javax.api,javax.transaction.api [standalone@localhost:9999 /] /subsystem=datasources/jdbc-driver=hsqldb:add(driver-module-name=org.hsqldb, driver-name=hsqldb, driver-class-name=org.hsqldb.jdbc.JDBCDriver) {"outcome" => "success"}In the above
module addcommand you have to update theresourcesparameter with the full path to your local Maven repository! -
Next we need the datasource
UniversedDSwhich is using HSQLDB. A deployable datasource configuration can be found insrc/generated/resources/dbschema/hellowrld-ds.xml. But we’re using JBoss CLI for this as well:[standalone@localhost:9999 /] /subsystem=datasources/data-source=UniverseDS:add(driver-name="hsqldb", connection-url="jdbc:hsqldb:mem:universe", jndi-name="java:/jdbc/UniverseDS", use-java-context=true, user-name="sa", password="sa") {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=datasources/data-source=UniverseDS:enable(persistent=true) {"outcome" => "success"}
Adjust for JBoss
To deploy the WAR in JBoss the following adjustments have to be made:
-
Since JBoss has some libraries in its default classpath you need to adjust several dependencies in
pom.xmlfiles (both business tier and presentation tier). Hibernate, slf4j and some more should not be bundled in WAR or EAR when deployed to JBoss. To generate different POMs with the Sculptor Maven archetypes you have to set the property-Djboss=totruein the scriptsculptor-archetypescreated in chapter “Part 1 - Setup Maven projects”. Then delete both POM files and re-run the scriptsculptor-archetypes. -
To create code for JBoss instead of Jetty you have to adjust the following property in
sculptor-generator.propertiesinhelloworldandhelloworld-webproject.deployment.applicationServer=JBoss -
To get a proper context root for the deployed web app (the default one is the name of the WAR file) you have to create the JBoss deployment descriptor
jboss-web.xmlin the foldersrc/main/webapp/WEB-INF/of thehellowworld-webproject with the following content:<?xml version="1.0" encoding="UTF-8"?> <jboss-web> <context-root>/helloworld</context-root> </jboss-web>
Rebuild with mvn clean install from the helloworld-parent project.
Deploy to JBoss
Deploy the WAR file to JBoss via mvn jboss-as:deploy in the project helloworld-web.
Open http://localhost:8080/helloworld in your browser.
Part 4 - Use MySQL Database
To use JBoss with MySQL instead of HSQLDB the following adjustments are neccessary:
-
Adjust the following properties in
sculptor-generator.propertiesin the projecthelloworldto let Sculptor generate a database creation sql script (DDL) for MySQL insrc/generated/resources/dbschema/:db.product=mysql generate.ddl=true -
Rebuild with
mvn clean installfrom projecthelloworld-parent. -
Create the database schema named
universein your MySQL database and run the DDL SQL script inhelloworld/src/generated/resources/dbschema/to create the database tables. You can use MySQLWorkbench to do that or use the MySQL command line client:mysql -u root mysql> create database universe; mysql> connect universe; mysql> source helloworld/src/generated/resources/dbschema/Universe_ddl.sql -
JBoss AS 7 doesn’t come with the MySQL JDBC driver. So we have to download the MySQL JDBC driver from http://dev.mysql.com/downloads/connector/j/ and install it first. For this we’re using the JBoss Command Line Client (CLI) as described here:
./bin/jboss-cli.sh [disconnected /] connect [standalone@localhost:9999 /] module add --name=com.mysql --resources=/Users/torsten/Develop/maven-repos/mysql/mysql-connector-java/5.1.26/mysql-connector-java-5.1.26.jar --dependencies=javax.api,javax.transaction.api [standalone@localhost:9999 /] /subsystem=datasources/jdbc-driver=mysql:add(driver-module-name=com.mysql, driver-name=mysql, driver-class-name=com.mysql.jdbc.Driver) {"outcome" => "success"}In the above
module addcommand you have to update theresourcesparameter with the full path to your MySQL JDBC driver! -
Next we have to replace the previously created datasource
UniversedDS(which is using HSQLDB) by one using MySQL instead. A deployable datasource configuration can be found insrc/generated/resources/dbschema/hellowrld-ds.xml. But we’re using JBoss CLI for this as well:[standalone@localhost:9999 /] /subsystem=datasources/data-source=UniverseDS:remove {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=datasources/data-source=UniverseDS:add(driver-name="mysql", connection-url="jdbc:mysql://localhost/universe", jndi-name="java:/jdbc/UniverseDS", use-java-context=true, user-name="root") {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=datasources/data-source=UniverseDS:enable(persistent=true) {"outcome" => "success"} -
Redeploy and test again.