DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Latest Articles - DZone

article thumbnail
JavaScript: Wrap All Methods (functions) In A Class With An Error Handler.
Example of a way to wrap all methods in a class with an error handler. Could stand more improvement. /** @Description: Takes in an exception or string and turns it into an Error object, then appends the caller name to the message. @Returns: A new Error object or null. */ function wrapError (e, caller) { if (null === e) { return null; } var ret = ( (typeof e) === (typeof "") ) ? new Error(e) : new Error(e.message); ret.stackTrace = e.stackTrace || []; ret.stackTrace.push(caller); return ret; } /** @Description: Returns a method (function) wrapped in an error handler. Does not affect the behavior of the underlying function. Does not affec the function either, only returns the wrapped function, doesn't modify it directly. Usage: function foo() { throw new Error("bar"); }; foo = safeWrapMethod(foo, "foo"); @Param: fn The function pointer/object to wrap. @Param: name A string containing the name of fn as you wish it to be displayed in the call stack. @Return: The method/function fn wrapped in an error handler. */ function safeWrapMethod (fn, name) { try { return function () { /* Wrapper added by safeWrapMethod */ try { return fn.apply(this, arguments); } catch (e) { throw wrapError(e, name); } }; } catch (e) { throw wrapError(e, "ErrorHelpers.safeWrapMethod"); } } /** @Description: Wraps every method in an object with an error handler. Affects the instance of the object, but does not alter the underlying behavior of the methods. @Param: o The class instance (object) to wrap. @Param: name A string containing the name of the class. Method names will show as "name.methodName" in an error's stack trace. */ function safeWrapClass (o, name) { for (var m in o) { if (typeof(o[m]) === "function") { o[m] = safeWrapMethod(o[m], name + "." + m); } } }; safeWrapClass = safeWrapMethod(safeWrapClass, "ErrorHelpers.safeWrapClass"); // Example Usage function Foo() { safeWrapClass(this, "Foo"); }; Foo = safeWrapMethod(Foo, "Foo.ctor"); Foo.prototype.a = function () { throw new Error("oh noes!"); }; Foo.prototype.b = function () { this.a(); } Foo.prototype.c = function () { this.b(); } try { var f = new Foo(); f.c(); } catch (e) { var msg = e.message; if (e.stackTrace) { msg += "\r\n\r\nstackTrace: " + e.stackTrace.join("\r\n\tat "); } alert(msg); /* oh noes! stackTrace: Foo.a at Foo.b at Foo.c */ }
December 18, 2009
by Jason McDonald
· 8,383 Views
article thumbnail
OSGi Fragment Bundles Don't Have Activators. Or Do They?
Using "pseudo"-activators, fragment bundles can be more active than you think! Writing test code in an OSGi-setting requires some more work and decisions than in a plain Java-main()-applications-setting. For example, we typically don't want to put test code in the "functional" bundles themselves, as this makes the build process more complex, as we need to be able to extract the test code from the "production" release package. On the other hand, we don't want to export all bundle packages. So if we put our test code in separate bundles, we're not able to access all classes/packages that we might like to test... An often-cited approach can then be to include the test code in fragment bundles. These can be easily included/excluded in test launches or release packaging, and they use the same classloader as the host bundle, so they have access to all of the host's classes. For more info/discussion on this, check: http://rcpquickstart.com/2007/06/20/unit-testing-plug-ins-with-fragments/ http://www.modumind.com/2008/06/12/running-unit-tests-for-rcp-and-osgi-applications/ http://michaelscharf.blogspot.com/2008/04/is-osgi-enemy-of-junit-tests_17.html http://alblue.blogspot.com/2006/03/javaeclipse-running-all-tests-in.html Ok, and now what? Indeed. Once the decision to put test code in fragments is made, the next step is : how can we get these tests executed??? The problems are : fragments do not get activated, so they can not register services, start service trackers etc. It's not possible AFAIK to have the fragment initiate any kind of action on "start-up". fragment classes/resources are only visible in the host bundle, unless the host bundle exports them. But if the fragment is meant to be optional, we can not export its packages from the host. host bundles can not easily discover their registered fragment bundles. The only approach I found was to inspect the MANIFEST of all running bundles, and found out if there are some with a Fragment-Host entry that refers to the host bundle. And even there, we may need features that are only practically available in the new OSGi 4.2. See http://java.dzone.com/articles/osgi-junit-test-extender-using So how can we "discover" the presence of test cases? In the links above, all kinds of tricks with reflection are described, or using eclipse-specific things. Others ensure that their test fragments provide a "magic file" on the root etc., for which the host can search. All these approaches are based on the host bundle being aware of the optional presence of a test fragment, and checking for the presence of a class or a file on some predefined path. In this way, test cases can be found and added to test suites etc. But this implies that the host bundle is aware of the purpose of the fragment(s). Now, to make things even more complicated, we often like to run tests using Equinox Console commands. This implies that we must be able to register CommandProvider implementations as OSGi services. But fragments do not have activators, so how can they register service implementations!? Enter the TestFragmentActivator To increase testing flexibility, we don't want the host bundle to be aware whether the fragment is providing JUnit test cases, CommandProviders, or other test approaches. At the same time, we want to allow the fragment to be able to register OSGi services or perform other OSGi-magic typically done in Activators. So we propose the following approach : each test fragment must provide a BundleActivator implementation with a predefined qualified name. E.g. for a project FOO, to test backend services, the name could be com.foo.backend.service.test.TestFragmentActivator in the host bundle's Activator, we add code like : public class Activator implements BundleActivator {private static Activator defaultInstance;// a reference to the fragment's pseudo-activatorprivate BundleActivator testFragmentActivator;public void start(BundleContext context) throws Exception {defaultInstance = this;try {Class frgActClass = (Class) Class.forName("com.foo.backend.service.test.TestFragmentActivator");testFragmentActivator = frgActClass.newInstance();testFragmentActivator.start(context);} catch (ClassNotFoundException e) {// ignore, means the test fragment is not present...// it's a dirty way to find out, but don't know how to // discover fragment contribution in a better way...}public void stop(BundleContext context) throws Exception {defaultInstance = null;if(testFragmentActivator!=null) testFragmentActivator.stop(context);}public static Activator getDefault() {return defaultInstance;} and in the fragment we add the implementation, that can e.g. register a new CommandProvider : package com.foo.backend.service.test;import org.eclipse.osgi.framework.console.CommandProvider;import org.osgi.framework.BundleActivator;import org.osgi.framework.BundleContext;import org.osgi.framework.ServiceRegistration;import com.foo.backend.service.test.impl.ServiceTestCommandProvider;/** * This is a fake activator, i.e. the OSGI platform will never see or invoke it, * as we're inside a fragment. The goal is that the host bundle tries to * figure out if this kind of activator is present and if so, invoke its start() * & stop() methods from inside its own ones. * * Remark that this activator will not really start the fragment, it will remain * in the RESOLVED state as far as the OSGi platform is concerned! */public class TestFragmentActivator implements BundleActivator {private ServiceRegistration svcReg;public void start(BundleContext context) throws Exception {ServiceTestCommandProvider svcTester = new ServiceTestCommandProvider();svcReg = context.registerService(CommandProvider.class.getName(), svcTester, null);}public void stop(BundleContext context) throws Exception {svcReg.unregister();} In a similar way, we could use the fragment's pseudo activator to register JUnit testcases to some centralized test suite executor etc. Couldn't it even be a useful pattern in general for fragments, i.e. not only for test-oriented fragments?? What do you think? Erwin De Ley iSencia Belgium Voorhavenlaan 31 - 011 B-9000 Gent Belgium http://www.isencia.be/
December 18, 2009
by erwin de ley
· 23,849 Views
article thumbnail
An Introduction to the Trident Animation Library
When it comes to creating impressive, animation-rich user interfaces on the desktop, Java developers aren't quite spoilt for choice. Sure, we have JavaFX, which gives use nice interfaces to work across a series of devices. But for those of us who are using existing Swing or SWT based interfaces without the time to port over, we're beginning feel left behind. That was until I came across the Trident project, developed by Kirill Grouchnikov, earlier this year. Today I'll provide a brief introduction to Trident and it's timeline concept. What Is Trident? According to Kirill: "Trident aims to simplify the development of rich animation effects in Java based UI applications, addressing both simple and complex scenarios" Trident provides an API to add in timelines and keyframes for animating the user interface. As well as being pluggable into any UI framework, full implementations for SWT and Swing are provided. Getting Started With Trident First off you'll want to download the latest version of the library from the Kenai site. For this example I took version 1.1. All that you'll need to get Trident integrated into your application is trident.jar. I'm working with Eclipse as my development environment - you'll need to add the Trident library to the build path of your application. For this example I'm going to focus on SWT, even though you can also use Trident with Swing. Because I've created a standalone Java application, you'll need to include the SWT jar to your build path. To get the SWT jar, just go to the plugins directory of your Eclipse installation, and take a copy of the org.eclipse.swt.win32.win32.x86_.jar. You can also download all the source code including code for the sample applications as part of the Trident-all.zip file. Trident Timelines As you'd expect from an animation library, Trident is based around timelines. A great example of this is ShapesFrame located in the test.swt package (or test.swing if that's your preference). When it runs, the gradient background of the shell continuously changes from ranges of blue to green. As we're running a timeline over the user interface, you'll want to create an instance of an org.eclipse.swt.widgets.Canvas. public static class ShapesPanel extends Canvas { Now, you'll need to specify a variable that gets modified during the course of the animation. In this case we have two variables, the top and bottom color. private Color topColor; private Color bottomColor; Now that we have these parts set up we can create our timeline: // animate the gradient endpoint colors in an infinite timeline Timeline colorTimeline = new SWTRepaintTimeline(this); colorTimeline.addPropertyToInterpolate("topColor", COLOR_BLUE, COLOR_GREEN); colorTimeline.addPropertyToInterpolate("bottomColor", COLOR_GREEN, COLOR_BLUE); The timeline that's created here is a specific SWT timeline which will force the repaint. When any timeline is created, it takes an object that it is related to. In this case, we're just passing through the SWT canvas. We've already defined two variables that we will modify - topColor and bottomColor. Once you provide public setters for these variables, you can add them as properties to interpolate on your timeline. This is provided in Trident's Timeline class so that it takes a propertyName, and then two other parameters (from and to) public final void addPropertyToInterpolate(String propName, T from, T to) Every time that the timeline pulses, or wakes up, it will change the values of the properties that you have registered. At the same time that it changes these values, all listeners will be notified. Behind the scenes, as we're using an SWTRepaintTimeline, the canvas that we passed through to the constructor is automatically passed through to an SWTRepaintCallback. The onTimelinePulse method will get called for each pulse, which in turn will call a repaint. As we're gradually changing the value of the properties, during the timeline we'll see different colours for the top and bottom at each pulse. So to play through our timeline, we can simply use the following code colorTimeline.setDuration(1000); colorTimeline.playLoop(RepeatBehavior.REVERSE); If the duration of the timeline is shortened, everything will happen faster. So to make the gradient appear in a more subtle fashion, just increase the duration to about 3 seconds. Putting it all together, you can see that Trident provides a clean, straightforward API. In this example we've just seen the core concepts for Timelines: Creating a new Timeline associated with an SWT Control Adding fields to interpolate Setting the duration of the timeline and kicking it off. Next time around we'll look at some other features of Trident and see how to improve simple desktop applications using the API.
December 15, 2009
by James Sugrue
· 16,747 Views
article thumbnail
Maven Repository Manager: Nexus Vs. Artifactory
My goal is to compare Sonatype Nexus and JFrog Artifactory,the two leading open source Maven repository managers.
December 14, 2009
by Ori Dar
· 136,766 Views · 4 Likes
article thumbnail
How to Create a Swing CRUD Application on NetBeans Platform 6.8
this article shows you how to integrate a java db database into a netbeans platform application. we start by exploring a java db database, from which we create entity classes. next, we wrap the entity classes into a module, together with modules for the related jpa jars. note: these instructions are not applicable to java db only. rather, they are relevant to any relational database, such as oracle or mysql. several applications on the netbeans platform, many of which are listed here , use these databases too. java db was chosen for this article because it is easiest to get started with, since it comes with the jdk. once the above modules are part of our application, we create a new module that provides the user interface for our application. the new module gives the user a tree hierarchy showing data from the database. we then create another module that lets the user edit the data displayed by the first module. by separating the viewer from the editor in distinct modules, we will enable the user to install a different editor for the same viewer, since different editors could be created by external vendors, some commercially and some for free. it is this flexibility that the modular architecture of the netbeans platform makes possible. when we have a module for our editor, we begin adding crud functionality. first, the "r", standing for "read", is handled by the viewer described above. next, the "u" for "update" is handled, followed by the "c" for "create", and the "d" for "delete". at the end of the article, you will have learned about a range of netbeans platform features that help you in creating applications of this kind. for example, you will have learned about the undoredo.manager and the explorermanager , as well as netbeans platform swing components, such as topcomponent and beantreeview . contents setting up the application integrating the database creating entity classes from a database wrapping the entity class jar in a module creating other related modules designing the user interface setting dependencies running the prototype integrating crud functionality read update create delete the application you create in this article will look as follows: source code: http://kenai.com/projects/nbcustomermanager once you're at the stage shown above, you can simply download a netbeans module that provides office laf support ( ), add it to your application, and then when you redeploy the application, you will see this: note: it is advisable to watch the screencast series top 10 netbeans apis before beginning to work on this article. many of the concepts addressed in this article are discussed in more detail within the screencast series. setting up the application let's start by creating a new netbeans platform application. choose file > new project (ctrl+shift+n). under categories, select netbeans modules. under projects, select netbeans platform application. click next. in the name and location panel, type dbmanager in the project name field. click finish. the ide creates the dbmanager project. the project is a container for all the other modules you will create. run the application and notice that you have quite a few features out of the box already. open some of the windows, undock them, and get to know the basic components that the netbeans platform provides without you doing any work whatsoever: integrating the database in order to integrate the database, you need to create entity classes from your database and integrate those entity classes, together with their related jars, into modules that are part of your netbeans platform application. creating the entity classes in this section, you generate entity classes from a selected database. for purposes of this example, use the services window to connect to the sample database that is included with netbeans ide: note: alternatively, use any database you like and adapt the steps that follow to your particular use case. in the case of mysql, see connecting to a mysql database . in the ide, choose file | new project, followed by java | java class library to create a new library project named customerlibrary. in the projects window, right-click the library project and choose file | new file, followed by persistence | entity classes from database. in the wizard, select your database and the tables you need. here we choose "customer", and then "discount code" is added automatically, since there is a relationship between these two tables. specify the persistence strategy, which can be any of the available options. here, since we need to choose something, we'll choose eclipselink: specify "demo" as the name of the package where the entity classes will be generated. click finish. once you have completed this step, look at the generated code and notice that, among other things, you now have a persistence.xml file in a folder called meta-inf, as well as entity classes for each of your tables: build the java library and you will have a jar file in the library project's "dist" folder, which you can view in the files window: wrapping the entity class jar in a module in this section, you add your first module to your application! the new netbeans module will wrap the jar file you created in the previous section. right-click the dbmanager's modules node in the projects window and choose add new library. select the jar you created in the previous subsection and complete the wizard, specifying any values you like. let's assume the application is for dealing with customers at shop.org, in which case a unique identifier "org.shop.model" is appropriate for the code name base: you now have your first custom module in your new application, wrapping the jar containing the entity classes and the persistence.xml file: creating other related modules in this section, you create two new modules, wrapping the eclipselink jars, as well as the database connector jar. do the same as you did when creating the library wrapper for the entity class jar, but this time for the eclipselink jars, which are in the "customerlibrary" java library that you created earlier: note: in the library wrapper module wizard, you can use ctrl-click to select multiple jars. next, create yet another library wrapper module, this time for the java db client jar, which is available in your jdk distribution, at db/lib/derbyclient.jar. designing the user interface in this section, you create a simple prototype user interface, providing a window that uses a jtextarea to display data retrieved from the database. right-click the dbmanager's modules node in the projects window and choose add new. create a new module named customerviewer, with the code name base org.shop.ui. in the projects window, right-click the new module and choose new | window component. specify that it should be created in the editor position and that it should open when the application starts. set customer as the window's class name prefix. use the palette (ctrl-shift-8) to drag and drop a jtextarea on the new window: add this to the end of the topcomponent constructor: entitymanager entitymanager = persistence.createentitymanagerfactory("customerlibrarypu").createentitymanager(); query query = entitymanager.createquery("select c from customer c"); list resultlist = query.getresultlist(); for (customer c : resultlist) { jtextarea1.append(c.getname() + " (" + c.getcity() + ")" + "\n"); } note: since you have not set dependencies on the modules that provide the customer object and the persistence jars, the statements above will be marked with red error underlines. these will be fixed in the section that follows. above, you can see references to a persistence unit named "customerlibrarypu", which is the name set in the persistence.xml file. in addition,there is a reference to one of the entity classes, called customer, which is in the entity classes module. adapt these bits to your needs, if they are different to the above. setting dependencies in this section, you enable some of the modules to use code from some of the other modules. you do this very explicitly by setting intentional contracts between related modules, i.e., as opposed to the accidental and chaotic reuse of code that tends to happen when you do not have a strict modular architecture such as that provided by the netbeans platform. the entity classes module needs to have dependencies on the derby client module as well as on the eclipselink module. right-click the customerlibrary module, choose properties, and use the libraries tab to set dependencies on the two modules that the customerlibrary module needs. the customerviewer module needs a dependency on the eclipselink module as well as on the entity classes module. right-click the customerviewer module, choose properties, and use the libraries tab to set dependencies on the two modules that the customerviewer module needs. open the customertopcomponent in the source view, right-click in the editor, and choose "fix imports". the ide is now able to add the required import statements, because the modules that provide the required classes are now available to the customertopcomponent. you now have set contracts between the modules in your application, giving you control over the dependencies between distinct pieces of code. running the prototype in this section, you run the application so that you can see that you're correctly accessing your database. start your database server. run the application. you should see this: you now have a simple prototype, consisting of a netbeans platform application that displays data from your database, which you will extend in the next section. integrating crud functionality in order to create crud functionality that integrates smoothly with the netbeans platform, some very specific netbeans platform coding patterns need to be implemented. the sections that follow describe these patterns in detail. read in this section, you change the jtextarea, introduced in the previous section, for a netbeans platform explorer view. netbeans platform explorer views are swing components that integrate better with the netbeans platform than standard swing components do. among other things, they support the notion of a context, which enables them to be context sensitive. representing your data, you will have a generic hierarchical model provided by a netbeans platform node class, which can be displayed by any of the netbeans platform explorer views. this section ends with an explanation of how to synchronize your explorer view with the netbeans platform properties window. in your topcomponent, delete the jtextarea in the design view and comment out its related code in the source view: entitymanager entitymanager = persistence.createentitymanagerfactory("customerlibrarypu").createentitymanager(); query query = entitymanager.createquery("select c from customer c"); list resultlist = query.getresultlist(); //for (customer c : resultlist) { // jtextarea1.append(c.getname() + " (" + c.getcity() + ")" + "\n"); //} right-click the customerviewer module, choose properties, and use the libraries tab to set dependencies on the nodes api and the explorer & property sheet api. next, change the class signature to implement explorermanager.provider: final class customertopcomponent extends topcomponent implements explorermanager.provider you will need to override getexplorermanager() @override public explorermanager getexplorermanager() { return em; } at the top of the class, declare and initialize the explorermanager: private static explorermanager em = new explorermanager(); note: watch top 10 netbeans apis for details on the above code, especially the screencast dealing with the nodes api and the explorer & property sheet api. switch to the topcomponent design view, right-click in the palette, choose palette manager | add from jar. then browse to the org-openide-explorer.jar, which is in platform11/modules folder, within the netbeans ide installation directory. choose the beantreeview and complete the wizard. you should now see beantreeview in the palette. drag it from the palette and drop it on the window. create a factory class that will create a new beannode for each customer in your database: import demo.customer; import java.beans.introspectionexception; import java.util.list; import org.openide.nodes.beannode; import org.openide.nodes.childfactory; import org.openide.nodes.node; import org.openide.util.exceptions; public class customerchildfactory extends childfactory { private list resultlist; public customerchildfactory(list resultlist) { this.resultlist = resultlist; } @override protected boolean createkeys(list list) { for (customer customer : resultlist) { list.add(customer); } return true; } @override protected node createnodeforkey(customer c) { try { return new beannode(c); } catch (introspectionexception ex) { exceptions.printstacktrace(ex); return null; } } } back in the customertopcomponent, use the explorermanager to pass the result list from the jpa query in to the node: entitymanager entitymanager = persistence.createentitymanagerfactory("customerlibrarypu").createentitymanager(); query query = entitymanager.createquery("select c from customer c"); list resultlist = query.getresultlist(); em.setrootcontext(new abstractnode(children.create(new customerchildfactory(resultlist), true))); //for (customer c : resultlist) { // jtextarea1.append(c.getname() + " (" + c.getcity() + ")" + "\n"); //} run the application. once the application is running, open the properties window. notice that even though the data is available, displayed in a beantreeview, the beantreeview is not synchronized with the properties window, which is available via window | properties. in other words, nothing is displayed in the properties window when you move up and down the tree hierarchy. synchronize the properties window with the beantreeview by adding the following to the constructor in the topcomponent: associatelookup(explorerutils.createlookup(em, getactionmap())); here we add the topcomponent's actionmap and explorermanager to the lookup of the topcomponent. run the application again and notice that the properties window is now synchronized with the explorer view: now you are able to view your data in a tree hierarchy, as you would be able to do with a jtree. however, you're also able to swap in a different explorer view without needing to change the model at all because the explorermanager mediates between the model and the view. finally, you are now also able to synchronize the view with the properties window. update in this section, you first create an editor. the editor will be provided by a new netbeans module. so, you will first create a new module. then, within that new module, you will create a new topcomponent, containing two jtextfields, for each of the columns you want to let the user edit. you will need to let the viewer module communicate with the editor module. whenever a new node is selected in the viewer module, you will add the current customer object to the lookup. in the editor module, you will listen to the lookup for the introduction of customer objects. whenever a new customer object is introduced into the lookup, you will update the jtextfields in the editor. next, you will synchronize your jtextfields with the netbeans platform's undo, redo, and save functionality. in other words, when the user makes changes to a jtextfield, you want the netbeans platform's existing functionality to become available so that, instead of needing to create new functionality, you'll simply be able to hook into the netbeans platform's support. to this end, you will need to use the undoredomanager, together with the savecookie. create a new module, named customereditor, with org.shop.editor as its code name base. right-click the customereditor module and choose new | window component. make sure to specify that the window should appear in the editor position and that it should open when the application starts. in the final panel of the wizard, set "editor" as the class name prefix. use the palette (ctrl-shift-8) to add two jlabels and two jtextfields to the new window. set the texts of the labels to "name" and "city" and set the variable names of the two jtextfields to jtextfield1 and jtextfield2. in the gui builder, the window should now look something like this: go back to the customerviewer module and change its layer.xml file to specify that the customertopcomponent window will appear in the explorer mode. note: right-click the application project and choose "clean", after changing the layer.xml file. why? because whenever you run the application and close it down, the window positions are stored in the user directory. therefore, if the customerviewer was initially displayed in the editor mode, it will remain in the editor mode, until you do a "clean", thus resetting the user directory (i.e., thus deleting the user directory) and enabling the customerviewer to be displayed in the position currently set in the layer.xml file. also check that the beantreeview in the customerviewer will stretch horizontally and vertically when the user resizes the application. check this by opening the window, selecting the beantreeview, and then clicking the arrow buttons in the toolbar of the gui builder. run the application and make sure that you see the following when the application starts up: now we can start adding some code. firstly, we need to show the currently selected customer object in the editor: start by tweaking the customerviewer module so that the current customer object is added to the viewer window's lookup whenever a new node is selected. do this by creating an abstractnode, instead of a beannode, in the customerchildfactory class. that enables you to add the current customer object to the lookup of the node, as follows (note the "lookups.singleton(c)" below): @override protected node createnodeforkey(customer c) { node node = new abstractnode(children.leaf, lookups.singleton(c)); node.setdisplayname(c.getname()); node.setshortdescription(c.getcity()); return node; // try { // return new beannode(c); // } catch (introspectionexception ex) { // exceptions.printstacktrace(ex); // return null; // } } now, whenever a new node is created, which happens when the user selects a new customer in the viewer, a new customer object is added to the lookup of the node. let's now change the editor module in such a way that its window will end up listening for customer objects being added to the lookup. first, set a dependency in the editor module on the module that provides the entity class, as well as the module that provides the persistence jars. next, change the editortopcomponent class signature to implement lookuplistener: public final class editortopcomponent extends topcomponent implements lookuplistener override the resultchanged so that the jtextfields are updated whenever a new customer object is introduced into the lookup: @override public void resultchanged(lookupevent lookupevent) { lookup.result r = (lookup.result) lookupevent.getsource(); collection coll = r.allinstances(); if (!coll.isempty()) { for (customer cust : coll) { jtextfield1.settext(cust.getname()); jtextfield2.settext(cust.getcity()); } } else { jtextfield1.settext("[no name]"); jtextfield2.settext("[no city]"); } } now that the lookuplistener is defined, we need to add it to something. here, we add it to the lookup.result obtained from the global context. the global context proxies the context of the selected node. for example, if "ford motor co" is selected in the tree hierarchy, the customer object for "ford motor co" is added to the lookup of the node which, because it is the currently selected node, means that the customer object for "ford motor co" is now available in the global context. that is what is then passed to the resultchanged, causing the text fields to be populated. all of the above starts happening, i.e., the lookuplistener becomes active, whenever the editor window is opened, as you can see below: @override public void componentopened() { result = utilities.actionsglobalcontext().lookupresult(customer.class); result.addlookuplistener(this); resultchanged(new lookupevent(result)); } @override public void componentclosed() { result.removelookuplistener(this); result = null; } since the editor window is opened when the application starts, the lookuplistener is available at the time that the application starts up. finally, declare the result variable at the top of the class, like this: private lookup.result result = null; run the application again and notice that the editor window is updated whenever you select a new node: however, notice what happens when you switch the focus to the editor window: because the node is no longer current, the customer object is no longer in the global context. this is the case because, as pointed out above, the global context proxies the lookup of the current node. therefore, in this case, we cannot use the global context. instead, we will use the local lookup provided by the customer window. rewrite this line: result = utilities.actionsglobalcontext().lookupresult(customer.class); to this: result = windowmanager.getdefault().findtopcomponent("customertopcomponent").getlookup().lookupresult(customer.class); the string "customertopcomponent" is the id of the customertopcomponent, which is a string constant that you can find in the source code of the customertopcomponent. one drawback of the approach above is that now our editortopcomponent only works if it can find a topcomponent with the id "customertopcomponent". either this needs to be explicitly documented, so that developers of alternative editors can know that they need to identify the viewer topcomponent this way, or you need to rewrite the selection model, as described here by tim boudreau. if you take one of the above approaches, you will find that the context is not lost when you switch the focus to the editortopcomponent, as shown below: note: since you are now using abstractnode, instead of beannode, no properties are shown in the properties window. you need to provide these yourself, as described in the nodes api tutorial . secondly, let's work on the undo/redo functionality. what we'd like to have happen is that whenever the user makes a change to one of the jtextfields, the "undo" button and the "redo" button, as well as the related menu items in the edit menu, become enabled. to that end, the netbeans platform makes the undoredo.manager available. declare and instantiate a new undoredomanager at the top of the editortopcomponent: private undoredo.manager manager = new undoredo.manager(); next, override the getundoredo() method in the editortopcomponent: @override public undoredo getundoredo() { return manager; } in the constructor of the editortopcomponent, add a keylistener to the jtextfields and, within the related methods that you need to implement, add the undoredolisteners: jtextfield1.getdocument().addundoableeditlistener(manager); jtextfield2.getdocument().addundoableeditlistener(manager); run the application and show the undo and redo functionality in action, the buttons as well as the menu items. the functionality works exactly as you would expect. you might want to change the keylistener so that not all keys cause the undo/redo functionality to be enabled. for example, when enter is pressed, you probably do not want the undo/redo functionality to become available. therefore, tweak the code above to suit your business requirements. thirdly, we need to integrate with the netbeans platform's save functionality: by default, the "save all" button is available in the netbeans platform toolbar. in our current scenario, we do not want to save "all", because "all" refers to a number of different documents. in our case, we only have one "document", which is the editor that we are reusing for all the nodes in the tree hirerarchy. remove the "save all" button and add the "save" button instead, by adding the following to the layer file of the customereditor module: when you now run the application, you will see a different icon in the toolbar. instead of the "save all" button, you now have the "save" button available. set dependencies on the dialogs api and the nodes api. in the editortopcompontn constructor, add a call to fire a method (which will be defined in the next step) whenever a change is detected: public editortopcomponent() { ... ... ... jtextfield1.getdocument().adddocumentlistener(new documentlistener() { public void insertupdate(documentevent arg0) { fire(true); } public void removeupdate(documentevent arg0) { fire(true); } public void changedupdate(documentevent arg0) { fire(true); } }); jtextfield2.getdocument().adddocumentlistener(new documentlistener() { public void insertupdate(documentevent arg0) { fire(true); } public void removeupdate(documentevent arg0) { fire(true); } public void changedupdate(documentevent arg0) { fire(true); } }); //create a new instance of our savecookie implementation: impl = new savecookieimpl(); //create a new instance of our dynamic object: content = new instancecontent(); //add the dynamic object to the topcomponent lookup: associatelookup(new abstractlookup(content)); } ... ... ... here are the two methods referred to above. first, the method that is fired whenever a change is detected. an implementation of the savecookie from the nodes api is added to the instancecontent whenever a change is detected: public void fire(boolean modified) { if (modified) { //if the text is modified, //we add savecookie impl to lookup: content.add(impl); } else { //otherwise, we remove the savecookie impl from the lookup: content.remove(impl); } } private class savecookieimpl implements savecookie { @override public void save() throws ioexception { confirmation message = new notifydescriptor.confirmation("do you want to save \"" + jtextfield1.gettext() + " (" + jtextfield2.gettext() + ")\"?", notifydescriptor.ok_cancel_option, notifydescriptor.question_message); object result = dialogdisplayer.getdefault().notify(message); //when user clicks "yes", indicating they really want to save, //we need to disable the save action, //so that it will only be usable when the next change is made //to the jtextarea: if (notifydescriptor.yes_option.equals(result)) { fire(false); //implement your save functionality here. } } } run the application and notice the enablement/disablement of the save button: note: right now, nothing happens when you click ok in the dialog above. in the next step, we add some jpa code for handling persistence of our changes. next, we add jpa code for persisting our change. do so by replacing the comment "//implement your save functionality here." the comment should be replaced by all of the following: entitymanager entitymanager = persistence.createentitymanagerfactory("customerlibrarypu").createentitymanager(); entitymanager.gettransaction().begin(); customer c = entitymanager.find(customer.class, customer.getcustomerid()); c.setname(jtextfield1.gettext()); c.setcity(jtextfield2.gettext()); entitymanager.gettransaction().commit(); note: the "customer" in customer.getcustomerid() is currently undefined. add the line "customer = cust;" in the resultchanged (as shown below), after declaring customer customer; at the top of the class, so that the current customer object sets the customer, which is then used in the persistence code above to obtain the id of the current customer object. @override public void resultchanged(lookupevent lookupevent) { lookup.result r = (lookup.result) lookupevent.getsource(); collection c = r.allinstances(); if (!c.isempty()) { for (customer customer : c) { customer = cust; jtextfield1.settext(customer.getname()); jtextfield2.settext(customer.getcity()); } } else { jtextfield1.settext("[no name]"); jtextfield2.settext("[no city]"); } } run the application and change some data. currently, we have no "refresh" functionality (that will be added in the next step) so, to see the changed data, restart the application. here, for example, the tree hierarchy shows the persisted customer name for "toyota motor co": fourthly, we need to add functionality for refreshing the customer viewer. you might want to add a timer which periodically refreshes the viewer. however, in this example, we will add a "refresh" menu item to the root node so that the user will be able to manually refresh the viewer. in the main package of the customerviewer module, create a new node, which will replace the abstractnode that we are currently using as the root of the children in the viewer. note that we also bind a "refresh" action to our new root node. public class customerrootnode extends abstractnode { public customerrootnode(children kids) { super(kids); setdisplayname("root"); } @override public action[] getactions(boolean context) { action[] result = new action[]{ new refreshaction()}; return result; } private final class refreshaction extends abstractaction { public refreshaction() { putvalue(action.name, "refresh"); } public void actionperformed(actionevent e) { customertopcomponent.refreshnode(); } } } add this method to the customertopcomponent, for refreshing the view: public static void refreshnode() { entitymanager entitymanager = persistence.createentitymanagerfactory("customerlibrarypu").createentitymanager(); query query = entitymanager.createquery("select c from customer c"); list resultlist = query.getresultlist(); em.setrootcontext(new customerrootnode(children.create(new customerchildfactory(resultlist), true))); } now replace the code above in the constructor of the customertopcomponent with a call to the above. as you can see, we are now using our customerrootnode instead of the abstractnode. the customerrootnode includes the "refresh" action, which calls the code above. in your save functionality, add the call to the method above so that, whenever data is saved, an automatic refresh takes place. you can take different approaches when implementing this extension to the save functionality. for example, you might want to create a new module that contains the refresh action. that module would then be shared between the viewer module and the editor module, providing functionality that is common to both. run the application again and notice that you have a new root node, with a "refresh" action: make a change to some data, save it, invoke the refresh action, and notice that the viewer is updated. you have now learned how to let the netbeans platform handle changes to the jtextfields. whenever the text changes, the netbeans platform undo and redo buttons are enabled or disabled. also, the save button is enabled and disabled correctly, letting the user save changed data back to the database. create in this section, you allow the user to create a new entry in the database. right-click the customereditor module and choose "new action". use the new action wizard to create a new "always enabled" action. the new action should be displayed anywhere in the toolbar and/or anywhere in the menu bar. in the next step of the wizard, call the action newaction. note: make sure that you have a 16x16 icon available, which the wizard forces you to select if you indicate that you want the action to be invoked from the toolbar. in the new action, let the topcomponent be opened, together with emptied jtextfields: import java.awt.event.actionevent; import java.awt.event.actionlistener; public final class newaction implements actionlistener { public void actionperformed(actionevent e) { editortopcomponent tc = editortopcomponent.getdefault(); tc.resetfields(); tc.open(); tc.requestactive(); } } note: the action implements the actionlistener class, which is bound to the application via entries in the layer file, put there by the new action wizard. imagine how easy it will be when you port your existing swing application to the netbeans platform, since you'll simply be able to use the same action classes that you used in your original application, without needing to rewrite them to conform to action classes provided by the netbeans platform! in the editortopcomponent, add the following method for resetting the jtextfields and creating a new customer object: public void resetfields() { customer = new customer(); jtextfield1.settext(""); jtextfield2.settext(""); } in the savecookie, ensure that a return of null indicates that a new entry is saved, instead of an existing entry being updated: public void save() throws ioexception { confirmation message = new notifydescriptor.confirmation("do you want to save \"" + jtextfield1.gettext() + " (" + jtextfield2.gettext() + ")\"?", notifydescriptor.ok_cancel_option, notifydescriptor.question_message); object result = dialogdisplayer.getdefault().notify(msg); //when user clicks "yes", indicating they really want to save, //we need to disable the save button and save menu item, //so that it will only be usable when the next change is made //to the text field: if (notifydescriptor.yes_option.equals(result)) { fire(false); entitymanager entitymanager = persistence.createentitymanagerfactory("customerlibrarypu").createentitymanager(); entitymanager.gettransaction().begin(); if (customer.getcustomerid() != null) { customer c = entitymanager.find(customer.class, cude.getcustomerid()); c.setname(jtextfield1.gettext()); c.setcity(jtextfield2.gettext()); entitymanager.gettransaction().commit(); } else { query query = entitymanager.createquery("select c from customer c"); list resultlist = query.getresultlist(); customer.setcustomerid(resultlist.size()+1); customer.setname(jtextfield1.gettext()); customer.setcity(jtextfield2.gettext()); //add more fields that will populate all the other columns in the table! entitymanager.persist(customer); entitymanager.gettransaction().commit(); } } } run the application again and add a new customer to the database. delete in this section, let the user delete a selected entry in the database. using the concepts and code outlined above, implement the delete action yourself. create a new action, deleteaction. decide whether you want to bind it to a customer node or whether you'd rather bind it to the toolbar, the menu bar, keyboard shortcut, or combinations of these. depending on where you want to bind it, you will need to use a different approach in your code. read the article again for help, especially by looking at how the "new" action was created, while comparing it to the "refresh" action on the root node. get the current customer object, return an 'are you sure?' dialog, and then delete the entry. for help on this point, read the article again, focusing on the part where the "save" functionality is implemented. instead of saving, you now want to delete an entry from the database. see also this concludes the article. you have learned how to create a new netbeans platform application with crud functionality for a given database. you have also seen many of the netbeans apis in action. for more information about creating and developing applications on the netbeans platform, see the following resources: netbeans platform learning trail netbeans api javadoc
December 8, 2009
by Geertjan Wielenga
· 232,085 Views
article thumbnail
Lombok Reduces Your Boilerplate Code
In this article, I show you the power of the product I stumbled upon this week: Project Lombok enables you to modify bytecode at compile code. First, I will detail what features Lombok brings you out-of-the-box. In the second part of this article, I will describe how to extend it to generate you own code. Introduction Since the dawn of JEE, complaints have been filed regarding the complexity of coding components. I consider EJB v2 a very good example of this complexity: for just a simple EJB, you have to provide the EJB class itself and a home and an interface for each access type (local and remote). This makes it complex, error-prone and more importantly gives you less time to focus on business code where the real value is. Two initiatives show the will to decrease the amount of boilerplate code needed when coding: the Spring Framework’s motto is to decrease JEE complexity. The boilerplate code is written once in the Spring framework and only used by projects. EJB v3 has taken into account the lessons from Spring and aim to reduce boilerplate code too, making local and remote interfaces unnecessary. Eventually, the next version of the specification will make the local and remote home optional too. The goal of Project Lombok is exactly the same as the previous initiatives but in order to do so, it uses another mechanism. Annotation processing Version 5 of the Java language introduced the concept of annotations, code meta-data that could be processed at compile time and/or runtime. Unfortunately, in JDK 5, processing annotations at compile is a 2-step process. First, you have to run the apt executable to process annotations, perhaps creating or modifying source files, then compile your sources with javac. That was not the best approach, so Java 6 removes apt and make javac able to manage annotations, streamlining the process to obtain a simpler single step computing. This is the path taken by Lombok. Project Lombok Lombok’s driving feature is to create code you need from annotations in order to reduce the amount of boilerplate code you have to write. It provides you with the following annotations that will change your code (if not your life) forever: @Getter and @Setter: create getters and setters for your fields @EqualsAndHashCode: implements equals() and hashCode() @ToString: implements toString() @Data: uses the four previous features @Cleanup: closes your stream @Synchronized: synchronize on objects @SneakyThrows: throws exceptions For example, while learning to code the OO way, you were drilled into making your fields private and into writing public accessors to access these fields: public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } Since this is a bother to write, some (if not all) IDE have a feature to generate the accessors. It has some drawbacks: You have to manually remove the accessors if you remove the field It clutters your real code with boilerplate code Corollary: it takes a real effort to check whether an accessor already exist for a field in a long class Moreover, creating accessors manually is error-prone: I once searched for hours for a bug in code developed by a fellow developer and finally found the setter was wrong. Since getter / setter is only meta-data for a field, Lombok’s stance is to treat it like such: in Java, meta-data is managed with annotations. Look at the following code: import org.lombok.Getter; import org.lombok.Setter; public class Person { @Getter @Setter private String name; } I decompiled the generated class (using JAD) and it creates exactly the same bytecode, only the source code is more concise and less error-prone. When thinking, I found 3 arguments against using Lombok: The first argument against using such a strategy is that you can’t create a protected accessor like that. You’re wrong, Lombok is configurable: import lombok.AccessLevel; import org.lombok.Getter; import org.lombok.Setter; public class Person { @Getter @Setter(AccessLevel.PROTECTED) private String name; } And its true for all the provided annotations! Just look at them. The second argument against using Lombok is that you don’t know what it does behind the scene. It’s true, but the same could be said for AOP or CGLIB or whatever framework you’re using. The last argument and IMHO the only one valid enough is that it renders debugging more complex: but so is the use of Java dynamic proxies that Spring uses throughout its code, and still many projects use them. Use and installation Using Lombok is a 3-step process: Put the JAR on the classpath Add the annotation you want to use Compile with javac There’s a catch, though. Notice the last statement and the emphasis on javac. Since most (if not all) the developers you and I know focus a little bit on productivity, chances are you’re using a IDE. I do not know about NetBeans and fellows, but my favorite IDE Eclipse does not use javac to compile but its own internal compiler. Our friends from Lombok thought about that and Lombok is able to hook into Eclipse compiling process too. In order to do so, just launch lombok.jar and follow the instructions on you screen: it will just add 2 lines to your eclipse.ini. A word of advice (since I made the mistake): if you launch Eclipse with a command that takes parameters, such as a Windows shortcut, these parameters take precedence and eclipse.ini is silently ignored. Just to let you know… Lombok extensions To my knowledge, there’s currently only a single extension of Lombok called Morbok. It lets you create your classical private static final logger with just an annotation. The advantage of this is that Morbok automatically uses the fully qualified class name as the name of the logger so no more copy paste error. The disadvantage is that if you do not use Commons Logging as you logging framework, you have to configure each @Logger annotation with the framework you want to use, there’s no overall configuration: IMHO, that’s something that could be covered in the next version (is there’s one). Architecture First things first, Lombok needs a JDK 6 to compile since annotation processing is done in Java 5 with APT. For now, Lombok hooks into the compiling process immediately after the environment has built the AST for the class. It then passes the structure thus formed to each of its referenced handlers. There’s a single handler for each annotation: HandleGetter for @Getter, HandlerSetter for @Setter and so on. Handlers are, guess what, responsible for handling annotations. Extending Lombok Extending Lombok is a 3-step process: Create the annotation. Since the annotation is used at compile-time, it can be safely be discarded afterwards so its retention policy can be left to its default value (namely RetentionPolicy.SOURCE) Create the handler. A handler is a class that directly implements lombok.javac.JavacAnnotationHandler. Why directly? Because Lombok uses the ServiceProvider service and it’s one of its limitations Reference the fully qualified class name of the handler in a file named lombok.javac.JavacAnnotationHandler under META-INF/services The real coding takes place in step 2: the interface has a single method handle(AnnotationValues annotation, com.sun.tools.javac.tree.JCTree.JCAnnotation ast, JavacNode annotationNode). Notice the 2nd parameter package? It’s denotes Sun private implementation. It has some big drawbacks: The documentation is sparse if not completely unavailable. You go into unknown territory here Since the com.sun.tools.javac is not part of the public API, it can change at a moment’s notice. You can break your code with each update Remember that previously, I talked about this being only good for Java? That’s still true. If you want this new annotation to work under Eclipse, that’s another handler to write Example As an example, I coded an embryo for a @Delegate annotation. Such an annotation on a field indicates that the declaring class should have the same public methods as the field’s class and each method’s body should be a call to its delegate’s method. public class Delegator { @Delegate private DelegateObject object; ... } public class DelegateObject { public void doSomething() { ... } } The previous code should generate the same bytecode as the following code: public class Delegator { private DelegateObject object; public void doSomething() { object.doSomething(); } ... } As yet: it does not handle generics the only handler provided is for javac it is not configurable The final implementation is left for the brave readers: original sources are here in Eclipse/Maven format. Conclusion Some improvements could quickly be made to Lombok. First, I don’t like the monolithic structure the JAR has. IMHO, it could be nicely decoupled into 3 separate JARs: the Lombok agent itself, the provided annotations and associated handlers and finally, the installer. Moreover, coding two handlers for each annotation is a lost of time. What if you need to support NetBeans too? Perhaps using the Service Provider is a mistake… Finally, depending on Sun’s internal compiler API is too big a risk. I think that if Lombok could provide a facade to this API, it could be less risky for enterprise to take this road and the bridging could be made by people who understand the API (the Lombok team) and not base developers (like myself). All in all, and despite these flaws, Lombok looks like a very promising project that could well mimic Spring’s success. That’s what I wish it anyway because it’s real sideway thinking that brings much added value: good luck for the future! To go further: Project Lombok Lombok’s Javadoc Morbok From http://blog.frankel.ch
December 7, 2009
by Nicolas Fränkel
· 21,251 Views · 1 Like
article thumbnail
JAXB Customization of xsd:dateTime
A small JAXB puzzle: how to define a custom element to serialize Date objects with the TimeZone information? Piece of cake, isn't it? Try it yourself and you will be surprised with the tricky details. A friend of mine gave me a JAXB challenge this week: his company already uses a customization of the xsd:date type in a legacy code - mapped to a proprietary type instead of the default Calendar type. Now they also need to represent Calendar objects in their application schema, so they need to model the date objects as a custom type. My first thought was about a five minutes hack, just defining an element based on the xsd:date and use the JAXB customization to map the new type to the Java Calendar type. After my five minutes I got few issues: The default customization of Calendar in JAXB doesn't serialize the Time information of a date. Ok, let's create a custom binder class and hack the way we want to write and read our data. If you use xsd:dateTime instead of a simple xsd:date, the default adapter of JAXB doesn't work anymore. Other surprise: you can't use the java.text.SimpleDateFormat to serialize Date objects because the String representation of the TimeZone provided by Java is not compatible with the XML specification. - new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ") produces 2009-12-06T15:59:34+0100 - the expected format for the Schema xsd:dateTime type is 2009-12-06T15:59:34+01:00 You got the difference? Yes, the stupid missed colon in the time zone representation makes the output of the SimpleDateFormat incompatible with the XSD Schema specification. Yes, unbelievable but you need to handle that detail programatically. You can try by yourself but instead of proving you the details I wrote down my hack solution. If you know a more elegant solution, please give me your feedback. Remember the original problem: to not use the xsd:dateTime directly since it is already in use by other customization. Also: your customization should support a date and time representation, including the time zone. Below you find a transcription of the sample project I created to illustrate the solution, to facilitate the copy paste and also to allow you to check the solution in case you don't want or you can't compile and run the project. Otherwise, just download the complete project. To compile and run the project, open a terminal and type the following line commands in the folder you unzipped the project: mvn clean compile test eclipse:eclipse The sample Maven project First step, to create the maven project and configure the JAXB plugin in the pom.xml. To create the project I used the Maven default J2SE archetype: mvn archetype:create -DgroupId=cejug.org -DartifactId=jaxb-example mvn compile eclipse:eclipse Then you can import the project in your preferred IDE and configure the JAXB plugin in the pom.xml: 4.0.0 cejug.org jaxb-example jar 1.0-SNAPSHOT jaxb-example http://maven.apache.org junit junit 3.8.1 test maven2-repository.dev.java.net Java.net Maven 2 Repository http://download.java.net/maven/2 org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.6 1.6 org.jvnet.jaxb2.maven2 maven-jaxb2-plugin generate ${basedir}/src/main/resources/schema **/*.xsd true false true yes true After that, I created the sample schema /jaxb-example/src/main/resources/schema/sample-binding.xsd: Inspired by this blog I created the custom binder org.cejug.binder.XSDateTimeCustomBinder: package org.cejug.binder; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class XSDateTimeCustomBinder { public static Date parseDateTime(String s) { DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); try { return formatter.parse(s); } catch (ParseException e) { return null; } } // crazy hack because the 'Z' formatter produces an output incompatible with the xsd:dateTime public static String printDateTime(Date dt) { DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); DateFormat tzFormatter = new SimpleDateFormat("Z"); String timezone = tzFormatter.format(dt); return formatter.format(dt) + timezone.substring(0, 3) + ":" + timezone.substring(3); } } Then I created a JUnit class with the following test method: package cejug.org; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.cejug.sample.ElementType; import org.cejug.sample.ObjectFactory; import org.xml.sax.SAXException; public class JaxbSampleTest extends TestCase { private static final String UTF_8 = "UTF-8"; private static final File TEST_FILE = new File("target/test.xml"); public JaxbSampleTest(String testName) { super(testName); } public static Test suite() { return new TestSuite(JaxbSampleTest.class); } @Override protected void setUp() throws Exception { super.setUp(); if (TEST_FILE.exists()) { if (!TEST_FILE.delete()) { fail("impossible to delete the test file, please release it and run the test again"); } } } public void testApp() { ObjectFactory xmlFactory = new ObjectFactory(); ElementType type = new ElementType(); Date calendar = GregorianCalendar.getInstance(TimeZone.getDefault()) .getTime(); type.setJdate(calendar); JAXBElement element = xmlFactory.createElement(type); try { writeXml(element, TEST_FILE); JAXBElement result = read(TEST_FILE); assertEquals(calendar.toString(), result.getValue().getJdate().toString()); } catch (Exception e) { fail(e.getMessage()); } } private void writeXml(JAXBElement sample, File file) throws JAXBException, IOException { FileWriter writer = new FileWriter(file); try { JAXBContext jc = JAXBContext.newInstance(ElementType.class .getPackage().getName(), Thread.currentThread() .getContextClassLoader()); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_ENCODING, UTF_8); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.marshal(sample, writer); } finally { writer.close(); } } @SuppressWarnings("unchecked") public JAXBElement read(File file) throws JAXBException, SAXException, IOException { InputStreamReader reader = new InputStreamReader(new FileInputStream( file)); try { JAXBContext jc = JAXBContext.newInstance(ElementType.class .getPackage().getName(), Thread.currentThread() .getContextClassLoader()); Unmarshaller unmarshaller = jc.createUnmarshaller(); SchemaFactory sf = SchemaFactory .newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema(Thread.currentThread() .getContextClassLoader().getResource( "../classes/schema/sample-binding.xsd")); unmarshaller.setSchema(schema); JAXBElement element = (JAXBElement) unmarshaller .unmarshal(reader); return element; } finally { reader.close(); } } } That's it, I hope it can save your next five minutes of hack :) From http://weblogs.java.net/blog/felipegaucho
December 7, 2009
by Felipe Gaúcho
· 40,505 Views
article thumbnail
An Introduction to Feature-Driven Development – Part 2
This is the second part of a two-part article introducing Jeff De Luca’s Feature Driven Development (FDD) process. In particular, we are looking at how FDD differs from Scrum and eXtreme Programming-inspired approaches when it comes to working with larger teams and projects. In the first part we briefly introduced the ‘just enough’ upfront activities that FDD uses to support the additional communication that inevitably is needed in a larger project/team. In the second part of the article we cover how FDD leverages the results of those upfront activities within the highly iterative, self-managing, organized-chaos that is the delivery engine room of an FDD project. The Engine Room: Delivering Frequent, Tangible Working Results Once there is an initial overall model (FDD Process #1), an initial overall features list (FDD Process #2), and an initial overall plan (FDD Process #3) in place, an FDD project is ready to start delivering the required software feature by feature. Peter Coad, the Chief Architect on the original FDD project used the phrase ‘Deliver frequent, tangible, working results’ as a mantra to impress upon people the idea of delivering real, completed, client-valued function as often as possible. Scrum and eXtreme Programming do this using fixed length iterations of a calendar month or 2-4 weeks. FDD is different. Each Chief Programmer (lead developer) runs a series of iterations, each of which is normally a matter of a few days, and never longer than two weeks. At the start of each of these iterations, each Chief Programmer selects the next few features that make sense to implement from the backlog of feature sets (activities) that were assigned to him or her in FDD Process #2. The Chief Programmer leads the development of these features through FDD processes #4 and #5, Design by Feature (DBF) and Build By Feature (BBF). Note that iterations through the DBF/BBF processes are not fixed length, and Chief Programmers do not synchronize the start and end of their iterations with each other. In addition, the DBF/BBF processes are always executed as a pair (FDD describes them as two separate processes rather than one combined process for psychological reasons). FDD Process #4: Design By Feature After selecting the features for the iteration, a Chief Programmer needs to form their feature team. Yes, feature teams are formed and disbanded for each iteration through the DBF/BBF process pair. Using the knowledge gained from the modeling process (FDD Process #1), the Chief Programmer identifies the domain classes that are likely to be involved in this iteration, and forms his or her feature team from the owners of those classes. In practice, this means: a feature team is small, typically 3 to 5 people, because features are small. By definition, a feature team comprises of all the class owners who need to modify their classes in the development of the features during that iteration. There is no need to wait for members of other teams to change code. Therefore, there are all the benefits of code ownership and a sense of collective ownership too. Class owners may find themselves a member of multiple feature teams at the same time. This does not happen as frequently as might be supposed because iterations are so short – days not weeks. When it does, it is not a big problem in practice. Chief Programmers work together to resolve any problematic conflicts and, with care, most developers can manage the demands of occasionally belonging to more than one feature team for a short time. Once formed, the Chief Programmer facilitates the collaborative analysis and design of the features for that iteration. Depending on the complexity, this may involve the team walking through the requirements in detail with a domain expert, and studying any existing relevant documents. It also involves agreeing on the interactions and other details that need to be added to the model to support the new features. The final step in the DBF part of the iteration is to review the design. For simple features, this may be a brief sanity check of the design held within the feature team. For more significant features, the Chief Programmer will typically involve other Chief Programmers or class owners so that they are aware and can comment on the impact of the proposed design. For small team projects, the object models are frequently small enough for individual or pairs of developers to create good designs while writing tests for a particular feature or user story. For larger projects, this is not necessarily the case and designs created purely by considering the tests a feature or user story must pass are more likely to be brittle and require significant refactoring. The DBF process in FDD ensures that the overall model also guides the design, helping to maintain its ‘conceptual integrity’ [Brooks]. FDD Process #5: Build By Feature The Build by Feature (BBF) part of the iteration involves the team members coding up the features, testing them at both unit level and feature level, and holding a code inspection before promoting the completed features into the project's regular build process. Testing FDD expects developers to unit test their code. It expects feature teams to test their features. FDD is not overly concerned with how this is achieved. Projects and feature teams are free to adopt the testing tools, frameworks, and level of formality and completeness that are most appropriate. FDD does not mind if tests are written before or after code. What FDD mandates, is that the feature team deliver code that has been appropriately tested and inspected. Only once the new features have passed testing and inspection is the source code allowed into the build process. Code Inspections Most people want to know why FDD mandates code inspections, especially those that have endured sitting through hours of boring, unproductive, ego-polishing/demolishing, point-scoring sessions that formed so-called code reviews, inspections or walkthroughs. The reason FDD mandates code inspections is that research has shown time and again that when done well, inspections find more defects and different kinds of defects than testing [McConnell]. Not only that but by examining the code of the more experienced, knowledgeable developers on the team and having them explain the idioms they use, less experienced developers learn better coding techniques. In addition, knowing that their code will be inspected and not be allowed in the build unless it conforms to the agreed standards encourages developers to pay more attention to conforming to those standards. One of the benefits of working in feature teams is that the whole feature team is on the hot seat during an inspection, not just one individual. This removes much of the intensity and anxiety inherent in inspecting one individuals work. The Chief Programmer decides on the level of formality of each inspection depending on the complexity and impact of the features developed in that iteration. Where the code has little or no impact outside the feature team, an inspection will usually only involve the feature team inspecting each other’s work. Where there is significant impact the Chief Programmer pulls in other Chief Programmers and developers to both verify the code and communicate the impact of the new features. eXtreme Programming acknowledges inspections as a ‘best practice' but promotes pair programming as the logical conclusion of applying this practice. Pair programming is obviously better than individual developers delivering code without any form of inspection. However, while FDD neither mandates nor forbids pair programming, a more-traditional inspection is: fresh eyes looking at the code, catching bad assumptions made by the coder/s a Chief Programmer present to ensure the techniques passed on are good. After all, developers can just as easily teach each other bad habits as well as good habits. a change of pace for developers, a chance to step away from the keyboard and mouse for a short while. With the wide availability of automated source code formatting and static analysis tools, code inspections can now be shorter, concentrating on the logic and coding idioms involved and not getting bogged down in nit-picking such as alignment of braces, etc. The Build FDD assumes some sort of regular build process. Some teams build weekly, others daily and others continuously. FDD avoids mandating any particular build regime. This enables the project team to apply the most applicable. If a continuous integration environment makes sense, then the team is free to employ the best there is. Progress Reports Agile projects like highly visible progress information. FDD projects are no exception. In fact, because larger projects frequently have higher profiles within an organization, presenting meaningful, accurate, timely project information appropriately at the different levels of leadership/management is even more important. Conventionally, FDD projects track the development of each feature through its DBF/BBF iteration against six milestones: domain walkthrough, design, design inspection, coding, testing and inspection, and promoted to build. For each feature, Chief Programmers record the actual date a milestone is reached. Tracking each feature through these six milestones enables the project to keep an eye on how much work is 'in progress'. Too many features at a particular milestone indicate a process problem. Those promoting Kanban and other Limited Work In Progress methods have formalized this idea to strictly define what is meant by 'too many' for each of their development iteration milestones/statuses. They then refuse to move an item to a new milestone/status if the limit on the number of items at that status has been reached. This forces a team to keep items moving forward through the process [Kanban]. FDD is not so formal, leaving the Chief Programmers and Development Manager to keep an eye informally on the amount of work in progress. The Big Wallchart, Burn-Down/Up Charts, Etc For general visibility of progress within a project, the team typically lists all the features in the project complete with their owning Chief Programmer, feature team members, and the dates of each milestone achieved on a suitable wall. In addition, features can be colored to show if they are started, in-progress, completed or blocked. This allows people to stand back from the wall and get a good visual feel for the overall status of the project. They can then walk up to the wall to zoom in on particular areas and activities in more detail. Recording the date each milestone is achieved enables a team to produce burn-down or burn-up charts analogous to those produced in Scrum and XP. Chief Programmers and Project Managers can determine from these if the underlying rate of feature completion is increasing, decreasing, or stable, etc. One of the best ways to achieve this is to have the Chief Programmers regularly (typically once a week) communicate progress to either the project manager or someone dedicated to the task. That person then produces whatever roll-up and burn-down charts desired. Having an administrative person, the equivalent of the Tracker role in eXtreme Programming, perform these report formatting duties frees the Chief Programmers to spend more time on making progress rather than formatting reports about it. Parking Lot Charts For reporting to senior management, the level of individual features is often too granular. Here, FDD projects typically use a graphical report format that known as the Parking Lot chart. In a Parking Lot chart, each group of ‘parking lots’ represents one of the subject areas from the features list. Each parking lot represents one of the activities within that subject area, and displays the name of that set of features, the number of features within it, and the percentage of those features that have been completed (typically both in text and using a progress bar). The parking lots are also colored to indicate whether the features in that activity have been started, completed, or have significant blockages. The FDD parking lot format has become so popular that Mike Cohn included it in his book, Agile Planning and Estimating [Cohn]. (click for larger image) Figure 1: Example Parking Lot Chart Conclusion Feature-Driven Development combines the key advantages of other popular agile approaches with model-centric techniques and other best practices that scale to much larger teams and projects. It defines three upfront activities that provide a conceptual and management framework within which a larger-than-usual agile team can add functionality to the software, feature by feature. It is also just as applicable for smaller teams tackling non-trivial problem domains where it is worth spending just a little time to sketch a map of the journey before dashing off down the agile coding highway. Even if you and your team decide not to adopt FDD as a whole, understanding why FDD is the way it is, can provide insight into scaling traditional agile approaches beyond small, largely independent teams. Finally, I would like to say thank you to Serguei Khramtchenko and Mark Lesk at Nebulon for their corrections and suggestions incorporated in this article. References [Brooks] Frederick P. Brooks, Jr., The Mythical Man-Month, Addison Wesley [Cohn] Cohn, Agile Planning and Estimating, Prentice-Hall PTR [FDD] FDD Community Site, www.featuredrivendevelopment.com/ [Kanban] The home of Kanban software development, www.limitedwipsociety.org/ [McConnell] McConnell, Code Complete, Microsoft [Nebulon] The Latest FDD Processes available from www.nebulon.com/articles/fdd/latestprocesses.html [Palmer-1] Palmer, Felsing, A Practical Guide to Feature-Driven Development, Prentice Hall PTR
December 4, 2009
by Stephen Palmer
· 25,577 Views · 1 Like
article thumbnail
jQuery, Each() and Async Gets
One of the things to keep in mind when using jQuery is that nothing is a blocking call. Sure, there is a certain sequence to when things operate. But, to be safe, you should always assume that step two will happen during step one. No where is this more evident than when retrieving content from a URL and inserting that content in your page. The temptation is to write code that looks something like this $.each(json, function(index, entry) { jQuery.get(entry['url'], function(html) { // insert the HTML here. } } The problem with this is that jQuery.get is an asynchronous call. This means that once the get has fired, the each loop will continue. This can cause all kinds of trouble for you, including having a complete iteration skipped, or if you are doing some kind of concatenation prior to inserting the HTML, having HTML for one iteration showing up in the middle of another. Not exactly what you had in mind, eh? But there is a fix. Use the ajax call instead and specify async:false to force the call to complete before allowing another call. $.each(json, function(index, entry) { jQuery.ajax({ url: directory + '/' + entry['url'] , success: function(html) { // insert the HTML here. } }, async: false }); Note too that using ajax without the async: false is the same as just using get.
December 3, 2009
by Dave Bush
· 16,280 Views
article thumbnail
A Groovy ride on Camel
Apache Camel is a routing and mediation engine which implements the Enterprise Integration Patterns. But don't let the words Enterprise Integration scare you off. Camel is designed to be really light weight and has a small footprint. It can be reused anywhere, whether in a servlet, in a Web services stack, inside a full ESB or a standalone messaging application. Camel makes it really simple to implement messaging application. So there are not many reasons why you could not use it in non-enterprise application. In fact, it is possible to use Camel as a tool, similar to the way you use scripting languages. For example, you could fire up the Camel Web Console and define a messaging application without write a single line of code. This article is a getting-started type of tutorial. As you might have guessed, I'm going to use Groovy as the programming language. And the programs in this article are intend to be ran with Groovysh, the Groovy Shell. Reasons: Groovy is concise, expressive and has less noice than Java. All programs in this article are just a couple dozen lines long and should be real easy to follow along. Using Groovysh allows the reader to interact with the application. I'm a Linux guy and am comfortable with VIM and working in command line. So bare with me. Putting the pieces together First, I'm going to write a simple program to make sure I'm able to talk to Camel in Groovy. I'm not using an IDE like Eclipse, nor creating a project, nor going to use any build tools like Maven. Any text editor will be sufficient. Save the following code to a file named CamelDemo.groovy (source download). import groovy.grape.Grape Grape.grab(group:"org.apache.camel", module:"camel-core", version:"2.0.0") class MyRouteBuilder extends org.apache.camel.builder.RouteBuilder { void configure() { from("direct://foo").to("mock://result") } } mrb = new MyRouteBuilder() ctx = new org.apache.camel.impl.DefaultCamelContext() ctx.addRoutes mrb ctx.start() p = ctx.createProducerTemplate() p.sendBody "direct:foo", "Camel Ride for beginner" e = ctx.getEndpoint("mock://result") ex = e.exchanges.first() println "INFO> ${ex}" This little program does a couple things: Imports the camel-core jar using Grape.grab() Defines a our custom RouteBuilder, which defines a simple route between a direct:foo and a mock:result enpoints. Instantiates the CamelContext, adds our custom RouteBuilder to it and starts Camel by ctx.start(). Tests the route by sending a message exchange using the producerTemplate obtained from the CamelContext Lookups the mock:result endpoint (ctx.getEndpoint("mock:result")) and dislays the first Exchange, which should contain the message we just sent. Now start the groovysh in a command window and load the program: $ groovysh groovy:000> load CamelDemo.groovy you should see a bunch of output and then the output from the script: INFO> Exchange[Message: Camel Ride for beginner] ===> null groovy:000> At this point, you can interact with the program via groovysh. For example the following shows a few things you can do. groovy:000> ctx.routes ===> [EventDrivenConsumerRoute[Endpoint[seda://foo] -> UnitOfWork(Channel[sendTo(Endpoint[mock://result])])]] groovy:000> ctx.components ===> {mock=org.apache.camel.component.mock.MockComponent@14f2bd7, seda=org.apache.camel.component.seda.SedaComponent@c759f5} groovy:000> ctx.endpoints ===> [Endpoint[seda://foo], Endpoint[mock://result]] groovy:000> ctx.endpoints[1].exchanges ===> [Exchange[Message: Camel Ride for beginner]] groovy:000> ctx.endpoints[1].exchanges[0].in.body ===> Camel Ride for beginner groovy:000> p.sendBody("seda:foo", "Camel Kicking") ===> null groovy:000> e.exchanges ===> [Exchange[Message: Camel Ride for beginner], Exchange[Message: Camel Kicking]] This is it for our first Groovy/Camel program. For the curious, you can actually modify the program and reload it without terminating and restarting groovysh. Camel Stock Quote This is a simple stock quote application. Initially, I planed to walk you thru the development steps, from adding a simple bean as a Processor to transforming it to a Multi-Channel, Multi-Data-Format service application. But after I've finished developing the program, it turns out that it is too simple to justify for such elaboration. To save your time and mine, I'm just going to show you the final version right here. Take a look at it, and if you can understand what it does, then may be you should skip the rest of this article :) Save the following code to a file named StockQuote.groovy (source download). import groovy.grape.Grape Grape.grab(group:"org.apache.camel", module:"camel-core", version:"2.0.0") Grape.grab(group:"org.apache.camel", module:"camel-jetty", version:"2.0.0") Grape.grab(group:"org.apache.camel", module:"camel-freemarker", version:"2.0.0") class QuoteServiceBean { public String usStock(String symbol) { "${symbol}: 123.50 US\$" } public String hkStock(String symbol) { "${symbol}: 90.55 HK\$" } } class MyRouteBuilder extends org.apache.camel.builder.RouteBuilder { void configure() { from("direct://quote").choice() .when(body().contains(".HK")).bean(QuoteServiceBean.class, "hkStock") .otherwise().bean(QuoteServiceBean.class, "usStock") .end().to("mock://result") from("direct://xmlquote").transform().xpath("//quote/@symbol", String.class).to("direct://quote") //curl -H "Content-Type: text/xml" http://localhost:8080/quote?symbol=IBM from('jetty:http://localhost:8080/quote').transform() .simple('').to("direct://xmlquote").choice() .when(header("Content-Type").isEqualTo("text/xml")).to("freemarker:xmlquote.ftl") .otherwise().to("freemarker:htmlquote.ftl") .end() } } ctx = new org.apache.camel.impl.DefaultCamelContext() mrb = new MyRouteBuilder() ctx.addRoutes mrb ctx.start() p = ctx.createProducerTemplate() //p.sendBody("direct:quote", "00005.HK") //p.sendBody("direct:xmlquote", "") //p.sendBody("direct:xmlquote", "") e = ctx.getEndpoint("mock://result") //e.exchanges.each { ex -> // println "INFO> in.body='${ex.in.body}'" //} OK, you are still here. It is assumed that: We have two market data providers, one for U.S. market and the other for Hong Kong market. An existing QuoteServiceBean class has been implemented as a POJO. It has two methods, usStock() and hkStock(). It is part of a legacy system, it works great, it hides the underlying details of interacting with the data providers. No one understands it and no one dares to modify it. We would like to use the existing QuoteServiceBean to provide a stock quote service that can be consume easily. i.e. Multi-Channel and Multi-Data-Format. Content Based Router and Message Translator from("direct://quote").choice() .when(body().contains(".HK")).bean(QuoteServiceBean.class, "hkStock") .otherwise().bean(QuoteServiceBean.class, "usStock") .end().to("mock://result") The first route (start at line 17) represented by the direct:quote endpoint. It routes the message according to the content of the body of the exchange, which it's assumed to contain the stock symbol. When the body of the exchange contains the string ".HK" the hkStock(String symbol) of QuoteServiceBean is called, otherwise the usStock(String symbol) of QuoteServiceBean is called. Notice that the route DSL almost reads like plain English! Let us try it out. First start groovysh, load the program and send two messages to the direct:quote endpoint: jack@localhost tmp]$ groovysh Groovy Shell (1.6.6, JVM: 1.6.0_11) groovy:000> load StockQuote.groovy .............. groovy:000> p.sendBody("direct:quote", "00001.HK") ===> null groovy:000> e.exchanges.last() ===> Exchange[Message: 00001.HK: 90.55 HK$] groovy:000> p.sendBody("direct:quote", "SUNW") ===> null groovy:000> e.exchanges.last() ===> Exchange[Message: SUNW: 123.50 US$] groovy:000> That is it, our simple content-based router successfully routes request to the corresponding processor methods. XML Quote Request, message Transform from("direct://xmlquote").transform().xpath("//quote/@symbol", String.class).to("direct://quote") This next route simply accepts requests in XML, transforms the request and chains it to direct://quote. With this, we've added the capability to accept requests in XML format! We are using XPath here to expression our transform. Check out the hosts of Expression Langauges supported by Camel. Let us try it out: groovy:000> p.sendBody("direct:xmlquote", "") ===> null groovy:000> e.exchanges.last() ===> Exchange[Message: GOOG: 123.50 US$] groovy:000> Multi-Channel, Multi-Data-Format Provisioning Grape.grab(group:"org.apache.camel", module:"camel-jetty", version:"2.0.0") Grape.grab(group:"org.apache.camel", module:"camel-freemarker", version:"2.0.0") // ........... lines removed for brevity ............. from('jetty:http://localhost:8080/quote').transform() .simple('').to("direct://xmlquote").choice() .when(header("Content-Type").isEqualTo("text/xml")).to("freemarker:xmlquote.ftl") .otherwise().to("freemarker:htmlquote.ftl") .end() Here we use the camel-jetty to expose an endpoint jetty:http://localhost:8080/quote to our quote service. Note that camel-jetty is not part of camel-core. That is why we have to grab it into our program. The HTTP request is translate into XML using simple expression. Note that the camel-jetty has kindly extracted the request parameters as well as the HTTP header and placed them on the Message header. So the request parameter symbol is access as ${header.symbol} in the expression. Next we simply chain the message exchange to the direct:xmlquote endpoint. The result from direct:xmlquote went thru another translation, which depends on the content-type of the orginating HTTP request. Here, I make use of the camel-freemarker to generate the desire output. So we need to create the two Freemarker templates: htmlquote.ftl ${body} xmlquote.ftl ${body} So let us see it in action, I'm going to use curl to make HTTP requests. Do this on another command window: [jack@localhost tmp]$ curl http://localhost:8080/quote?symbol=IBM IBM: 123.50 US$ [jack@localhost tmp]$ curl http://localhost:8080/quote?symbol=00001.HK 00001.HK: 90.55 HK$ [jack@localhost tmp]$ And to request XML content: [jack@localhost tmp]$ curl -H "Content-Type: text/xml" http://localhost:8080/quote?symbol=IBM IBM: 123.50 US$ [jack@localhost tmp]$ That's about it for our multi-channel/multi-data-format ser vice provision. Summary In this tutorial, I hoped to illustrate how Camel supports message passing paradigm style of application development. Camel provides all sort of components to help you build processing pipelines. All you need is to implement your business logic as simple POJOs and let Camel handle all the translating, routing, filtering, spliting and forwarding for you. Not shown in this tutorial is how to consume external resources and services from within a route. No sweat, it is just as easy. Camel integrates nicely with Spring as well as Guice, but works nicely on its own. It won't be in your way if you don't need DI support in your application. As they say: Keep the simple easy. Camel works nicely in a JBI environment like ServiceMix and OpenESB. Camel is OSGI-ready and tracks newly deployed bundles for Route definitions at runtime. So you can gear it all to way up to be part of an enterprise SOA infrastructure. Disclaimer, I'm not an experienced Camel user and still learning. Thank you for staying up with me.
December 3, 2009
by Jack Hung
· 26,056 Views
article thumbnail
Reload Your Plugins Without Restarting Eclipse
When you are developing Eclipse plugins, sometimes its annoying that the changes in the plugin.xml won't reflect immediately. You need to restart the target Eclipse to see the changes. This will be painful if you are playing with trial-n-error stuff like the menu urls. In this tip, I'll explain how to make Eclipse reread your plugin.xml without restarting the target. Create a plugin, launch as an Eclipse Application (you don't even need to Debug, just Run would do) Check the UI contributions of your plugin. Make the desired change in your plugin.xml. Right now, I've changed a Command's name; added a Command contribution to an existing menu; added a new view and made changes to an existing perspective In your target, open the Plug-ins Registry view and in the pull down menu, check the 'Show Advanced Operations' Right click your plugin and select Disable. Then right click again and select Enable. Since you have made changes to the current perspective by adding a view, you would be greeted with this Dialog. Say Yes. There you go. Now all the changes in the plugin.xml would reflect in the UI While this may not be applicable for all the changes you make in plugin.xml, this should cover up for most the changes From http://blog.eclipse-tips.com
December 2, 2009
by Prakash
· 13,377 Views
article thumbnail
How to Split an Application into Modules?
When you're new to modular architectures, a question that is likely to arise (sooner, rather than later) is: "How should I determine the best way to split an application into modules?" I asked NetBeans Dream Team member Tom Wheeler this question, in relation to his contribution to advice given during a training session described here. Below follows his response, which could apply to any modular system (based on OSGi bundles, NetBeans modules, or anything comparable). There's really no right answer for knowing how to split your application into multiple modules. In general, it's better to have lots of small modules instead of a few big ones. In general, I definitely prefer to have lots of little modules than a few big ones. If you're designing a new app from scratch, it's easy to achieve "smallness" in your modules and you'll have a better design (less coupling) because of it. If you're porting an existing application to the NetBeans platform, then you'll probably just have one or two big modules at first and you'll have to achieve smallness as you make things more modular over time. One rule of thumb is that you can often split the application into modules based on package boundaries. Thus, if you have the following packages: com.tomwheeler.app.gui com.tomwheeler.app.data com.tomwheeler.app.logic You might refactor this into a GUI module, a data module and a logic module. As you continue development, you might find that these could be split even further. For example, your data module might have objects representing customer data and product data, so you could create a customer data module and a product data module. Making your application modular actually makes refactoring easier because it's clear exactly what you've exposed as a public API. For any given feature, I almost always strive to separate API, implementation and client code into separate modules. This allows me to develop iteratively -- I can first concentrate on the API, then write a very basic implementation of it. I can then develop additional (or better) implementations of that API as time allows. One example might be a reporting subsystem for an application. I could create an API that defines what's needed to generate a report, but the API won't focus on details like file format. I can then create the simplest possible implementation of that API; it might create a plain text version of the report. I can later create a new module which creates a better report, perhaps in Excel or PDF format. While I could simply replace the first version, I could also easily add a little code to let the user select the desired report format. In addition to reducing coupling in your application's design, having smaller modules gives you more flexibility. When your application is modular, it's very easy to build different versions of the application with different sets of features, kind of like the "basic", "standard" and "enterprise" versions of software you sometimes see. Doing that with a monolithic application is usually pretty difficult. If you, reading this article, have experience in this area, i.e., modularization, please share your thoughts on this topic in the comments below, since doing so would be very useful to others starting on this path!
December 1, 2009
by Geertjan Wielenga
· 84,222 Views
article thumbnail
How to Combine REST Services with EJB 3.1
Want to combine REST services using EJB 3.1? Learn how in this great tutorial.
December 1, 2009
by Milan Kuchtiak
· 138,394 Views · 1 Like
article thumbnail
Data-driven tests With JUnit 4 and Excel
One nice feature in JUnit 4 is that of Parameterized Tests, which let you do data-driven testing in JUnit with a minimum of fuss. It's easy enough, and very useful, to set up basic data-driven tests by defining your test data directly in your Java class. But what if you want to get your test data from somewhere else? In this article, we look at how to obtain test data from an Excel spreadsheet. Parameterized tests allow data-driven tests in JUnit. That is, rather than having different of test cases that explore various aspects of your class's (or your application's) behavior, you define sets of input parameters and expected results, and test how your application (or, more often, one particular component) behaves. Data-driven tests are great for applications involving calculations, for testing ranges, boundary conditions and corner cases. In JUnit, a typical parameterized test might look like this: @RunWith(Parameterized.class) public class PremiumTweetsServiceTest { private int numberOfTweets; private double expectedFee; @Parameters public static Collection data() { return Arrays.asList(new Object[][] { { 0, 0.00 }, { 50, 5.00 }, { 99, 9.90 }, { 100, 10.00 }, { 101, 10.08 }, { 200, 18}, { 499, 41.92 }, { 500, 42 }, { 501, 42.05 }, { 1000, 67 }, { 10000, 517 }, }); } public PremiumTweetsServiceTest(int numberOfTweets, double expectedFee) { super(); this.numberOfTweets = numberOfTweets; this.expectedFee = expectedFee; } @Test public void shouldCalculateCorrectFee() { PremiumTweetsService premiumTweetsService = new PremiumTweetsService(); double calculatedFees = premiumTweetsService.calculateFeesDue(numberOfTweets); assertThat(calculatedFees, is(expectedFee)); } } The test class has member variables that correspond to input values (numberOfTweets) and expected results (expectedFee). The @RunWith(Parameterzed.class) annotation gets JUnit to inject your test data into instances of your test class, via the constructor. The test data is provided by a method with the @Parameters annotation. This method needs to return a collection of arrays, but beyond that you can implement it however you want. In the above example, we just create an embedded array in the Java code. However, you can also get it from other sources. To illustrate this point, I wrote a simple class that reads in an Excel spreadsheet and provides the data in it in this form: @RunWith(Parameterized.class) public class DataDrivenTestsWithSpreadsheetTest { private double a; private double b; private double aTimesB; @Parameters public static Collection spreadsheetData() throws IOException { InputStream spreadsheet = new FileInputStream("src/test/resources/aTimesB.xls"); return new SpreadsheetData(spreadsheet).getData(); } public DataDrivenTestsWithSpreadsheetTest(double a, double b, double aTimesB) { super(); this.a = a; this.b = b; this.aTimesB = aTimesB; } @Test public void shouldCalculateATimesB() { double calculatedValue = a * b; assertThat(calculatedValue, is(aTimesB)); } } The Excel spreadsheet contains multiplication tables in three columns: The SpreadsheetData class uses the Apache POI project to load data from an Excel spreadsheet and transform it into a list of Object arrays compatible with the @Parameters annotation. I've placed the source code, complete with unit-test examples on BitBucket. For the curious, the SpreadsheetData class is shown here: public class SpreadsheetData { private transient Collection data = null; public SpreadsheetData(final InputStream excelInputStream) throws IOException { this.data = loadFromSpreadsheet(excelInputStream); } public Collection getData() { return data; } private Collection loadFromSpreadsheet(final InputStream excelFile) throws IOException { HSSFWorkbook workbook = new HSSFWorkbook(excelFile); data = new ArrayList(); Sheet sheet = workbook.getSheetAt(0); int numberOfColumns = countNonEmptyColumns(sheet); List rows = new ArrayList(); List rowData = new ArrayList(); for (Row row : sheet) { if (isEmpty(row)) { break; } else { rowData.clear(); for (int column = 0; column < numberOfColumns; column++) { Cell cell = row.getCell(column); rowData.add(objectFrom(workbook, cell)); } rows.add(rowData.toArray()); } } return rows; } private boolean isEmpty(final Row row) { Cell firstCell = row.getCell(0); boolean rowIsEmpty = (firstCell == null) || (firstCell.getCellType() == Cell.CELL_TYPE_BLANK); return rowIsEmpty; } /** * Count the number of columns, using the number of non-empty cells in the * first row. */ private int countNonEmptyColumns(final Sheet sheet) { Row firstRow = sheet.getRow(0); return firstEmptyCellPosition(firstRow); } private int firstEmptyCellPosition(final Row cells) { int columnCount = 0; for (Cell cell : cells) { if (cell.getCellType() == Cell.CELL_TYPE_BLANK) { break; } columnCount++; } return columnCount; } private Object objectFrom(final HSSFWorkbook workbook, final Cell cell) { Object cellValue = null; if (cell.getCellType() == Cell.CELL_TYPE_STRING) { cellValue = cell.getRichStringCellValue().getString(); } else if (cell.getCellType() == Cell.CELL_TYPE_NUMERIC) { cellValue = getNumericCellValue(cell); } else if (cell.getCellType() == Cell.CELL_TYPE_BOOLEAN) { cellValue = cell.getBooleanCellValue(); } else if (cell.getCellType() ==Cell.CELL_TYPE_FORMULA) { cellValue = evaluateCellFormula(workbook, cell); } return cellValue; } private Object getNumericCellValue(final Cell cell) { Object cellValue; if (DateUtil.isCellDateFormatted(cell)) { cellValue = new Date(cell.getDateCellValue().getTime()); } else { cellValue = cell.getNumericCellValue(); } return cellValue; } private Object evaluateCellFormula(final HSSFWorkbook workbook, final Cell cell) { FormulaEvaluator evaluator = workbook.getCreationHelper() .createFormulaEvaluator(); CellValue cellValue = evaluator.evaluate(cell); Object result = null; if (cellValue.getCellType() == Cell.CELL_TYPE_BOOLEAN) { result = cellValue.getBooleanValue(); } else if (cellValue.getCellType() == Cell.CELL_TYPE_NUMERIC) { result = cellValue.getNumberValue(); } else if (cellValue.getCellType() == Cell.CELL_TYPE_STRING) { result = cellValue.getStringValue(); } return result; } } Data-driven testing is a great way to test calculation-based applications more thoroughly. In a real-world application, this Excel spreadsheet could be provided by the client or the end-user with the business logic encoded within the spreadsheet. (The POI library handles numerical calculations just fine, though it seems to have a bit of trouble with calculations using dates). In this scenario, the Excel spreadsheet becomes part of your acceptance tests, and helps to define your requirements, allows effective test-driven development of the code itself, and also acts as part of your acceptance tests. From http://weblogs.java.net/blog/johnsmart
November 30, 2009
by John Ferguson Smart
· 43,599 Views · 1 Like
article thumbnail
Fill Data Into An XML Template With VTD-XML
This example shows you how to edit an XML template to fill in the data to generate an output XML file. /* This is the template */ /* Output XML file Empire Burlesque Bob Dylan USA Columbia 10.9 1985 Still Got the Blues Gary More UK Virgin Records 10.2 1990 */ import com.ximpleware.*; import java.io.*; public class editTemplate { public static void main(String[] args) throws Exception { VTDGen vg = new VTDGen(); FileOutputStream fos = new FileOutputStream("new_cd.xml"); AutoPilot ap = new AutoPilot(); ap.selectXPath("/CATALOG/CD"); if (vg.parseFile("cd_Template.xml", false)) { VTDNav vn = vg.getNav(); ap.bind(vn); if (ap.evalXPath() == -1) { System.out.println("XPath eval failed"); System.exit(0); } fillTemplate(vn, "Empire Burlesque", "Bob Dylan", "USA", "Columbia", 10.90, 1985); if (ap.evalXPath() == -1) { System.out.println("XPath eval failed"); System.exit(0); } fillTemplate(vn, "Still Got the Blues", "Gary More", "UK", "Virgin Records", 10.20, 1990); // dump out the XML fos.write(vn.getXML().getBytes()); fos.close(); } } public static void fillTemplate(VTDNav vn, String title, String artist, String country, String company, double price, int year) throws NavException { int i = -1; if (vn.toElement(VTDNav.FIRST_CHILD)) { vn.overWrite(vn.getText(), title.getBytes()); vn.toElement(VTDNav.NEXT_SIBLING); vn.overWrite(vn.getText(), artist.getBytes()); vn.toElement(VTDNav.NEXT_SIBLING); vn.overWrite(vn.getText(), country.getBytes()); vn.toElement(VTDNav.NEXT_SIBLING); vn.overWrite(vn.getText(), company.getBytes()); vn.toElement(VTDNav.NEXT_SIBLING); vn.overWrite(vn.getText(), (price + "").getBytes()); vn.toElement(VTDNav.NEXT_SIBLING); vn.overWrite(vn.getText(), (year + "").getBytes()); } vn.toElement(VTDNav.PARENT); } }
November 30, 2009
by Jimmy Zhang
· 3,567 Views
article thumbnail
An Introduction to Feature-Driven Development
Feature-Driven Development (FDD) is one of the agile processes not talked or written about very much. Often mentioned in passing in agile software development books and forums, few actually know much about it. However, if you need to apply agile to larger projects and teams, it is worthwhile taking the time to understand FDD a little more The natural habitat of Scrum and XP-inspired approaches is a small team of skilled and disciplined developers. It remains a significant challenge to scale these approaches to larger projects and larger teams. Some have been successful but many have struggled. Feature-Driven Development (FDD) invented by Jeff De Luca is different. While just as applicable for small teams, Jeff designed FDD from the ground up to work for a larger team. Larger teams present different challenges. For example, a small team of disciplined and highly skilled developers by definition is likely to succeed regardless of which agile method they use. In contrast, it is unrealistic to expect that everyone in a larger team is equally skilled and disciplined. For this and other reasons, FDD makes different choices to Scrum and XP in a number of areas. In the first part of this two-part article, we briefly introduce the ‘just enough’ upfront activities that FDD uses to support the additional communication that inevitably is needed in a larger project/team. In the second part of the article, we cover how the highly iterative delivery part of FDD differs from Scrum and XP-inspired approaches. Iteration Zero:Getting Set to Deliver Most experienced agile teams are familiar with the concept of an iteration zero, a relatively short period for a team to put in place what they need to start delivering client-valued functionality in subsequent iterations. Despite general acceptance within the agile community that some form of iteration zero is a pragmatic necessity on most projects, neither Scrum nor eXtreme Programming formally have much to say about it. In contrast, an FDD project is organized around five 'processes', of which the first three can be considered roughly the equivalent of iteration zero activities. FDD does not use the term, iteration zero. It calls these three ‘processes’ initial project-wide activities. Each of the FDD processes is described so that it can be printed, in a typical-sized font, on no more than two sides of letter-sized paper. The most recent versions of the FDD processes are available from the FDD section of the Nebulon website, but very briefly an FDD project: … starts with the creation of a domain object model in collaboration with Domain Experts. Usinginformation from the modeling activity, and from any other requirements activities that have taken place, the developers go onto create a features list. Then a rough plan is drawn up and responsibilities assigned. Now we are ready to repeatedly take small groups of features through a design and build iteration that lasts no longer than two weeks and is often much shorter, sometimes only a matter of hours...[Palmer-1] FDD Process #1: Develop an Overall Model For many who have escaped from the perils of large, upfront analysis and design phases to the freedom and discipline of Scrum and eXtreme Programming-inspired approaches, the idea of developing a domain object model at the start of a project is controversial. In FDD, however, the building of an object model is not a long, drawn-out, activity performed by an elite few using expensive CASE tools. The modelers do not format the resulting model into a large document and throw it over the wall for developers to implement. Instead, building an initial object model in FDD is an intense, highly iterative, collaborative and generally enjoyable activity involving ‘domain and development members under the guidance of an experienced object modeler in the role of Chief Architect' [Nebulon]. FDD Process #1 describes the tasks and quality checks for executing this work, and while not mandatory, the object model is typically built using Peter Coad's modeling in color technique (modeling in color needs an introductory article all of its own [Palmer-2]). The idea is for both domain and development members of the team to gain a good, shared understanding of the problem domain. It is important that everyone understands the key problem domain concepts, relationships, and interactions. In doing so, the team as a whole learn to communicate with each other and start to establish a shared vocabulary, what Eric Evans calls a Ubiquitous Language [Evans]. The object model developed at this point concentrates on breadth rather than depth; depth is added iteratively through the lifetime of the project. The model is, therefore, a living artifact. Throughout the project, the model becomes the primary vehicle around which the team discusses, challenges, and clarifies requirements. FDD Process #2: Build a Features List With the first activity being to build an object model, some may conclude FDD is a model-driven process. It is not. While the model is central to the process, an FDD project is like a Scrum or eXtreme Programming project in being requirement-driven. Small, client-valued requirements referred to as features drive the project; the model merely helps guide. Formally, FDD defines a feature as a small, client-valued function expressed in the form:
November 20, 2009
by Stephen Palmer
· 109,378 Views · 6 Likes
article thumbnail
Groovy, Sometimes You Still Need a Semicolon.
Like Javascript, semicolons are optional in Groovy except for when they aren't optional. These examples are both pretty contrived, though I found both because they're actually something that I've written, and could both be written better. That's not really the point I'm making though. When something doesn't compile when it looks like it clearly should sometimes it's hard to track down why, and it's surprising to learn that it's because you need a semicolon. Example the first: Generics at the end of a line: def list = [1,2,3] as List println list If you try to compile this in Groovy it will give you the error message: 'unexpected token: println', however this: def list = [1,2,3] as List; println list Gives the expected output. Example the second: Ambiguous Closures {-> assert GroovyClosureTest == owner.getClass() }() {-> assert GroovyClosureTest == delegate.getClass() }() I don't think you'd really ever need to do something like this, but a closure can be defined and called on a single line. Because of Groovy's special closure parameter syntax (e.g. list.each() {} being synonomous with list.each({})) the compiler thinks I'm passing the second closure into the first as an argument. Again a semicolon is needed to seperate the two lines: {-> assert GroovyClosureTest == owner.getClass() }(); {-> assert GroovyClosureTest == delegate.getClass() }() From
November 6, 2009
by Scott Leberknight
· 32,164 Views · 1 Like
article thumbnail
Fluent Navigation in JSF 2
In this article, the third in a series covering JavaServer Faces (JSF) 2.0 features contributed by Red Hat, or which Red Hat participated in extensively, you'll discover that getting around in a JSF 2 application is much simpler and requires less typing. With improved support for GET requests and bookmarkability, which the previous article covered, JSF 2 is decidely more nimble. But not at the cost of good design. JSF no longer has to encroach on your business objects by requiring action methods to return navigation outcomes, but can instead reflect on the state of the system when selecting a navigation case. This article should give you an appreciation for how intelligent the navigation system has become in JSF 2. Read the other parts in this article series: Part 1 - JSF 2: Seam's Other Avenue to Standardization Part 2 - JSF 2 GETs Bookmarkable URLs Part 3 - Part 4 - Part 5 - Three new navigation variants are going to be thrown at you in this article: implicit, conditional and preemptive. These new options are a sign that the JSF navigation system is becoming more adaptable to the real world. There's also a touch of developer convenience thrown in. Implicit navigation is particularly useful for developing application prototypes, where navigation rules just get in the way. This style of navigation interprets navigation outcomes as view IDs. As you move beyond prototyping, conditional navigation removes the coupling between the web and transactional tier because the navigation handler pulls information from your business components to select a navigation case. Preemptive navigation, which you were introduced to in the last article, can use either implicit navigation or declarative navigation rules to produce bookmarkable URLs at render time. Leveraging the navigation system to generate bookmarkable URLs allows JSF to add GET support while maintaining consistent, centralized navigation rules. Even with these new options, there's no telling what requirements your application might have for navigation. Thus, in JSF 2, you can finally query and modify the navigation cases; a new API has been introduced in JSF 2 that exposes the navigation rule set. Before we get into customizations, let's find out how these new variants make the navigation system more flexible and help prepare the user's next move. Hopefully you won't need those customizations after all. Flexible navigation choices The declarative navigation model in JSF was a move away from the explicit navigation "forward" selection by the action in Struts. Navigation transitions in JSF, which get matched based on current view ID, logical outcome and/or action expression signature, are described in the JSF descriptor (faces-config.xml) using XML-based rules. The matched transition indicates the next view to render and whether a client-side redirect should proceed rendering. Here's a typical example: /guess.xhtml #{numberGuessGame.guess} correct /gameover.xhtml While the JSF navigation model is clearer and arguably more flexible than in Struts, two fundamental problems remain. First, the action method is still required to return a navigation directive. The directive just happens to be a more "neutral" string outcome rather than an explicit type (i.e., ActionForward), but the coupling is just as tight and you loose type safety in the process, so is it really an improvement? The other issue is that you must define a navigation case to match that outcome, even in the simplest cases, which can be really tedious. So you can't make the argument that the navigation model is less obtrusive or more convenient. It's just stuck somewhere in between. To sum it up, the JSF navigation model is not flexible enough. It needs to accommodate different development styles better and it needs to be more self sufficient. On the one hand, your style or development phase may dictate waiving the declarative navigation rule abstraction. On the other hand, you may want to completely decouple your business objects from the navigation model, eradicating those arbitrary return value directives. JSF 2 gives you this broad range of options, and even let's you settle for a happy medium. The first option is provided by implicit navigation and the second conditional navigation. With implicit navigation, you can even use the current model without having to define the navigation rule right away. Let's unbox these two new alternatives, starting with implicit navigation. Implicit navigation JSF will post a form back to the current view (using the POST HTTP method) whenever the user performs an action, such a clicking a command button (hence the term "postback"). In the past, the only way to get JSF to advance to another view after the action is invoked (i.e., following the Invoke Application phase) was to define a navigation case in faces-config.xml. Navigation cases are matched based on the EL signature of the action method invoked and the method's return value converted to a string (the logical outcome). To cite an example, assume the user clicks on a button defined as follows: The preview() method on the bean named commandHandler returns a value to indicate the outcome of processing: public String preview() { // tidy, translate and/or validate comment return "success"; } These two criteria are joined in a navigation case that dictates which view is to be rendered next. /entry.xhtml #{commentHandler.preview} success /previewComment.xhtml If no navigation case can be matched, all JSF knows to do is render the current view again. So without a navigation case, there is no navigation. A quick shorthand, which is present in Seam, is to have the action method simply return the target view ID directly. In this case, you're effectively treating the logical outcome value as a view ID. This technique has been adopted in JSF 2 as implicit navigation. It's improved since Seam because you can choose to drop the view extension (e.g., .xhtml) and JSF will automatically add it back on for you when looking for a view ID. Therefore, it's no more invasive than the string outcome values you are currently returning. Implicit navigation comes into play when a navigation case cannot be matched using the existing mechanism. Here's how the logic outcome is processed in the implicit navigation case: Detect the presence of the ? character in the logical outcome If present, capture the query string parameters that follow it the ? character The special query string parameter faces-redirect=true indicates that this navigation should be issued using a client-side redirect If the logical outcome does not end with a file extension, append file extension of current view ID (e.g., .xhtml) If the logical outcome does not begin with a /, prepend the location of current view id (e.g., /, /admin/, etc.) Attempt to locate the template for the view ID If the template is found, create a virtual navigation case that targets the resolved view ID If the template is not found, skip implicit navigation Carry out the navigation case If the navigation case is not a redirect, build and render the target view in the same request If the navigation case is a redirect, build a redirect URL, appending the query string parameters captured earlier, then redirect to it Implicit navigation can be leveraged anywhere a logical outcome is interpreted. That includes: The return value of an action method The action attribute of a UICommand component (e.g., ) The outcome attribute of a UIOutcomeTarget (e.g., ) The handleNavigation() method of the NavigationHandler API Here's an example of the navigation to the preview comment view translated into implicit navigation. The return value is automatically decorated with a leading / and a trailing .xhtml. public String preview() { // tidy, translate and/or validate comment return "previewComment"; } The /previewComment.xhtml view will be rendered in the same request. If you want to redirect first, add the following flag in the query string of the return value: public String preview() { // tidy, translate and/or validate comment return "previewComment?faces-redirect=true"; } You can accomplish any navigation scenario using implicit navigation that you can today with a formal navigation case defined in faces-config.xml. Implicit navigation is designed as the fall-through case (after the explicit navigation rules are consulted). If it fails (i.e., the template cannot be located), and the JSF 2 ProjectStage is set to development, a FacesMessage is automatically generated to warn the developer of a possible programming error. Implicit navigation is great for prototyping and other rapid development scenarios. The major downside of implicit navigation is that you are further tying your business objects into the navigation model. Next we'll look conditional navigation, which provides an alternative that keeps your tiers loosely coupled. Conditional navigation Implicit navigation spotlights how invasive it is to put the onus on your business object to return a logic outcome just to make JSF navigation happy (and work). This coupling is especially problematic when you want to respond to user interface events using components in your business tier, a simplified architecture that is supported by both Seam and Java EE 6 to reduce the amount of glue code without increasing coupling. What would be more "logical" is to invert the control and have the navigation handler consult the state of the bean to determine which navigation case is appropriate. The navigation becomes contextual rather than static. That's what conditional navigation gives you. Conditional navigation introduces a condition as a new match criteria on the navigation case. It's defined in the element as a child of and expressed using an EL value expression. The value expression is evaluated each time the navigation case is considered. For any navigation case that matches, if a condition is defined, the condition must resolve to true for the navigation case to be considered a match. Here's an example of a conditional navigation case: #{registration.register} #{currentUser.registered} /account.xhtml As you can see, the condition doesn't necessarily have to reference a property on the bean that was invoked. It can be any state reachable by EL. Conditional navigation solves a secondary problem with the JSF navigation model, one of those little annoyances in JSF that was tedious to workaround. In JSF 1.2 and earlier, if your action method is a void method or returns a null value, interpreted in both cases as a null outcome, the navigation is skipped entirely. As a result, the current view is rendered again. The only workaround is to override the navigation handler implementation and change the behavior. That really throws a wrench in being able to cut the glue code between your UI and transactional tier. That changes with the introduction of conditional navigation. Since the condition provides either an alternative, or supplemental, match criteria to the logical outcome, navigation cases that have a condition are consulted even when the logical outcome is null or void. When the outcome is null, you can emulate switch statement to match a navigation case, switching on the condition criteria: #{identity.login} #{currentUser.admin} /admin/home.xhtml #{identity.login} #{currentUser.vendor} /vendor/home.xhtml #{identity.login} #{currentUser.client} /client/home.xhtml If you intend to simply match the null outcome in any case, you can use a condition that is verily true (which, admittedly, could be improved in JSF 2.1): #{identity.logout} #{true} /home.xhtml You can also use this fixed condition to provide a fall-through case. But wait, there's more! Having to itemize all the possible routes using individual navigation cases causes death by XML (a quite painful death). What if you wanted to delegate the decision to a navigation helper bean or involve a scripting language? There's good news. You can! The target view ID can be resolved from an EL value expression. Let's return to the login example and use a helper bean to route the user using one navigation case: #{identity.login} #{navigationHelper.userHomeViewId} Oh my goodness, how much nicer is that? The navigation helper can encapsulate the logic of inspecting the currentUser bean and determining the correct target view ID. In this section, we looked at two additional ways a navigation case is matched, increasing the overall flexibility of the navigation model. Implicit navigation maps logical outcomes directly to view IDs and conditional navigation reflects on contextual data to select a navigation case without imposing unnecessary coupling with the transactional tier. We're still looking at the same fundamental navigation model, though. In the next section, you'll see the navigation model used in a new role, and in a new place in the JSF life cycle, to generate bookmarkable links. Anticipating the user's next move Up to this point, the navigation handler only comes into play on a postback. Since user interface events trigger a "postback" to the current view, as mentioned earlier, the navigation handler kicks in after the Invoke Application phase to route the user to the next view. JSF 2 introduces a completely new use of the navigation handler by evaluating the navigation rules during the Render Response phase. This render-time evaluation is known as preemptive (or predetermined) navigation. Preemptive navigation The spec defines preemptive navigation as a mechanism for determining the target URL at Render Response, typically for a hyperlink component. The current view ID and specified outcome are used to determine the target view ID, which is then translated into a bookmarkable URL and used as the hyperlink's target. This process happens, of course, before the user has activated the component (i.e., click on the hyperlink). In fact, the user may never activate the component. The idea is to marry the declarative (or implicit) navigation model with the support for generating bookmarkable links. Based on what was just described, you should now understand why you declare the target view ID in an attribute named outcome on the new bookmarkable component tags (and why those components inherit from a component class named UIOutcomeTarget). You are not targeting a view ID directly, but rather a navigation outcome which may be interpreted as a view ID if the matching falls through to implicit navigation. Let's consider an example. Assume that you want to create a link to the home page of the application. You could define the link using one the new bookmarkable link component: This definition would match the following navigation case if it existed: * home /home.xhtml Of course, with implicit navigation available, this navigation case would be redundant. We could exclude it and the result would be the same. Home But if the target view ID depends on the context, such as the user's credentials, you might choose to reintroduce the navigation case to leverage conditional logic as we did earlier. In either case, the key is that the target view ID is not hard-coded in the template. As it turns out, you've already been using preemptive navigation when you explored bookmarkability in the last article. But there's a critical part of preemptive navigation that we haven't yet fully explored: the assembly of the query string. As it turns out, this topic also applies to redirect navigation rules. In a sense, preemptive navigation has the same semantics as redirect navigation rules because both produces URL that lead to a non-faces request. The only difference is that a bookmarkable URL is a deferred request, whereas a redirect happens immediately. In both cases, the payload in the query string is an essential part of the URLs identity. Building the query string As a result of the new GET support in JSF 2, there are now a plethora of ways to tack on values to the query string. Options can collide when heading into the navigation funnel. What comes out on the other side? There's a simple conflict resolution algorithm to find out. Each parameter source is given a precedence. When a conflict occurs, meaning two sources define the same parameter name, the parameter from the source with the highest precedence is used. The query string parameters are sourced using the following order of precedence, from highest to lowest: Implicit query string parameter (e.g., /blog.xhtml?id=3) View parameter (defined in the of the target view ID) Nested in UIOutcomeTarget (e.g., ) or UICommand component (e.g., ) Nested within the navigation case element in faces-config.xml Granted, this appears to be a lot of options. Don't worry, we'll walk you through the cases in which you would use each option in this article. We recommend you choose a single style of providing navigation parameters that best suits your architecture and keep the others in the back of your mind, so that when an edge case comes up, you can tap into their power. In the last article, you learned that you can use view parameters to let JSF manage the query string for you. Instead of using view parameters, you could just tack on the query string yourself when building a link to a blog entry. You could even abstract the parameter away from the view and define it in the navigation case instead, but it again it presents a challenge to tooling: permalink /entry.xhtml?id=#{blog.entryId} A nested would also work here, especially if you want to centralized your parameters. In terms of navigation, the most important point to emphasize here is that you can finally add query string parameters to a redirect URL in the navigation rules. This need likely appears in your existing applications. No longer do you have to resort to using the programmatic API to issue a redirect with a query string payload. Let's consider the case of posting a comment to an entry. This example demonstrates the case when you are submitting a form and want to redirect to a bookmarkable page which displays the result of submitting the form: #{commentHandler.post} /entry.xhtml id #{blog.entryId} Note: Don't confuse with a UIViewParameter. Think of it more as a redirect parameter (the tag should probably be called not , something to address in JSF 2.1). There are now plenty of options to pass the user along with the right information. But the spec can't cover everything. That's why you can now query the navigation rule base at runtime to do with it what you like. Peeking into the navigation cases You've now seen a number of ways in which the navigation cases themselves have become more dynamic. Regardless of how dynamic they are, the fact remains that once you ship the application off for deployment, the navigation cases that you defined in faces-config.xml are set in stone. That's no longer the case in JSF 2. A new navigation handler interface, named ConfigurableNavigationhandler, has been introduced that allows you to query and make live modifications to the registered NavigationCase objects. Not that you necessarily want to make changes in production. Having a configurable navigation rule set means that you can incorporate a custom configuration scheme such as a DSL or even a fluent, type-safe navigation model from which rules can be discovered at deployment time. In short, the navigation rule set is pluggable, and it's up to you what to plug into it. NavigationCase is the model that represents a navigation case in the JSF API. When JSF starts up, the navigation cases are read from the JSF descriptor, encapsulated into NavigationCase objects and registered with the ConfigurableNavigationHandler. You can retrieve one of the registered NavigationCase objects by the action expression signature and logical outcome under which it is registered. NavigationCase case = navigationHandler.getNavigationCase( facesContext, "#{commandBoard.post}", "success"); You can also access the complete navigation rule set as a Map>, where the keys are the values. Map> cases = navigationHandler.getNavigationCases(); You can use this map to register your own navigation cases dynamically. For example, a framework might read an alternative navigation descriptor (such as Seam's pages descriptor) and contribute additional navigation cases. With an individual NavigationCase object in hand, you can either read its properties or use it to create an action or redirect URL, perhaps to feed into your own navigation handler. There are a lot of possiblities here. The slightly awkward part is how you reference this new API (ConfigurableNavigationHandler). The default NavigationHandler implementation in a standard JSF implementation must implement this interface. But you still have to cast to it when you retrieve it from the Application object, as follows: ConfigurableNavigationHandler nh = (ConfigurableNavigationHandler) FacesContext.getCurrentInstance() .getApplication().getNavigationHandler(); Obviously, something to revisit in JSF 2.1. Once you get a handle on it, the navigation model is your oyster. You can define new ways to navigate or use it to generate bookmarkable URLs in your own style. Forging ahead The JSF navigation model had the right idea in spirit, but lacked a couple of elements that would allow it to truly realize loose coupling, it's required use slowed down prototyping, and you had no control to query or modify the navigation rule set at runtime. Your going to find that in JSF 2, the navigation system is much more flexible. You could argue that it finally accomplishes its original goals. For prototype applications, you can get navigation working without touching the faces-config.xml descriptor with implicit navigation. Just use a view ID, with or without an extension, as the logical outcome and away you go. As the application matures, you can establish a clean separation between JSF and your transactional tier by using conditional navigation to select a navigation case. You can trim the number of navigation cases by defining the target view ID as a value expression and having JSF resolve the target view ID from a navigation helper bean. If the design of your application calls for bookmarkable support, you can leverage the navigation handler in its new role to produce bookmarkable URLs at render time. In JSF 2, it's a lot easier to route the user around the application. While that may be good for some applications, other applications never advance the user beyond a single page. These single page applications transform in place using Ajax and partial page updates. The next article in this series will open your eyes to how well Ajax and JSF fit together, and what new Ajax innovations made their way into the spec.
November 2, 2009
by Dan Allen
· 139,613 Views · 2 Likes
article thumbnail
Top Open Source ESB Projects
In today's software markets, open source technologies are giving commercial products some stiff competition. Enterprise Service Busses are no exception. Don Rippert, the chief technology officer at Accenture says, "ESBs are software products that allow you to create a business process with web services running on different platforms." Rippert believes an ESB is essential for achieveing the full potential of service-oriented architecture. In general, an ESB should provide flexibility built on a basis of standards. Jos Dirksen, an author of "Open Source ESBs in Action," said in a recent interview that today's top open source ESBs were "on par with commercial alternatives." Competition drives innovation, and this page has a list of the most competitive open source ESBs on the market. Here are the the forerunners among open source ESBs (in no particular order): JBoss ESB JBoss JBoss generally has mature components in its GA releases with no vendor-lockin characteristics. Their ESB leverages JEMStechnologies like the JBoss business rules engine for content-basedrouting and messaging. Content-based routing on the JBoss ESB can use Drools or XPath. The JBoss ESB supports XSLT and the Smookstransformation engine for XML and non-XML data formats. JBoss' ESBalso runs on the JBoss application server and features a pluggable architecture for swapping out ESBsubsystems. Apache ServiceMix Apache Apache ServiceMix 4 is OSGi based and a great option for integrating with an XML standards focussed landscape. Apache ServiceMix makes it very easy to hot-deploy new integration flows. Even the pluggable integration components are hot deployable. ServiceMix uses a JBI standard which provides a lot of components like JMS, BPEL, Web service, and Camel. The inclusion of Camel is a strong point for ServiceMix along with the Spring Framework, which is also supported. FUSE ESB is another great distribution of Apache ServiceMix. OpenESB Sun(Oracle) OpenESBhas an easy learning curve due to its solid integration with theGlassFish Application Server and Sun's popular IDE, NetBeans. TheNetbeans IDE provides countless integrated functions for administrationand development. The best thing about OpenESB is its toolset. OpenESB's tools include WSDL and schema editors, a JPI manager integrated into the service manager, and Antrunning in the background. Another tool is the Composite ApplicationService Assembly (CASA) editor, which gives you a graphical overview ofintegration applications. Many Java developers will love OpenESBbecause it comes straight from the home of Java. OpenESB is also OSGi based. MuleESB MuleSoft Mule is the most used open source integration platform. MuleESB's low cost along with easy configuration, expansion, and flexibility make it very popular. Java developers will find MuleESB easy to work with because it is Java centric. There’s also a powerful set of XML schemas in MuleESB. The creation of integration flows is very straightforward. MuleESB can have fairly complex integration flows up and running in minutes. It has many connectivity, routing, and transformation options right out of the box. WSO2 ESB WSO2 Other ESB products take a relatively heavyweight approach by using the JBI specification, but the relative newcomer, WSO2, takes a lightweight approach in its ESB. It does this by focusing on Web service standards for integration. The WSO2 ESB uses Apache Synapse, a nimble Web service mediation and routing engine that focuses on providing fast XML message processing. WSO2 takes advantage of Synapse's non-blocking http://s transport implementation over the Apache HttpComponents/NIO module. This allows the WSO2 ESB to handle thousands of parallel requests using a small amount of resources and threads. You can always expect great XML support from the WSO2 ESB because well-known XML expert James Clark is a company director at WSO2.
October 29, 2009
by Mitch Pronschinske
· 241,676 Views
article thumbnail
JSF 2 GETs Bookmarkable URLs
JSR-314: JavaServer Faces (JSF) 2.0 demonstrates a strong evolution of the JSF framework driven by de facto standards that emerged out of the JSF community and participating vendor's products. This article, the second installment in covering JSF 2.0 features contributed by Red Hat, or which Red Hat participated in extensively, covers the new features that bring formalized GET support to a framework traditionally rooted in POST requests. The primary building blocks of this support are view parameters and a pair of UI components that produce bookmarkable hyperlinks. Both features incubated in Seam and, therefore, should be familiar to any Seam developer. They are also features for which the JSF community has passionately pleaded. Author's Note: Many thanks to Pete Muir, who played a pivotal role as technical editor of this series. Read the other parts in this article series: Part 1 - JSF 2: Seam's Other Avenue to Standardization Part 2 - JSF 2 GETs Bookmarkable URLs Part 3 - Part 4 - Part 5 - Every user session must start somewhere. JSF was designed with the expectation that the user always begins on a launch view. This view captures initial state and allows the user to indicate which action to invoke by triggering a UI event, such as clicking a button. For instance, to view a mortgage loan, the user might enter its id into a text box and then click the "Lookup" button. The assumption that this scenario is the norm is surprising since it overlooks that fact that the web was founded on the concept of a hyperlink. A hyperlink points to a resource (URI), which may already contain the original state and intent, such as to view a mortgage loan summary. There's no need to bother the user with a launch view in this case. While hyperlinks are most often used in web sites, they apply to web applications as well (see this blog entry for a discussion about the difference between a web site and a web application). Hyperlinks support reuse by serving as an exchange language in composite applications. One application can link to a resource in another application in lieu of having to duplicate its functionality. In fact, the request may be coming from a legacy application that isn't even web-based. In that case, you'll likely be plopping the user into the web application somewhere in the middle. As it turns out, this situation is quite common. When you visit a blog, do you start on the search screen to find an entry to read? Not likely. More times than not, you click on a link to view a specific blog entry. The point to take away from this discussion is that initial requests (referred to as non-faces requests in JSF) can be just as important as form submissions (faces requests), whether in a web site or web application. In the past, JSF has struggled to support the scenario cited above, placing much more emphasize on faces requests. JSF 2 rectifies this imbalance by introducing view parameters and hyperlink-producing UI components. View parameters allow the application to respond to a resource request by baking formal processing of request parameters into the JSF life cycle for both GET and POST requests. View parameters are not limited to consuming data. They are bi-directional. JSF 2 can propagate the data captured by view parameters when generating bookmarkable URLs, with complementary behavior for redirect URLs produced by redirect navigation cases. We'll start by examining view parameters, how they are defined and how they are worked into the JSF life cycle. You'll then discover how they work in tandem with the new hyperlink-producing components and the navigation handler to bring "bookmarkable" support to JSF. Introducing view parameters The API documentation describes a view parameter, represented by the javax.faces.component.UIViewParameter component class, as a declarative binding between a request parameter and a model property. The binding to the model property is expressed using an EL value expression (e.g., #{blog.entryId}). If the expression is omitted, the request parameter is bound instead to a request-scoped variable with the same name. Here's a simple example of a view parameter that maps the value of a request parameter named id to the JavaBean-style property named entryId on a managed bean named blog. Assuming the entryId property on the blog managed bean is of type long, a value of 9 will be assigned to the property when the following URL is requested: http://domain/blog/entry.jsf?id=9 But wait, there's more! The value of the request parameter is first converted and validated before being assigned to the model property. This behavior should sound familiar. That's because it mirrors the processing of form input bindings on a faces request. In a way, view parameters turn the query string into an alternative form submission. And like form inputs, view parameters are also processed during faces requests. The complete view parameter life cycle is covered later when we look at view parameter propagation Before going any further, it's important to point out that view parameters are only available when using the new View Declaration Language (VDL), a standardized version of Facelets. The primary reason is because the JSR-314 EG agreed that no new features should be made to support JSP since it's deprecated as a view handler in JSF 2. Perhaps you are thinking... Isn't this already possible? If you are savvy JSF developer, you're perhaps aware that it's already possible to map a request parameter value to a model property. The assignment is declared by referencing an element of the #{param} map in a element of a managed bean declaration. For instance, you could alternatively map the id request parameter to the blog managed bean in faces-config.xml as follows: blog com.acme.Blog entryId #{param['id']} The similiarities end there. View parameters go above and beyond this simple assignment by providing: View-oriented granularity (the property mapping in the managed bean definition is global to the application) Custom converters and/or validators (along with failure messages) Bi-directionality It's hard to say which feature is the most important, but bi-directionality is certainly the most unique. Since view parameters are a mapping to a JavaBean-style property, the value can be read from the property and propagated to the next request using either the query string or the UI component tree state (depending on the type of request). You are going to find out how useful this bi-directionality can be later on in the article. Suffice to say, while the property mapping in the managed bean definition works, it's pretty anemic. View parameters are far more adequate and robust in contrast. Pertaining to the topic in this article, view parameters are the key to bringing bookmarkable support to JSF. And since bookmarks link to specific views, so must view parameters. It's all in the view As you may have guessed, view parameters are view-oriented. That means they somehow need to be associated with one or more views (as opposed to being linked to a managed bean, for instance). Up to this point, however, there was no facility for associating extensible, non-rendering metadata with a JSF view. So the EG first had to find a place within the UI component tree to stick metadata like view parameters. That led to the introduction of the metadata facet of UIViewRoot. The next section will introduce this new facet and how it's used to host view parameters for a particular view, or even a set of views. Then we get into how view parameters get processed in the JSF life cycle. The view metadata facet View parameters provide information about how request parameters should be handled when a view is either requested or linked to. The view parameters are not rendered themselves. Therefore, we say that they are part of the view's metamodel and described using metadata. So the question is, "Where should this metadata live?" It turns out that a JSF view, which is represented at the root by the javax.faces.component.UIViewRoot component class, already accommodates some metadata. Currently, this metadata consists of string values to define settings such as the locale, render kit, and content type of the view, and method expressions that designate view-specific phase observers. For example: ... While values can be assigned to these metadata properties explicitly in Java code, more often they are assigned declaratively using corresponding attributes of the component tag. But neither UIViewRoot or it's component tag can accommodate complex metadata--that is, metadata which cannot be described by a single attribute. That's were the view metadata facet comes in. The view metadata facet is a reserved facet of UIViewRoot, named javax_faces_metadata, that can hold an arbitrarily complex branch of UI components that provide additional metadata for a view. Facets are special because they are ignored by a UI component tree traversal, requiring an imperative request to step into one of them. This aspect makes a facet an ideal candidate for tucking away some metadata for the view that can be accessed on demand. The view metadata facet looks like any other facet in the UI component tree. It must be declared as a direct descendant of within a view template as follows: ... ... Note: If you are using Facelets, you may not be familiar with the tag since it's optional in Facelets. When you add it to your template, it must be the outer-most component tag, but it does not have to be the root of the document. Since the view metadata facet is a built-in facet, and is expected to be heavily used, the alias tag was introduced as a shorthand for the formal facet definition shown above: ... ... We now have a place in the UI component tree to store metadata pertaining to the view. But why define the metadata in the view template? It's all about reuse and consistency. Describing view metadata with UI components There are two important benefits to defining the metadata within the view template. First, it circumvents introducing yet another XML file with its own schema that developers would have to learn. More importantly, it allows us to reuse the UI component infrastructure to define behavior, such as registering a custom converter or validator, or to extract common view parameters into an include template. Since we're using UI components to describe the view metadata, then it makes sense to treat the UIViewParameter like any other input component. In fact, it extends UIInput. That allows us to register custom converters and validators on a UIViewParameter without any special reservations. Here's an example: Note: Later in this series you'll learn that like input components, view parameters can enforce constraints defined by Bean Validation annotations (or XML), making the explicit validation tags such as this unnecessary. But there is one caveat to embedding the view metadata in the template. Without special provisions, extracting the metadata would require building the entire view (i.e., UI component tree). Not only would this be expensive and unnecessary if the intent is not to render the view, it could also have side effects. When the component tree is built, value expressions in Facelets tag handlers get evaluated, potentially altering the state of the system. To prevent these counteractions, the view metadata facet is given special treatment in the specification. Specifically, it must be possible to be extract and built it separately from the rest of the component tree. Earlier, I mentioned that view parameters are only available in Facelets, and not JSP, because of an executive decision. There's also a technical reason why view parameters rely on Facelets. Only Facelets can provide the necessary separation between template parsing and component tree construction that allows a template fragment to be processed in isolation. The result of this operation is a genuine UI component tree, represented by UIViewRoot, that contains only the view metadata facet and its children. For all intents and purposes, it's as though the view template only contained this one child element. Using the following logic, it's possible to retrieve the metadata for an arbitrary view at any point in time. This data mining will come in to play later when we talk about view parameter propagation. String viewId = "/your_view_id.xhtml" FacesContext ctx = FacesContext.getCurrentInstance(); ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler() .getViewDeclarationLanguage(ctx, viewId); ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId); UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx); UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME); At this point you could retrieve the UIViewParameter components, which are children of the facet, to perhaps access the view parameter mappings. More likely, though, you'll be looking for your own custom components so you can execute custom behavior before the view is rendered (e.g., view actions). The extraction of the view metadata is very clever because, while it only builds a partial view, it still honors Facelets compositions. That means you can put your metadata into a common template and include it. Using some creative arrangement, you can apply common metadata to a pattern of views. Here's an example: ... ... You've learned that defining a view metadata facet provides the following services for JSF: Arbitrarily complex metadata, which can reuse existing component infrastructure Metadata is kept with the view, or in a shared template, instead of in an external XML file Can be extracted and processed without any side effects (idempotent) Common metadata declarations can be shared across multiple views Now that you are well versed in the view metadata facet, it's time to work out a concrete example of view parameters in practice. We'll look at how to enforce preconditions and load data on an initial request using information from the query string. Then you'll learn how that information gets propagated as the user navigates to other views. Weaving parameters into the life cycle This article has alluded several times to the use case of loading a blog entry from a URL by passing the value of the id parameter to our managed bean on an initial request. Let's allow this scenario to play out. Here's the URL the user might request coming into the site: http://domain/blog/entry.jsf?id=9 We'll start by asking what we do with the value once it is assigned to the entryId property of the blog managed bean. One approach is to load the entry lazily as soon as it's referenced in the UI. #{blog.blogEntry.title} #{blog.blogEntry.content} Here's what the managed bean would look like to support this approach: @ManagedBean(name = "blog") public class Blog { private Long entryId; private BlogEntry blogEntry; public Long getEntryId() { return entryId; } public void setEntryId(Long entryId) { this.entryId = entryId; } public BlogEntry getBlogEntry() { if (blogEntry == null) { blogEntry = blogRepository.findEntry(entryId); } return blogEntry; } } Of course, it doesn't make any sense to display an entry without an id (and could even lead to a NullPointerException). So we should really make the id request parameter required. We'll also add a message if it is missing. ... In the case a required request parameter is missing, you can display the error message using the tag. Conversion and validation failures are recorded as global messages since there's no view element with which to associate. But these preconditions still don't stop the view from being rendered if a request parameter is missing or invalid. What we need is a way to execute an initialization method that parallels an action invocation on a postback. That would allow us to get everything sorted before the user sees a response. View initialization While view parameters provide the processing steps from retrieving the request value to updating the model, they do not furnish the action invocation and navigation steps that are part of the faces request life cyle. That means you have to fall back to lazy loading the data as the view is being rendered (i.e., encoded). You are also missing a definitive point to fine tune the UI component tree programmatically before it's encoded. Fortunately, another new feature in JSF 2, system events, makes it possible to perform a series of initialization steps before view rendering begins. Systems events notify registered listeners of interesting transition points in the JSF life cycle at a much finer-grained level than phase listeners. In particular, we are interested in the PreRenderViewEvent, which is fired immediately after the component tree is built (but not yet rendered). If the word "registered" evokes dreadful memories of XML descriptors, fear not. Observing the event we are interested in is just a matter of appending one or more elements to the view metadata facet. The tag has two required attributes, type and listener. The type attribute is the name of the event to observe derived by removing the Event suffix from the end of the event class name and decaptializing the result. We are only interested in one event, preRenderView. The listener attribute is a method binding expression pointing to either a no-arguments method or a method that accepts a SystemEvent. ... We can use this method to retrieve the blog entry before the view is rendered. public void loadEntry() { blogEntry = blogRepository.findEntry(entryId); } If the entry cannot be found, you could add conditional logic to the view to display an error message: The blog entry you requested does not exist. Ideally, it would be better not to display the view at all. You can force a navigation to occur using the NavigationHandler API. public void loadEntry() { try { blogEntry = blogRepository.findEntry(entryId); } catch (NoSuchEntryException e) { FacesContext ctx = FacesContext.getCurrentInstance(); ctx.getApplication().getNavigationHandler() .handleNavigation(ctx, "#{blog.loadEntry}", "invalid"); } } The only problem is that the listener method is going to be invoked even if the view parameter could not be successfully converted, validated and assigned to the model property. Once again, there's a JSF 2 feature to the rescue. You can use the new isValidationFailed() method on FacesContext to check whether a conversion or validation failure occurred while processing the view parameters. public void loadEntry() { FacesContext ctx = FacesContext.getCurrentInstance(); if (ctx.isValidationFailed()) { ctx.getApplication().getNavigationHandler() .handleNavigation(ctx, "#{blog.loadEntry}", "invalid"); return; } // load entry } So far we have dealt with a trivial string to long conversion. But view parameters allow you to represent more complex data, as long as you have a converter that can marshal the value from (and to) a string. Let's assume that we want to allow the user to look at blog entries that fall within a range of dates. The before and after dates can be encoded into the URL as follows: /entries.jsf?after=2007-12-31&before=2009-01-01 Those values can then be converted to Date objects using the converter tag and assigned to Date properties on a managed bean as follows: We again use a PreRenderViewEvent listener to load the data before the page is rendered, in this case filtering the collection of blog entries to be displayed. Emulating the behavior of an action-oriented framework, which the previous examples have demonstrated, is one use of the PreRenderViewEvent. Another is to act as a life cycle callback for programmatically creating or tweaking the UI component tree after it is "inflated" from the view template. Perhaps you want to build part of the tree dynamically from a data structure. Accomplishing this in JSF would require "binding" a bean property to an existing UI component, declared using an EL value expression in the binding attribute of the tag. But this approach is really ugly because you have to put the tree-appending logic in either the JavaBean property getter or setter, depending on whether the view is being created or restored. The PreRenderViewEvent offers a much more definitive and self-documentating hook. As you've seen, it's finally possible to respond to a bookmarkable URL in JSF (without pain or brittle code). But, up to this point, all we've done is take, take, take. For bookmarkable support to be complete, we need to be able to create bookmarkable URLs. That brings us to the topic of parameter propagation. Push the parameters on If view parameters were only capable of accepting data sent through the query string of the URL, even considering the built-in conversion and validation they provide, they really wouldn't be all that helpful. What makes them so compelling is that they are bi-directional, meaning they are also propagated to subsequent requests, and rather transparently. The subsequent request may be a faces request, which targets the current view, or a non-faces request to a view that has view parameters, which translates into a bookmarkable URL. A request for a bookmarkable URL can come from either a link in the page or a redirect navigation event. We'll look at how view parameters get propagated in all of these cases in this section. Saved by the component tree Let's return to the blog entry view and consider what happens if we have a comment form below the post. The comment form might be defined as follows: Notice that there is no reference to the id of the blog entry in this form. Assuming that the blog entry is not stored in session scope (or a third-party conversation), how will the handler know which entry the comment should be linked? This is where view parameter propagation blends with component tree state saving. When encoding of the view (i.e., rendering) is complete, the view parameter values are tucked away in the saved state of the UI component tree. When the component tree is restored on a postback, such as when the comment form is submitted, the saved view parameter values are applied to the model. This allows view parameters to tie in nicely with the existing design of JSF. The initial state supplied to the view parameters by the URL can be maintained as long as the user interacts with the view (e.g., triggers faces requests through user interface events). You can think of view parameters as an elegant replacement for hidden form fields in this case. If the user bookmarked the URL after posting a comment, however, the reference to the blog entry would be lost. That's because after a POST request, the browser location does not contain a query string. Here's what the user would see: http://domain/blog/entry.jsf If we are following best practices, we'll want to implement the Post/Redirect/Get pattern anyway. That gives us a opportunity to repopulate the query string of the URL. In the past, this would have required an explicit call to the redirect() method of ExternalContext inside the action method. FacesContext.getCurrentInstance().getExternalContext().redirect("/entry.jsf?id=" + blog.getEntryId()); This explicit (and intrusive) call was necessary because the navigation case did not provide any way to append parameters to the query string. Now, view parameters can take care of this for us. We can tell JSF to encode the view parameters of the target view ID into the redirect URL by enabling the include-redirect-params attribute on the element. /entry.xhtml #{commentHandler.post} #{view.viewId} We'll get into navigation more in the next article in this series. Let's talk about those regular old hyperlinks in the page. We want those to be bookmarkable as well. That means the state needs to be encoded into the URL they point to. Once again, view parameters come into play. Bookmarkable links Let's now assume we want to create a bookmarkable link (permalink) to the current blog entry. You can link directly to another JSF view using the outcome attribute of the new hyperlink-producing component tags, and . These component tags are represented by the component class javax.faces.component.UIOutcomeTarget. (The reason the attribute is named outcome and not viewId will be explained in the next article. For now, just know that the value of the outcome attribute can be a view ID). Both of these component tags support encoding the view parameters into the query string of the URL as signaled by the includeViewParams attribute. Here's how the permalink is defined: The default value of includeViewParams is false. Since it's set to true, the view parameters are read in reverse and appended to the query string of the link. Here's the HTML that this component tag generated, assuming an entry id of 9: Permalink The link is produced using the new getBookmarkableURL() method on the ViewHandler API. This method calls through to the encodeBookmarkableURL() on the ExternalContext API to have the session ID token tacked on, if necessary. These methods complement the getRedirectURL() and encodeRedirectURL() methods on ViewHandler and ExternalContext, respectively. In a servlet environment, the implementations happen to be the same, but the extra methods serve as both a statement of intent and an extension point for environments where a link URL and a redirect URL are handled differently, such as a portlet. Notice that the context path of the application (/blog) is prepended to the path, the extension is changed from the view suffix (.xhtml) to the JSF servlet mapping (.jsf) and the query string contains the name and value of the view parameter read from the model. If you had used an tag, you would have had to do all of these things manually. That's exactly why the EG felt it was necessary to introduce this component. We can do one better. If the outcome attribute is absent, the current view ID is assumed. So we can shorten the tag to this: If you want the link to appear as a button, you can use the component tag instead. However, note that JavaScript is required in this case to update the browser location when the button is clicked, as you can see from the generated HTML: Permalink View parameters come in especially handy when the number of parameters to keep track of increases. For instance, let's consider the case when a user is searching for entries using a query string in a particular category and wants to paginate through the results. In this case, we are dealing with at least three parameters: Yet the link to these search results still remains as simple as the permalink to an entry: This component tag will produce HTML similar to this: Refresh What if we want to link back to the previous page? In that case, we cannot allow the view parameter named page be automatically written into the query string since that will just link us to the current page. We need an override. Fortunately, it's easy to override an encoded view parameter. You simply use the standard tag, just as you would if you were defining a new query string parameter: View parameters that are encoded into links to the current view ID are pretty intuitive. Where things get tricky is when we use view parameters on a link to a different view ID. This requires putting on your thinking cap and doing some reasoning. View parameter handoff When a request is made for a URL, and in turn a JSF view ID, the view parameters defined in that view are used to map request parameters to model properties. But when the view parameters are encoded into a bookmarkable URL, the mappings are read from the target view ID. That's why it's especially important to be able to extract the view metadata from a template without having building a full component tree, as mentioned earlier. Otherwise, you would end up building a component tree for every view that is linked to in the current view. That would be very costly. Let's consider a use case. Suppose that we want to create a link from the search results to a single entry. We would define the link as follows: #{_entry.title} #{_entry.excerpt} The question to ask yourself is this. "Are the search string, category and page offset included in the URL for the entry?". I hope you said "No". The reason is because when the URL for the entry link is built, the component tag reads the view parameter mappings defined in the /entry.xhtml template. The only parameter mapped in that template is entry id. In order to preserve the filter vector, the view parameters defined in the /entries.xhtml view need to also be in the /entry.xhtml template. Aha! Since these are shared view parameters, we should define them in a common template: We can then include that template in each view that needs to preserve these view parameters: ... Keep in mind that if the user navigates to the entry after performing a search, the URL for the entry shown in the browser's location bar will now contain the filter vector. But if you want the user to be able to return to the search filter (without using the back button), that's what you want. You can always provide a simple permalink to bookmark just the entry. Even though you are now defining view parameters in each of the views, that doesn't mean the URL will become littered with empty query string parameters when they are not in use. View parameters are only encoded (i.e., added to the query string) if the value is not null. Otherwise, there is no trace of the view parameter. You have now learned how view parameters are propagated during a postback, on a redirect and into a bookmarkable URL. The main benefit of this process is that it is transparent. You don't have to worry about each and every request parameter that comprises the state in the query string of the URL. Instead, JSF interprets the view parameter metadata defined in the template of the target view and automatically appends those name/value pairs to the URL when you activate this feature. Bookmark it View parameters serve as an alternative to storing state in the UI component tree, provide a starting point for the application, help integrate with legacy applications, assert preconditions of views, make views bookmarkable, and, with help of the new UIOutcomeTarget components or the enhancement to the redirect navigation case, produce links to those bookmarkable views. This article began by introducing you to the view metadata facet, which is a general facility for defining a view's metamodel that reuses the existing UI component infrastructure. You learned that view parameters and PreRenderViewEvent listeners are the first standard implementations of view metadata. You saw how the combination of these two features allow you to capture initial state from URL query string, validate preconditions and load data for a view all before the view is rendered. Finally, you learned how view parameter values are propagated to subsequent requests. This series continues by taking a deeper look at the navigation enhancements made in JSF 2 and explaining how those changes tie into the bookmarkability that you learned about in this article. So bookmark and check back again soon!
October 29, 2009
by Dan Allen
· 103,322 Views
  • Previous
  • ...
  • 1608
  • 1609
  • 1610
  • 1611
  • 1612
  • 1613
  • 1614
  • 1615
  • 1616
  • 1617
  • ...
  • Next
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook
×