1.4 Part 3 - Other Examples

The Metawidget distribution includes other examples showcasing particular features on particular platforms. These additional examples are not a required part of the tutorial, but you may find them useful depending on which platform you use.

1.4.1 Swing Applet Address Book Example

The Swing Applet Address Book Example demonstrates using Metawidget in applets. The example is pre-built for you in examples/swing/applet/addressbook. Alternatively you can build it yourself by changing to the src/examples folder and typing:

mvn -pl org.metawidget.examples.swing:addressbook-swing-applet -am integration-test

To run the applet, open the index.html file in a Web browser. The code is identical to the Swing Address Book covered in Part 2 of this tutorial, except it uses org.metawidget.example.swing.applet.AddressBookApplet instead of org.metawidget.example.swing.addressbook.MainFrame.

The notable feature of the example is how the applet is packaged. Metawidget is highly modular and has no mandatory third-party JAR dependencies. The addressbook-swing-applet Maven POM uses fine-grained Metawidget dependencies (as an alternative to metawidge-all.jar) to include only those modules necessary for the applet. The resulting small download size makes Metawidget very viable for applet-based environments. See Section 9.5.1, “JAR Size”.

1.4.2 Seam Example

The Seam Booking Example demonstrates updating an existing Seam application to use Metawidget, reducing boilerplate code. The example is included as part of Seam 2.2.0.GA. It also requires you to have JBoss 5.1.0.GA, and you should be familiar with the existing Seam Booking application.

The example is located in jboss-seam-2.2.0.GA/examples/metawidget/booking. It is not pre-built. To build it, change to the examples/metawidget/booking folder in the Seam binary distribution and type:

ant

To run it, type:

cd \Applications\jboss-5.1.0.GA
bin\run

Open a Web browser to http://localhost:8080/seam-booking. The updated Metawidget Seam Booking Example looks very similar to the original, as in Figure 1.33, but uses significantly less boilerplate code.

Seam Booking with Metawidget

Figure 1.33. Seam Booking with Metawidget


The files modified for adding Metawidget support are in examples/metawidget/booking. Most of the UI code in view/book.xhtml, view/confirm.xhtml and view/hotelview.xhtml has been replaced with a single Metawidget tag. Some annotations have been added to Hotel.java and Booking.java, though Metawidget also leverages the existing JPA and Hibernate Validator ones.

1.4.3 Groovy Example

The Seam Groovy Booking Example demonstrates updating an existing Seam Groovy application to use Metawidget, reducing boilerplate code. The example is a more advanced version of the previous Seam section, so you should work through that first.

The example is located in jboss-seam-2.2.0.GA/examples/metawidget/groovybooking. It is not pre-built. To build it, change to the examples/metawidget/groovybooking folder in the Seam distribution and type:

ant

To run it, type:

cd \Applications\jboss-5.1.0.GA
bin\run

Open a Web browser to http://localhost:8080/jboss-seam-groovybooking. As with the previous section, the updated Metawidget Seam Groovy Booking Example looks very similar to the original, but uses significantly less boilerplate code. This time we are using Groovy to define our business classes. The biggest impact this has is in metawidget.xml, where the Inspectors have been configured to use a Groovy property style instead of a JavaBean property style.

Metawidget supports pluggable 'property styles' for JavaBean, Groovy and other property styles. Groovy properties differ from JavaBean properties in that their annotations are tied to the private field, rather than the getters and setters. The use of Groovy is configured per Inspector, as in examples/metawidget/groovybooking/resources/WEB-INF/metawidget.xml:

<propertyTypeInspector config="org.metawidget.inspector.impl.BaseObjectInspectorConfig">
	<propertyStyle>
		<groovyPropertyStyle xmlns="java:org.metawidget.inspector.impl.propertystyle.groovy"/>
	</propertyStyle>
</propertyTypeInspector>

The example demonstrates how Metawidget can significantly reduce the amount of boilerplate code in your UI layer - in some cases up to 70%. Figure 1.33 shows the book.xhtml page before and after being fitted with Metawidget. The red boxes and lines highlight the chunks of boilerplate that have been removed:

book.xhtml before and after being fitted with Metawidget

Figure 1.34. book.xhtml before and after being fitted with Metawidget


1.4.4 jBPM Example

The Seam DVD Store Example demonstrates updating an existing Seam jBPM application to use Metawidget, reducing boilerplate code. The example requires you to have previously downloaded Seam 2.2.0.GA and JBoss 5.1.0.GA, and you should be familiar with the existing Seam DVD Store application.

