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.
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”.
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.
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.
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:
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.
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.
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:
The application manages details of penguins in a colony. To begin, click the
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 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 @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.
button, or checking one of the Hobbies checkboxes, triggers an AJAX call that re-evaluates theFor more details on ICEfaces support, see the section called “IceFacesWidgetBuilder” and the section called “PanelTabSetLayoutDecorator”.
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.
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
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
button, or save the car using the button.The addOwner method in the Car class (which has been annotated @org.jdesktop.application.Action). The 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.
button is generated by Metawidget based on theMetawidget 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 JexlInspectionResultProcessor to introduce an expression language for Swing similar to JSP's EL. The method is annotated...
button is clicked it disappears. This is acheived by using@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.
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
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.
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 )
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:
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 and buttons to preload different XML samples, and the button to generate their UI. Alternatively, you can edit the XML by hand to add new properties and actions and click .
Data binding and event binding are also implemented client side. Click the MapPropertyBinding (in a real application, this Map could be passed back to the server for persisting). Click the button to trigger an event binding.
to save the data from the generated UI using aFinally, 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”.
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.
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.
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.
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.
To try using static Metawidget inside JBoss Forge:
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.