JBoss Forge ships now with the 3.x release which brings several enhancements to the project creator engine. Besides it, the release 3.x has changed the option names syntax a bit, switching to a dashed and lower-cased structure. Let’s see how we can quickly create a project to be deployed on WildFly 10.
Starting Forge 3
Forge downloads are available at: https://forge.jboss.org/download
Pickup the latest stable version and start the forge tool:
$ bin/forge
You can even skip the installation if you have JBoss Developer Studio which already ships with Forge Console. Just switch the view to Forge Console and you can start using Forge!
Creating a simple Java EE Project with Forge
Let’s start building up a new project named “demo-forge” which uses the JAVA EE 7 stack, therefore its target will be WildFly:
project-new --named demo-forge --type war --stack JAVA_EE_7
What is really cool if you are using JBoss Developer Studio is that the project will be automatically created in your Workspace so no need to search and import it:
Now let’s create one Model object which will be eventually scaffolded:
jpa-new-entity --named Customer jpa-new-field --named name --not-nullable jpa-new-field --named surname --not-nullable jpa-new-field --named email --not-nullable
As you can see, we have created the Customer Entity class and included a basic NotNull constraint on the top of it. If we want, we can create more complex constraint such as Regular Expression patterns as follows:
constraint-add --on-property email --constraint Pattern --regexp ^(.+)@(.+)$
Done with the model, we will now create the Faces layer through the scaffold-generate command, specifying the provider (Faces) and the Web context root:
scaffold-generate --targets org.demo.forge.model.Customer --web-root demo-forge --provider Faces
Please note that Forge uses lots of defaults to simplify your project creation. In our case, as we have omitted the base package name in the project creation, the root package org.[project.name] has been usedDone with the project, it’s time to build it, which will trigger the maven install command:@SHELLbuild
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
Here is your application up and running:
Please note that on some versions of Linux (such as Fedora 21) you can incur in issues when installing the jboss-as-addon, due to an excessive number of io watches created. In order to cope with it (if you really don’t want to install the Maven WildFly plugin :-)!) you can increase that number with:
$ sudo sysctl fs.inotify.max_user_watches=20000
How to create a CRUD REST application with Forge
In the second example, we will show how to scaffold a JAX-RS application which uses JPA to store your data.
Firstly, create a new Project named “demo-rest” which uses JAVA EE 7 stack
project-new --named demo-rest --type war --stack JAVA_EE_7
We will then add an Entity object named Customer
jpa-new-entity --named Customer jpa-new-field --named firstname jpa-new-field --named surname jpa-new-field --named email
Now we move to the top of our project and we generate the REST Endpoints to CRUD our Entities:
cd ~~ rest-generate-endpoints-from-entities --targets org.demo.rest.model.Customer
As you can see, the following EJB Rest Resource has been created:
@Stateless @Path("/customers") public class CustomerEndpoint { @PersistenceContext(unitName = "demo-rest-persistence-unit") private EntityManager em; @POST @Consumes("application/json") public Response create(Customer entity) { em.persist(entity); return Response.created( UriBuilder.fromResource(CustomerEndpoint.class) .path(String.valueOf(entity.getId())).build()).build(); } @DELETE @Path("/{id:[0-9][0-9]*}") public Response deleteById(@PathParam("id") Long id) { Customer entity = em.find(Customer.class, id); if (entity == null) { return Response.status(Status.NOT_FOUND).build(); } em.remove(entity); return Response.noContent().build(); } @GET @Path("/{id:[0-9][0-9]*}") @Produces("application/json") public Response findById(@PathParam("id") Long id) { TypedQuery<Customer> findByIdQuery = em .createQuery( "SELECT DISTINCT c FROM Customer c WHERE c.id = :entityId ORDER BY c.id", Customer.class); findByIdQuery.setParameter("entityId", id); Customer entity; try { entity = findByIdQuery.getSingleResult(); } catch (NoResultException nre) { entity = null; } if (entity == null) { return Response.status(Status.NOT_FOUND).build(); } return Response.ok(entity).build(); } @GET @Produces("application/json") public List<Customer> listAll(@QueryParam("start") Integer startPosition, @QueryParam("max") Integer maxResult) { TypedQuery<Customer> findAllQuery = em.createQuery( "SELECT DISTINCT c FROM Customer c ORDER BY c.id", Customer.class); if (startPosition != null) { findAllQuery.setFirstResult(startPosition); } if (maxResult != null) { findAllQuery.setMaxResults(maxResult); } final List<Customer> results = findAllQuery.getResultList(); return results; } @PUT @Path("/{id:[0-9][0-9]*}") @Consumes("application/json") public Response update(@PathParam("id") Long id, Customer entity) { if (entity == null) { return Response.status(Status.BAD_REQUEST).build(); } if (id == null) { return Response.status(Status.BAD_REQUEST).build(); } if (!id.equals(entity.getId())) { return Response.status(Status.CONFLICT).entity(entity).build(); } if (em.find(Customer.class, id) == null) { return Response.status(Status.NOT_FOUND).build(); } try { entity = em.merge(entity); } catch (OptimisticLockException e) { return Response.status(Response.Status.CONFLICT) .entity(e.getEntity()).build(); } return Response.noContent().build(); } }
Now our Forge REST project is complete.
Scripting with JBoss Forge
Running a JBoss Forge script is an handy feature to create quickly an application starting from a script file. All you have to do is starting Forge and run the script file as follows:
run <scriptname>
As an example, pickup the following script from the quickstarts:
Run this file from the Forge console using the run
command:
$ run generate.fsh
At this point, Forge creates the new project and builds it.