The example is located in jboss-seam-2.2.0.GA/examples/metawidget/dvdstore. It is not pre-built. To build it, change to the examples/metawidget/dvdstore folder in the Seam distribution and type:

ant

To run it, type:

cd \Applications\jboss-5.1.0.GA
bin\run

Open a Web browser to http://localhost:8080/seam-dvdstore. As with the previous two sections, the updated Metawidget Seam DVD Store example looks very similar to the original, as in Figure 1.35, but uses significantly less boilerplate code.

Seam DVD Store with Metawidget

Figure 1.35. Seam DVD Store with Metawidget


This time, as well as generating UIComponents for domain objects such as com.jboss.dvd.seam.Customer, Metawidget inspects jBPM pageflow files like newuser.jpdl.xml and checkout.jpdl.xml to generate the correct UICommand buttons for each screen.

1.4.5 ICEfaces Example

ICEfaces is an AJAX component library for Java Server Faces. This example showcases how Metawidget can work with ICEfaces (1.8.2 and above) to deliver rich AJAX applications.

The example is pre-built for you in examples/faces/penguincolony-faces.war. Copy the WAR into Tomcat's webapps folder, start Tomcat, and open a Web browser to http://localhost:8080/penguincolony-faces:

ICEfaces with Metawidget

Figure 1.36. ICEfaces with Metawidget


The application manages details of penguins in a colony. To begin, click the Edit link in the first row of the table: ICEfaces and Metawidget work together to pop up an AJAX form without refreshing the page. Next, clear the form's Name box and tab to the next field: an AJAX call is made and a validation error appears. Try entering a new name and tabbing again: the validation error disappears and the new name is immediately reflected in the table behind the popup box.

The remaining fields are wrapped in an ICEfaces PanelTabSet. Click on the Details tab. Here, the example makes use of the @UiAttribute annotation and FacesInspectionResultProcessor. The Java code is annotated:

@UiAction
@UiAttribute( name = InspectionResultConstants.HIDDEN, value = "#{!empty _this.condition}" )
public void addCondition() { ... }

@UiAttribute( name = InspectionResultConstants.HIDDEN, value = "#{empty _this.condition}" )
public PenguinCondition getCondition() { ...}

Clicking the Add Condition button, or checking one of the Hobbies checkboxes, triggers an AJAX call that re-evaluates the @UiAttribute annotations and dynamically reconstructs the form without requiring a page refresh. This includes removing existing buttons, creating new dropdown boxes and creating new labels.

For more details on ICEfaces support, see the section called “IceFacesWidgetBuilder” and the section called “PanelTabSetLayoutDecorator”.

1.4.6 Java EE 6 Example

There is a retrofitted version of the GatewayWarDeployment example from Adam Bien's Real World Java EE Patterns book downloadable from his Java EE Patterns and Best Practices Kenai Repository.

For more information, see this blog entry.

1.4.7 Swing AppFramework Example

The Swing AppFramework Car Demo demonstrates using Metawidget with the Swing AppFramework. Metawidget can use Swing AppFramework's @Action annotation to identify actions, both amongst a domain object's properties and in external controllers, and automatically generate JButtons for them.

The application is pre-built for you in examples/swing/appframework-swing.jar or you can build it yourself by changing to the src/examples/swing/appframework folder and typing:

mvn package
[Tip]Note
This example uses annotations, so you'll need Java SE 5 or higher

This is a self-executing JAR. For convenience, it has MANIFEST.MF dependencies hard-wired into it to lib/AppFramework.jar among others, so it's best not to move it to a different folder (if you do, you'll need to manually put those JARs on your CLASSPATH).

Run the code by navigating to the examples/swing folder and typing:

java -jar appframework-swing.jar

The opening screen displays two fields to allow you to enter the make and type of a car. You can also optionally add an owner by clicking the Add an Owner button, or save the car using the Save button.

The Add an Owner button is generated by Metawidget based on the addOwner method in the Car class (which has been annotated @org.jdesktop.application.Action). The Save button is generated based on the save method in the CarApplication class (also annotated @Action). Two different Metawidgets are used in the example: one pointed at the Car class, the other at the CarApplication class.

Metawidget supports pluggable 'action styles'. The use of Swing AppFramework is configured per Inspector, as in src/examples/swing/appframework/src/main/resources/org/metawidget/example/swing/appframework/metawidget.xml from the source distribution:

