Navigation Menu

Skip to content

Commit

Permalink
Initial version of AdminJSF
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuir committed Apr 10, 2012
1 parent c3148e2 commit d65d6c0
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 14 deletions.
14 changes: 0 additions & 14 deletions AdminJSF.textile

This file was deleted.

245 changes: 245 additions & 0 deletions AdminJSF.txt
@@ -0,0 +1,245 @@
Adding an Admin UI using JSF
============================
Pete Muir <pmuir@redhat.com>
April 2012

You've just defined the domain model of your application, and all the entities managed directly by the end-users. Now it's time to build an administration GUI for the TicketMonster application using JSF and RichFaces. After reading this guide, you'll understand how to use JBoss Forge to create the views from the entities, how to "soup up" the UI using RichFaces, and how to test the UI using Selenium:

We'll round out the guide by revealing the required, yet short and sweet, configuration.

The tutorial will show you how to perform all these steps in JBoss Developer Studio, including screenshots that guide you through. For those of you who prefer to watch and learn, the included video shows you how we performed all the steps.


Setting up Forge
----------------

JBoss Enterprise Application Platform 6
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you are using JBoss Enterprise Application Platform 6, Forge is available in JBoss Developer Studio 5 (Beta1 or newer).

To show the Forge Console, navigate to _Window -> Show View -> Other_, locate _Forge Console_ and click _OK_. Then click the _Start_ button in top right corner of the view.


JBoss AS 7
~~~~~~~~~~

If you are using JBoss AS 7, you should install JBoss Forge version 1.0.2.Final or higher. Follow the instructions at link:https://docs.jboss.org/author/display/FORGE/Installation[Installing Forge].

Open a command line and navigate to the root directory of this quickstart.

Launch Forge by typing the following command:

forge


Required Forge Plugins
~~~~~~~~~~~~~~~~~~~~~~

Forge comes with a number of built in plugins, including the "scaffold" plugin, which is able to generate a full CRUD UI from JPA entities. The generated UI uses JSF as the view layer, backed by CDI beans. Internally, Forge uses http://metawidget.org/[Metawidget] to create the CRUD screens.

Forge also includes a powerful plugin management system. The RichFaces plugin isn't bundled with Forge, but it's easy to install. First use the `forge find-plugin` command to locate it

forge find-plugin richfaces

In this case, the plugin is just called `richfaces` - easy! We can install it using the `forge install-plugin` command:

forge install-plugin richfaces

This will download, compile and install the RichFaces plugin.


Getting started with Forge
--------------------------

Forge is a powerful rapid application development (aimed at Java EE 6) and project comprehension tool. It can operate both on projects it creates, and on existing projects, such as TicketMonster. If you want to learn more about Forge ...

When you `cd` into a project with Forge, it inspects the project, and detects what technologies you are using in the project. Let's see this in action:

project list-facets

Those facets detected are colored green.

[[project-list-faces_image]]
.Output of `project list-facets`
image::gfx/forge-project-list-facets.png[]

As you can see, Forge has detected all the technologies we are using, such as JPA, JAX-RS, CDI and Bean Validation.


Generating the CRUD UI
----------------------

.Forge Scripts
*************************************************************************************
Forge supports the execution of scripts. The generation of the CRUD UI is provided
as a Forge script in TicketMonster, so you don't need to type the commands everytime
you want to regenerate the Admin UI. To run the script:

run admin_layer.fsh
*************************************************************************************


Update the project
~~~~~~~~~~~~~~~~~~

First, we need to add Scaffold to the project. Run:

scaffold setup --targetDir admin

to instruct Forge to generate the css, images and templates used by the scaffolded UI. Forge also adds an error page to be used when a 404 or a 500 error is encountered.

[[project-scaffold-setup]]
.Output of `scaffold setup`
image::gfx/forge-scaffold-setup.png[]

Now, we need to add RichFaces to the project. Run:

richfaces setup

You'll be prompted for the version of RichFaces to use. Choose version `4.0.0.Final` (the default), by pressing *Enter*.

[[project-richfaces-setup]]
.Output of `richfaces setup`
image::gfx/forge-richfaces-setup.png[]


Scaffold the view from the JPA entities
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can either scaffold the entities one-by-one, which allows to control which UIs are generated, or you can generate a CRUD UI for all the entities. We'll do the latter:

scaffold from-entity org.jboss.jdf.example.ticketmonster.model.* --targetDir admin --overwrite

**************************************************************************************
Forge asks us whether we want to overwrite every file - which get's a bit tedious!
Specifying `--overwrite` allows Forge to overwrite files without prompt - much better!
**************************************************************************************

