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
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Latest Articles - DZone

article thumbnail
We’re not Japanese and we don’t build cars
In 1979 a group of western dignitaries visited Japan to learn more about the manufacturing models that had been applied to great success. Konosuke Matsushita, the president of Matsushita Corporation (Panasonic, Legend, Technics etc.), opened his talk with the famous statement…. “We are going to win and the industrial west is going to lose: there’s nothing much you can do about it, because the reasons for your failure are within yourselves. Your firms are built on the Taylor model; even worse, so are your heads. For you, the essence of management is getting the ideas out of the heads of the bosses and into the hands of labour. We are beyond the Taylor model.”. This leads to two questions: What did Matsushita-san mean by this bold statement?... and why did his visitors deserve such a warm welcome?! To understand Matsushita-san’s point we need to take a brief look at the history of management science. Prior to the Industrial Revolution in the 1830’s, businesses were small-scale, intimate affairs, consisting of a limited number of individuals. To look at the management of large numbers of people prior to this point requires the study of governments and armies. During the early 1800’s technological advances led to the rise of larger industrial enterprises. Factories emerged to produce goods at a larger scale and at lower costs than traditional cottage industries. Cue the entrance of Frederick Winslow Taylor to our story. Taylor was a mechanical engineer who was fascinated with industrial efficiency. He is regarded as being one of the founding fathers of management science and wrote a book on ‘Scientific Management’1. Taylor’s industrial models separated ‘working’ from ‘doing’; he believed that it was the role of management to determine the ‘one best way’ to perform the work… “It is only through enforced standardisation of methods, enforced adoption of the best implements and working conditions and enforced cooperation that this faster work can be assured. And the duty of enforcing the adoption of standards and enforcing this cooperation rests with management alone.”. When Henry Ford set about his mission to revolutionise mass transportation in the early 1900’s, he turned to the latest management thinking to make his dream a reality. Ford created a business of such scale and effectiveness that it must have seemed to his competitors and peers analogous to turning up to the proverbial knife fight with an F-14. He progressed from building a handful of vehicles in 1909 to over 500,000 units just six years later, inventing all of the technology he needed to do it along the way. The success of Henry Ford, and later Alfred Sloan at General Motors, led to a cascade in management thinking. The Taylor model that Ford and Sloan had applied to such great success became the archetypal model for the western corporation in the 20th century. Cut to 1947… The Second World War has ended and Japanese industry has been decimated by two atomic bombs: one at Hiroshima, the other at Nagasaki. The allies, keen to support the redevelopment efforts in Japan, send over a party of management consultants to help with the work required to rebuild industry. Amongst them is William Edwards Deming, a statistician and management theorist whose philosophies had been largely ignored at home. Deming, in contrast to Taylor, believed that ‘thinking’ and ‘doing’ should not be separated, and further, employees should be encouraged and empowered to make decisions on how work should be performed. “All anyone asks for is a chance to work with pride.”. While Deming had been largely ignored in the US, the Japanese got religion. In particular organisations like Toyota and Matsushita built organisational philosophies around empowerment, teamwork and collaboration. They went from some of the worst performing businesses in the country to the strongest. By the late 1970’s world governments were looking to these emerging giants to understand what made them so successful, and in particular, so resilient. It was at this point in 1979 that Matsushita-san delivered his famous speech to western industrial leaders keen to learn the secrets of Japan’s success. It was not until 1991 that the world began to understand the power of the management systems that had been developed in Japan. A book2 was published following a study by MIT’s automotive industry research programme. The book studied the history of the automotive industry and the rise and rise of the mighty Toyota Motor Corporation; the term used to describe Toyota’s secret sauce? Lean Thinking. What Konosuke Matsushita, Toyota’s Taichi Ohno and their contemporaries understood was that the key to the success of their businesses didn’t lie in their tools, techniques, or processes, but was the result of the management philosophies that underpinned their corporations. They thought about their businesses as socio-technical systems and because of this created organisations that encouraged the right behaviours throughout. So, what does this have to do with IT? Firstly we have to recognise that IT is failing. Standish Group estimate that $85B to $145B is spent every year on failed and cancelled IT projects, and that 60% to 70% of all projects either fail outright or are considered troubled (time, cost, scope issues)3. This is a repeated pattern; we can change the country, the industry, the people and the business; the data shows a similar pattern – the problem is systemic. To solve this kind of systemic problem we need to investigate the system more closely and understand the ‘games’ that are being played out within our IT divisions. But what are the components of our IT ecosystem? When we lift the hood, there are a few areas of focus for us to investigate: people, structure, process, culture and technology. The first thing that we may notice about our corporate IT divisions is how little they differ to the Taylorised models Henry Ford and Alfred Sloan built their businesses around 100 years ago. They are structured around functional silo’s, management philosophies are command and control and empowerment is just a word that appears on corporate mouse mats. They are structured for an industrial paradigm in an information age. To make matters worse, most IT managers aspire to create self-managed teams, high levels of collaboration, innovation and continuous improvement. Many have little appreciation that the management models that they enforce, often the only ones that they know, are the very things that are preventing them from achieving the results that they dream of. So how do we change things? Firstly, it’s important to understand the differences in the two management philosophies, as the contrast is stark. For example, where Taylor’s ‘scientific management’ teaches us that managers should manage people, systems management theory teaches us that managers should manage processes. ‘Scientific management’ advocates for maximising the utilisation of our people and machinery, ‘systems management theory’ teaches us to ruthlessly eliminate waste. Although the transition is anything but easy, the results, at least so far, appear impressive. At a recent conference, Jeff Smith, CIO of Suncorp’s 2000 person IT division, estimated that they had increased throughput by over 40% whilst at the same time reducing net operating costs by over 20%4. Similarly, the BBC’s David Joyce announced in a recent article that they had reduced the time taken to engineer a software feature by over 50%5. These organisations are re-engineering many of the components of the IT taxonomy. By taking Agile software principles and introducing statistical control and scheduling techniques from Lean Thinking, teams are radically improving the efficiency and throughput of software delivery processes. They aren’t stopping here though. Product development is being refined to ensure the teams aren’t ‘building the wrong things at speeds previously thought impossible’. Planning and governance processes are being simplified to support responsiveness and adaptability in the business. Even the organisational structure itself isn’t sacred, with some of the more progressive IT divisions moving away from a top-down, hierarchical design, towards a systems based, bottom-up model, removing organisational silo’s to increase collaboration and introduce a stronger customer focus. The real change for these organisations isn’t in the structure, processes or tools of course, but in something much more subtle and complex: the way they think. Changing 100 years of western management thinking is not a simple task but industrial models just don’t cut it in an information age. Deming taught us that the processes and structures we create as leaders always produce exactly the results they are designed to produce; the system always works perfectly. In IT we have created approaches that fail (or have difficulties) 60% to 70% of the time. It’s our responsibility as leaders to change the system. This leads to the title of the article. The most common excuse I hear for avoiding change and improvement in IT leadership is that we’re not Japanese and we don’t build cars. I hear this excuse every day and it misses the point. Lean Thinking, and the management paradigm that underpins it, Systems Management Theory, focus on changing the role of leadership; it knows no national or industrial bounds, and this has been proven time again over the last 30 years, from manufacturing to healthcare. IT leadership is once again lagging behind the management curve. To re-enforce the point even further, a recent article in the Harvard Business Review6 asked some of the worlds leading academic and industrial business thinkers for the big ticket changes required in western management thinking over the next 10 years. Retraining managerial minds in systems thinking appeared in it’s top 25. Also in there was reducing the pull of the past, eliminating the pathologies of formal hierarchy and reconstructing management’s philosophical foundations. This is nothing new – management science has pointed towards collaboration, teamwork and trust for over 30 years. But mouthing the words is easy; Systems Management Theory gives us the tools to go execute. Introducing this paradigm shift, although not an easy journey, has certainly been proven achievable. Agile software development methods, based on the Toyota Production System, help us to quickly introduce Lean concepts to our software development operations. Statistical control techniques can help us improve and refine them. Recently, Lean concepts have helped scale these working-level techniques to the enterprise by borrowing philosophies, tools and techniques to solve historic problems with structure, budgeting and governance in top-down, command and control organisations. And middle management are proving willing to change, and even lead the charge, given the right leadership, support and opportunities. Driving change is hard. I often compare being a CIO to the job of a grounds keeper in a cemetery; there are a lot of people underneath you but no-one is listening. Of course, we don’t have to strive to improve the problem; I’ll leave the last word to Deming himself… “It’s not necessary to change. Survival is not mandatory.”. 1. The Principles of Scientific Management: Frederick Winslow Taylor. 2. The Machine That Changed The World: Womack, Jones, Roos. 3. Standish Chaos Reports 2000 to 2009. 4. Agile Australia (http://www.agileaustralia.com/video.html) 5. David Joyce (http://leanandkanban.wordpress.com) 6. Harvard Business Review, February 2009: Moonshots for Managers
December 23, 2009
by Richard Durnall
· 24,984 Views · 1 Like
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,423 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,944 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,839 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
· 137,501 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,168 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,415 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,650 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,703 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,343 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,162 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,471 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,363 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,556 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,793 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,590 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,707 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,301 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,690 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,875 Views
  • Previous
  • ...
  • 1626
  • 1627
  • 1628
  • 1629
  • 1630
  • 1631
  • 1632
  • 1633
  • 1634
  • 1635
  • ...
  • 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
×