<metawidgetAnnotationInspector config="org.metawidget.inspector.impl.BaseObjectInspectorConfig">
	<actionStyle>
		<swingAppFrameworkActionStyle xmlns="java:org.metawidget.inspector.impl.actionstyle.swing">
	</actionStyle>
</metawidgetAnnotationInspector>

As a further feature, after the Add an Owner button is clicked it disappears. This is acheived by using JexlInspectionResultProcessor to introduce an expression language for Swing similar to JSP's EL. The method is annotated...

@Action( name = "add" )
@UiAttribute( name = HIDDEN, value = "${this.owner != null}" )
public void addOwner() {
	mOwner = new Owner();
	fireActionEvent( "addOwner" );
}

...such that the button gets hidden when the car has an owner.

1.4.8 Scala Example

The Scala Animal Races Example demonstrates using SwingMetawidget together with Scala and MigLayout.

The application is pre-built for you in examples/swing/animalraces-swing.jar or you can build it yourself by changing to the src/examples/swing/animalraces folder of the source distribution and typing:

mvn package
[Tip]Note
This example uses annotations, so you'll need Java SE 5 or higher

This is a self-executing JAR. For convenience, it has MANIFEST.MF dependencies hard-wired into it to lib/scala-library.jar among others, so it's best not to move it to a different folder (if you do, you'll need to manually put those JARs on your CLASSPATH).

Run the code by navigating to the examples/swing folder and typing:

java -jar animalraces-swing.jar

The screen displays fields to allow you to change the name, speed and type of each animal as well buttons to start and stop the race.

Scala and MigLayout with Metawidget

Figure 1.37. Scala and MigLayout with Metawidget


Animal Races' whimsical User Interface demonstrates how Metawidget's goal of not 'owning' the UI allows multiple Metawidgets to be combined for unconventional UIs. There are three Metawidgets across the top (one for each animal in the race), and a fourth Metawidget for the buttons at the bottom.

The top three Metawidgets all use MigLayout. Because Metawidget does not hide the underlying UI framework, using MigLayout allows the Animal Races code to easily pad the Metawidget:

metawidget.setMetawidgetLayout( new MigLayout() );
metawidget.setToInspect( animal );
((MigLayout) metawidget.getLayout()).setLayoutConstraints( new LC().insets( "10" ));

The Animal Races code is written purely in Scala, located at src/examples/swing/animalraces/src/main/scala/org/metawidget/example/swing/animalraces/AnimalRaces.scala. It uses ScalaPropertyStyle to allow Metawidget to inspect Scala-based domain objects:

<metawidgetAnnotationInspector xmlns="java:org.metawidget.inspector.annotation"
		config="org.metawidget.inspector.impl.BaseObjectInspectorConfig">
		<propertyStyle>
			<scalaPropertyStyle xmlns="java:org.metawidget.inspector.impl.propertystyle.scala"/>
		</propertyStyle>			
	</metawidgetAnnotationInspector>

In addition, it uses BeanUtilsBindingProcessorConfig.PROPERTYSTYLE_SCALA to bind JComponents to Scala-based domain objects:

val metawidget = new SwingMetawidget()
metawidget.addWidgetProcessor( new BeanUtilsBindingProcessor()
			.setPropertyStyle( BeanUtilsBindingProcessorConfig.PROPERTYSTYLE_SCALA ))
metawidget.setToInspect( animal )

1.4.9 GWT Client Side Example

By default, GwtMetawidget uses server-side inspection of domain objects. This is because client-side JavaScript does not support reflections or annotations. However if you don't need reflections or annotations, and have your own way of retrieving inspection results, you can plug in your own Inspector and keep everything client-side. This example implements a TextAreaInspector that retrieves inspection results from a textarea and generates the UI.

The GWT Client Side example is pre-built for you in examples/gwt/clientside-gwt. Because everything is purely client side, there is no need for Tomcat or any other container: simply navigate to the example folder and open index.html in your Web browser:

Client-Side GwtMetawidget

Figure 1.38. Client-Side GwtMetawidget


The example shows a textarea on the left containing inspection results in inspection-result-1.0.xsd format. The result of generating this XML is shown on the right. Click the Sample #2 and Sample #3 buttons to preload different XML samples, and the Generate button to generate their UI. Alternatively, you can edit the XML by hand to add new properties and actions and click Generate.