We now have a CRUD UI for all the entities used in TicketMonster!


Test the CRUD UI
----------------

Let's test our UI on our local JBoss AS instance. As usual, we'll build and deploy using Maven:

mvn clean package jboss-as:deploy


Make some changes to the UI
---------------------------

Let's add support for images to the Admin UI. TicketMonster doesn't provide support for storing images, but allows you to reference images from hosting sites on the internet. TicketMonster caches the images, so you can still use the application when you aren't connected to the internet.

We'll use JSF 2's composite components, which allow to easily create new components.

./src/main/webapp/resources/tm/image.xhtml
[source,html]
-------------------------------------------------------------------------------------------------------
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:composite="http://java.sun.com/jsf/composite">
<head>
<title>Cached Image</title>
</head>
<body>

<composite:interface>
<composite:attribute name="media" type="org.jboss.jdf.example.ticketmonster.services.MediaPath"/>
<composite:attribute name="id" type="java.lang.String" />
</composite:interface>

<composite:implementation>
<h:graphicImage value="#{cc.attrs.media.url}" rendered="#{!cc.attrs.media.cached}"/>
<h:graphicImage value="/rest/media/cache/#{cc.attrs.media.url}" rendered="#{cc.attrs.media.cached}"/>
</composite:implementation>

</body>
</html>
---------------------------------------------------------------------------------------------------------

The `image` composite component encapsulates the rendering of the image, pulling it from the remote location if the item is available and not cached, or pulling it from the cache if otherwise.

Adding this file to `/src/main/webapp/resources/tm/` automatically registers the component with JSF, using the namespace `xmlns:tm="http://java.sun.com/jsf/composite/tm`.

Let's go ahead and use this component to display the image in `src/main/webapp/admin/event/view.xhtml` - the page an admin uses to view an event before editing it. Open up the file in JBoss Developer Studio (or your favourite IDE or text editor). Forge has generated an entry in panel grid to display the image URL, so we can just replace the `<h:outputText id="eventBeanEventPicture" value="#{eventBean.event.picture}" />` with `<tm:image media="#{mediaManager.getPath(eventBean.event.picture)}" />`. We need to register the namespace as well, so add `xmlns:tm="http://java.sun.com/jsf/composite/tm"` to the `<ui:composition>` tag. You should end up with a file that looks a bit like:

./src/main/webapp/admin/event/view.xhtml
[source,html]
-------------------------------------------------------------------------------------------------------
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:tm="http://java.sun.com/jsf/composite/tm"
template="/resources/scaffold/pageTemplate.xhtml">

<f:metadata>
<f:viewParam name="id" value="#{eventBean.id}" />
<f:event type="preRenderView" listener="#{eventBean.retrieve}" />
</f:metadata>

<ui:param name="pageTitle" value="View Event" />

<ui:define name="header">
Event
</ui:define>

<ui:define name="subheader">
View existing Event
</ui:define>

<ui:define name="footer" />

<ui:define name="main">
<h:panelGrid columnClasses="label,component,required"
columns="3">
<h:outputLabel for="eventBeanEventName" value="Name:" />
<h:outputText id="eventBeanEventName"
value="#{eventBean.event.name}" />
<h:outputText />
<h:outputLabel for="eventBeanEventPicture" value="Picture:" />
<tm:image
media="#{mediaManager.getPath(eventBean.event.picture)}" />
<h:outputText />
<h:outputLabel for="eventBeanEventCategory"
value="Category:" />
<h:link id="eventBeanEventCategory"
outcome="/admin/eventCategory/view"
value="#{eventBean.event.category}">
<f:param name="id"
value="#{eventBean.event.category.id}" />
</h:link>
<h:outputText />
<h:outputLabel for="eventBeanEventDescription"
value="Description:" />
<h:outputText id="eventBeanEventDescription"
value="#{eventBean.event.description}" />
<h:outputText />
<h:outputLabel value="Major:" />
<h:outputText
styleClass="#{eventBean.event.major ? 'boolean-true' : 'boolean-false'}" />
<h:outputText />
</h:panelGrid>

<div class="buttons">
<h:link value="View All" outcome="search" />
<h:link value="Edit" outcome="create"
includeViewParams="true" />
<h:link value="Create New" outcome="create" />
</div>
</ui:define>

</ui:composition>
-------------------------------------------------------------------------------------------------------

We can test these changes by running

mvn clean package jboss-as:deploy

as usual.
Binary file added gfx/forge-project-list-facets.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gfx/forge-richfaces-setup.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gfx/forge-scaffold-setup.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d65d6c0

Please sign in to comment.