Data binding and event binding are also implemented client side. Click the Save to save the data from the generated UI using a MapPropertyBinding (in a real application, this Map could be passed back to the server for persisting). Click the Add Tracks button to trigger an event binding.

Finally, this example showcases using third-party GWT component libraries. ExtGwtWidgetBuilder is used to render a date picker widget. For more details on ExtGWT support, see the section called “ExtGwtWidgetBuilder”.

1.4.10 GWT Hosted Mode Examples

The examples/gwt/addressbook-gwt.war (discussed in Part 2 of this tutorial) and the examples/gwt/clientside (discussed in Part 3 of this tutorial) demonstrates GWT running in GWT Web mode. Developers may prefer instead to run the examples in GWT hosted mode as in Figure 1.39.

Address Book Example running in GWT Hosted Mode

Figure 1.39. Address Book Example running in GWT Hosted Mode


Source code for all examples can be found under the src/examples folder of the examples distribution. The code is organized into standalone Maven projects so that it can be easily imported into your favourite IDE. For example, to run the GWT Address Book example in Eclipse:

  • Install m2eclipse, then choose File > Import... > Maven > Existing Maven Projects

  • Navigate to src/examples/gwt/addressbook and choose to import pom.xml

  • The project may take a while to import and download dependencies (shown under Eclipse's Console tab). Afterwards, there will be build errors related to missing artifacts (shown under Eclipse's Problems tab)

  • Right click the project and choose Run As > Maven Build... (note the ellipses). In the Edit Configuration dialog, remove /gwt/addressbook from the end of Base directory and enter Goals as:

    -pl org.metawidget.examples.gwt:addressbook-gwt -am install

    Click Run and wait for all artifacts to build. Again, this may take a while.

  • Choose Project > Update All Maven Dependencies. The build errors should disappear.

  • Install the Google Plugin for Eclipse, then right click the project and choose Properties > Google > Web Toolkit and click Use Google Web Toolkit.

  • There will be a build error related to a missing web.xml. Right click the project and choose Refresh. The build error should disappear.

  • Right click the project and choose Run As > Web Application.

  • Choose hosted.jsp (this is a simplified home page that doesn't invoke custom JSTL tags).

  • Open the Google Development Mode view tab and double-click to open the URL in your browser.

[Important]Check your Build Path
If Hosted Mode fails to start, right click the project and choose Properties > Java Build Path > Libraries. Check the build path does not include any GWT libraries outside of those in Maven Dependencies, and that the GWT version matches the one in src/examples/gwt/addressbook/pom.xml.

Once you have the samples running, you can quickly make changes and play around. For example:

  • Find the line in ContactDialog that configures a LabelLayoutDecorator (which decorates sections using Labels).

  • Change it to a TabPanelLayoutDecorator. This will decorate sections using a GWT TabPanel.

  • Right click the pom.xml and choose Run As > Maven Package (this step is only necessary because the GWT Address Book uses shared projects. Import the GWT Client Side project for an example configured to deploy immediately without needing this extra step).

  • Refresh your browser. The application will be using TabPanel, as shown in Figure 1.40.

Address Book Example using GWT TabPanel

Figure 1.40. Address Book Example using GWT TabPanel


1.4.11 Static Metawidget Example

Although Metawidget is focused on runtime UI generation, its static mode (see Section 3.4, “Static Metawidgets”) can sometimes be more appropriate. The JBoss Forge project provides a thorough, real world demonstration of static Metawidget in action. JBoss Forge uses Metawidget internally for its UI scaffolding generation.

Static Metawidget is used internally by JBoss Forge

Figure 1.41. Static Metawidget is used internally by JBoss Forge


To try using static Metawidget inside JBoss Forge:

  • Download Forge

  • Install it

  • Run it

  • Execute the following command:

    $ run-url https://raw.github.com/forge/core/master/showcase/posale.fsh

This runs a Forge script that automates the creation of a Java EE web application. Forge makes use of static Metawidget in several places, including: for the JSF components on the Create, Retrieve, Update and Delete (CRUD) screens; for the search filter criteria; for generating Java statements inside the JSF managed bean.

Alternatively, there are Forge plugins that can generate scaffolds for different environments. For example the Spring plugin uses StaticSpringMetawidget to generate Spring scaffolds, and the AeroGear plugin uses StaticHtmlMetawidget to generate mobile scaffolds. For more information on JBoss Forge and how Metawidget relates to it, see the UI scaffolding section of the Forge documentation.