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

The Latest Integration Topics

article thumbnail
How to Manage Keyboard Shortcuts in Eclipse and Why You Should
when i use eclipse i try and use shortcuts all the time. they really make me work faster and give me time to focus on getting the code out rather than slowing down to invoke ide commands with the mouse. because people work differently and on different things, it’s important to manage keyboard shortcuts to suit the way you work. so it’s good that eclipse makes it really easy to change shortcuts and also to view shortcuts for the commands you use a lot. i’ll discuss how to change keyboard shortcuts, how to avoid conflicts with existing ones, why it’s a good thing to manage shortcuts and then end off with some examples of common shortcuts that you should add to you arsenal. how do you manage keyboard shortcuts the main preference page can be found under window > preferences > general > keys (or faster: press ctrl+3 , type keys and press enter ). from here you can see all commands and assign/change their associated keyboard shortcuts. in the video, i’ll show you how to reassign a key. we’ll use this to assign ctrl+tab to switch to the next editor. notes: you don’t have to copy a command to assign/reassign a shortcut. i just prefer to keep the old shortcut in case someone else wants to take over my keyboard and expects the shortcut to work. all commands registered with eclipse are listed on the keys preference page. browse through them or search to see if your favourite command is listed. if it doesn’t have a shortcut assigned, then assign one immediately. the when dropdown on the dialog shows you in which context the command applies (eg. only when editing java source). you can assign the same shortcut to two different commands, but if the context differs eclipse will only execute the one command. i suggest you don’t change the context. notice that eclipse shows you which keys conflict with the selected one if their in the same context. but all the keys are already taken no, they’re not. firstly, if a key you like is already taken then be creative. use combos like ctrl+alt, alt+shift or even alt+shift+ctrl (easier to press then you think). these aren’t used as often as ctrl or ctrl+shift. you can sort by binding to see which keys are already used. secondly, eclipse allows you to assign a sequence of keystrokes to a command. eg. alt+shift+x, j (that’s used to run the current class as a java application) is invoked by pressing alt+shift+x, releasing the keys then pressing j. if you forgot your sequence shortcuts, just press the first part (eg. alt+shift+x), wait a second then eclipse helps you out by listing all commands that have this keystroke as the first part of the sequence. the list appears in the lower right corner of the window. this works for any commands assigned a sequence of keystrokes. here’s an example of what you might see when you press the first sequence of keystrokes (notice the list in the lower, right corner). tip: for custom commands you want to assign, use a well-known first keystroke to group your commands. for example, i use alt+shift+b (b for byron) as my grouping prefix. this way there are fewer conflicts with existing shortcuts and eclipse can show me a quick list if i forgot which keys i used. so why bother managing keyboard shortcuts managing keyboard shortcuts in eclipse is important because: not all eclipse commands have assigned shortcuts. a command you frequently use could be assigned a shortcut. eg. an svn commit is registered as an eclipse command but doesn’t have a keyboard shortcut assigned. assigning one yourself will speed up checking in changes. sometime eclipse gets it wrong. a good example is ctrl+f6 for switching editors – ctrl+tab is a much more sensible option since the keys are close together and doable with one hand. going through the list of shortcuts may give you ideas for working faster or even show you a command you didn’t know eclipse could do. but don’t shortcuts take a long time to learn? no ways! i often hear people complain that it takes too long to learn the shortcuts. i assure you that the 5 minutes it takes to learn the shortcut saves you hours, even days, of work over the months and years that you’ll be working on eclipse. here are some tips to get into and improve your keyboard usage: start by learning the shortcuts for the things you do often. are you using the mouse a lot to launch applications or select code? well, there’s a shortcut to launch apps and one to select code faster. keyboard shortcuts are often indicated next to menu items. note them and try to use them instead of reaching for the mouse. learn to punish yourself when you reach for the mouse by undoing your action and forcing yourself to use the keyboard. this seems counterproductive (and harsh) at first, but it forces your brain to rewire itself so you’ll favour the shortcuts instead of the mouse the next time. there is an eclipse plugin called mousefeed that shows you a keyboard alternative to a mouse click you performed. you can also configure it to cancel mouse clicks where a keyboard alternative is available, forcing you to use the keyboard in those instances. i don’t use it personally but what i’ve seen looks good. it’s definitely sounds like a good idea if you want to change your mousey ways and it relates nicely to my previous point. also keep this in mind: one of the easiest, surefire ways to work faster is to reduce the number of times you move your hands between the keyboard and mouse. the key is doing as much as possible with either one. for the mouse there are things like mouse gestures (if you’re on windows, try strokeit ). for the keyboard there are keyboard shortcuts and eclipse has hundreds of them ready to make your life easier (also see the excellent autohotkey for other ways to boost your keyboard usage). examples of useful keyboard shortcuts there are way too many shortcuts to list and you’ll come across the more useful ones in other tips . here are some you should get acquainted with at first and try to use all the time. shortcut action ctrl+1 quick fix list (for resolving errors/warnings) and also refactoring ctrl+space display the autocomplete list to select a relevant method/template, etc. ctrl+3 open quick access which allows you to run commands and navigate views and dialogs by searching for them, similar to launchy on windows or quicksilver on mac. ctrl+shift+r open any resource in the workspace, eg. xml file, class file, etc. ctrl+shift+t open a java type, eg. a class or interface. f3 go to the declaration of the method/class/variable f11/ctrl+f11 debug/run the last launched application (see this tip for more information) ctrl+alt+h display all methods that call a method (call hierarchy) f2 show javadoc for the current element (shift+f2 shows external javadoc) alt+up/down, alt+shift+down, ctrl+d move a line up/down, copy a line, delete a line (see this tip for more information) ctrl+/ comment/uncomment the current line or selected lines. you can be anywhere in the line, not necessarily at the beginning. you can press ctrl+shift+l to get a list of registered keyboard shortcuts in the lower right corner. but for a complete list, i prefer to go to the preference dialog as i can see all commands that are registered, even if they don’t have shortcuts registered from http://eclipseone.wordpress.com
February 12, 2010
by Byron M
· 36,711 Views
article thumbnail
JavaFX, Sockets and Threading: Lessons Learned
When contemplating how machine-dependent applications might communicate with Java/JavaFX, JNI or the Java Native Interface, having been created for just such a task, would likely be the first mechanism that comes to mind. Although JNI works just fine thank you, a group of us ultimately decided against using it for a small project because, among others: Errors in your JNI implementation can corrupt the Java Virtual Machine in very strange ways, leading to difficult diagnosis. JNI can be time consuming and tedious, especially if there's a varied amount of interchange between the Native and Java platforms. For each OS/Platform supported, a separate JNI implementation would need to be created and maintained. Instead we opted for something a bit more mundane, namely sockets. The socket programming paradigm has been around a long time, is well understood and spans a multitude of hardware/software platforms. Rather than spending time defining JNI interfaces, just open up a socket between applications and send messages back and forth, defining your own message protocol. Following are some reflections on using sockets with JavaFX and Java. For the sake of simplicity, we'll skip the native stuff and focus on how sockets can be incorporated into a JavaFX application in a thread safe manner. Sockets and Threading Socket programming, especially in Java, lends itself to utilizing threads. Because a socket read() will block waiting for input, a common practice is to place the read loop in a background thread enabling you to continue processing while waiting for input at the same time. And if you're doing this work entirely in Java, you'll find that both ends of the socket connection -- the "server" side and the "client" side -- share a great deal of common code. Recognizing this, an abstract class called GenericSocket.java was created which is responsible for housing the common functionality shared by "server" and "client" sockets including the setup of a reader thread to handle socket reads asynchronously. For this simple example, two implementations of the abstract GenericSocket class, one called SocketServer.java, the other called SocketClient.java have been supplied. The primary difference between these two classes lies in the type of socket they use. SocketServer.java uses java.net.ServerSocket, while SocketClient.java uses java.net.Socket. The respective implementations contain the details required to set up and tear down these slightly different socket types. Dissecting the Java Socket Framework If you want to utilize the provided Java socket framework with JavaFX, you need to understand this very important fact: JavaFX is not thread safe and all JavaFX manipulation should be run on the JavaFX processing thread.1 If you allow a JavaFX application to interact with a thread other than the main processing thread, unpredictable errors will occur. Recall that the GenericSocket class created a reader thread to handle socket reads. In order to avoid non-main-thread-processing and its pitfalls with our socket classes, a few modifications must take place. [1] Stolen from JavaFX: Developing Rich Internet Applications - Thanks Jim Clarke Step 1: Identify Resources Off the Main Thread The first step to operating in a thread safe manner is to identify those resources in your Java code, residing off the main thread, that might need to be accessed by JavaFX. For our example, we define two abstract methods, the first, onMessage(), is called whenever a line of text is read from the socket. The GenericSocket.java code will make a call to this method upon encountering socket input. Let's take a look at the SocketReaderThread code inside GenericSocket, to get a feel for what's going on. class SocketReaderThread extends Thread { @Override public void run() { String line; waitForReady(); /* * Read from from input stream one line at a time */ try { if (input != null) { while ((line = input.readLine()) != null) { if (debugFlagIsSet(DEBUG_IO)) { System.out.println("recv> " + line); } /* * The onMessage() method has to be implemented by * a sublclass. If used in conjunction with JavaFX, * use Entry.deferAction() to force this method to run * on the main thread. */ onMessage(line); } } } catch (Exception e) { if (debugFlagIsSet(DEBUG_EXCEPTIONS)) { e.printStackTrace(); } } finally { notifyTerminate(); } } Because onMessage() is called off the main thread and inside SocketReaderThread, the comment states that some additional work, which we'll explain soon, must take place to assure main thread processing. Our second method, onClosedStatus(), is called whenever the status of the socket changes (either opened or closed for whatever reason). This abstract routine is called in different places within GenericSocket.java -- sometimes on the main thread, sometimes not. To assure thread safety, we'll employ the same technique as with onMessage(). Step 2: Create a Java Interface with your Identified Methods Once identified, these method signatures have to be declared inside a Java interface. For example, our socket framework includes a SocketListener.java interface file which looks like this: package genericsocket; public interface SocketListener { public void onMessage(String line); public void onClosedStatus(Boolean isClosed); } Step 3: Create Your Java Class, Implementing Your Defined Interface With our SocketListener interface defined, let's take a step-by-step look at how the SocketServer class is implemented inside SocketServer.java. One of the first requirements is to import a special Java class which will allow us to do main thread processing, achieved as follows: import com.sun.javafx.runtime.Entry; Next, comes the declaration of SocketServer. Notice that in addition to extending the abstract GenericSocket class it also must implement our SocketListener interface too: public class SocketServer extends GenericSocket implements SocketListener { Inside the SocketServer definition, a variable called fxListener of type SocketListener is declared: private SocketListener fxListener; The constructor for SocketServer must include a reference to fxListener. The other arguments are used to specify a port number and some debug flags. public SocketServer(SocketListener fxListener, int port, int debugFlags) { super(port, debugFlags); this.fxListener = fxListener; } Next, let's examine the implementation of the two methods which are declared in the SocketListener interface. The first, onMessage(), looks like this: /** * Called whenever a message is read from the socket. In * JavaFX, this method must be run on the main thread and * is accomplished by the Entry.deferAction() call. Failure to do so * *will* result in strange errors and exceptions. * @param line Line of text read from the socket. */ @Override public void onMessage(final String line) { Entry.deferAction(new Runnable() { @Override public void run() { fxListener.onMessage(line); } }); } As the comment points out, the Entry.deferAction() call enables fxListener.onMessage() to be executed on the main thread. It takes as an argument an instance of the Runnable class and, within its run() method, makes a call to fxListener.onMessage(). Another important point to notice is that onMessage()'s String argument must be declared as final. Along the same line, the onClosedStatus() method is implemented as follows: /** * Called whenever the open/closed status of the Socket * changes. In JavaFX, this method must be run on the main thread and * is accomplished by the Entry.deferAction() call. Failure to do so * will* result in strange errors and exceptions. * @param isClosed true if the socket is closed */ @Override public void onClosedStatus(final Boolean isClosed) { Entry.deferAction(new Runnable() { @Override public void run() { fxListener.onClosedStatus(isClosed); } }); } Another Runnable is scheduled via Entry.deferAction() to run fxlistener.onClosedStatus() on the main thread. Again, onClosedStatus()'s Boolean argument must also be defined as final. Accessing the Framework within JavaFX With this work behind us, now we can integrate the framework into JavaFX. But before elaborating on the details, lets show screenshots of two simple JavaFX applications, SocketServer and SocketClient which, when run together, can send and receive text messages to one another over a socket. These JavaFX programs were developed in NetBeans and utilize the recently announced NetBeans JavaFX Composer tool. You can click on the images to execute these programs via Java WebStart. Note: depending upon your platform, your system may ask for permission prior to allowing these applications to network. Source for the JavaFX applications and the socket framework in the form of NetBeans projects can be downloaded here. Step 4: Integrating into JavaFX To access the socket framework within JavaFX, you must implement the SocketListener class that was created for this project. To give you a feel for how this is done with our JavaFX SocketServer application, here are some code excerpts from the project's Main.fx file, in particular the definition of our ServerSocketListener class: public class ServerSocketListener extends SocketListener { public override function onMessage(line: String) { insert line into recvListView.items; } public override function onClosedStatus(isClosed : java.lang.Boolean) { socketClosed = isClosed; tryingToConnect = false; if (autoConnectCheckbox.selected) { connectButtonAction(); } } } Sparing all of the gory details, the onMessage() method will place the line of text read from the socket in to a JavaFX ListView control which is displayed in the program user interface. The onClosedStatus() method primarily updates the local socketClosed variable and attempts to reconnect the socket if the autoconnect option has been selected. To demonstrate how the socket is created, we examine the connectButtonAction() function: var socketServer : SocketServer; ... public function connectButtonAction (): Void { if (not tryingToConnect) { if (socketClosed) { socketServer = new SocketServer(ServerSocketListener{}, java.lang.Integer.parseInt(portTextbox.text), javafx.util.Bits.bitOr(GenericSocket.DEBUG_STATUS, GenericSocket.DEBUG_IO)); tryingToConnect = true; socketServer.connect(); } } } Whenever the user clicks on the "Connect" button, the connectButtonAction() function will be called. On invocation, if the socket isn't already open, it will create a new SocketServer instance. Recognize also that the SocketServer constructor includes an instance of the ServerSocketListener class which was defined above. To round this out, when the user clicks on the "Disconnect" button, the disconnectButtonAction() function is called. When invoked, it tears down the SocketServer instance. function disconnectButtonAction (): Void { tryingToConnect = false; socketServer.shutdown(); } Conclusion Admittedly, there's a fair amount to digest here. Hopefully, by carefully reviewing the steps and looking at the complete code listing, this can serve as a template if you wish to accomplish something similar in JavaFX. From http://blogs.sun.com/jtc/
February 11, 2010
by Jim Connors
· 22,225 Views
article thumbnail
Promiscuous Integration vs. Continuous Integration
The emergence of version control systems makes both promiscuous and continuous integration merging techniques more attractive. Which is better?
February 10, 2010
by Martin Fowler
· 50,262 Views · 2 Likes
article thumbnail
Reloading Java Classes: Classloaders in Web Development — Tomcat, GlassFish, OSGi, Tapestry 5
In this article we’ll review how dynamic classloaders are used in real servers, containers and frameworks to reload Java classes and applications. We’ll also touch on how to get faster reloads and redeploys by using them in optimal ways. RJC101: Objects, Classes and ClassLoaders RJC201: How do ClassLoader leaks happen? RJC301: Classloaders in Web Development — Tomcat, GlassFish, OSGi, Tapestry 5 and so on RJC401: HotSwap and JRebel — what do they really do? RJC501: The impact of the redeploy phase on the development process AKA:Turnaround Java EE (web) applications In order for a Java EE web application to run, it has to be packaged into an archive with a .WAR extension and deployed to a servlet container like Tomcat. This makes sense in production, as it gives you a simple way to assemble and deploy the application, but when developing that application you usually just want to edit the application’s files and see the changes in the browser. A Java EE enterprise application has to be packaged into an archive with an .EAR extension and deployed to an application container. It can contain multiple web applications and EJB modules, so it often takes a while to assemble and deploy it. Recently, 1100+ EE developers told us how much time it takes them, and we compiled the results into the Redeploy and Restart Report. Spoiler: Avg redeploy & restart time is 2.5 minutes – which is higher than we expected. In Reloading Java Classes 101, we examined how dynamic classloaders can be used to reload Java classes and applications. In this article we will take a look at how servers and frameworks use dynamic classloaders to speed up the development cycle. We’ll use Apache Tomcat as the primary example and comment when behavior differs in other containers (Tomcat is also directly relevant for JBoss and GlassFish as these containers embed Tomcat as the servlet container). Redeployment To make use of dynamic classloaders we must first create them. When deploying your application, the server will create one classloader for each application (and each application module in the case of an enterprise application). The classloaders form a hierarchy as illustrated: In Tomcat each .WAR application is managed by an instance of the StandardContext class that creates an instance of WebappClassLoader used to load the web application classes. When a user presses “reload” in the Tomcat Manager the following will happen: StandardContext.reload() method is called The previous WebappClassLoader instance is replaced with a new one All reference to servlets are dropped New servlets are created Servlet.init() is called on them Calling Servlet.init() recreates the “initialized” application state with the updated classes loaded using the new classloader instance. The main problem with this approach is that to recreate the “initialized” state we run the initialization from scratch, which usually includes loading and processing metadata/configuration, warming up caches, running all kinds of checks and so on. In a sufficiently large application this can take many minutes, but in a in small application this often takes just a few seconds and is fast enough to seem instant, as commonly demonstrated in the Glassfish v3 promotional demos. If your application is deployed as an .EAR archive, many servers allow you to also redeploy each application module separately, when it is updated. This saves you the time you would otherwise spend waiting for non-updated modules to reinitialize after the redeployment. Hot Deployment Web containers commonly have a special directory (e.g. “webapps” in Tomcat, “deploy” in JBoss) that is periodically scanned for new web applications or changes to the existing ones. When the scanner detects that a deployed .WAR is updated, the scanner causes a redeploy to happen (in Tomcat it calls the StandardContext.reload() method). Since this happens without any additional action on the user’s side it is commonly referred to “Hot Deployment”. Hot Deployment is supported by all wide-spread application servers under different names: autodeployment, rapid deployment, autopublishing, hot reload, and so on. In some containers, instead of moving the archive to a predefined directory you can configure the server to monitor the archive at a specific path. Often the redeployment can be triggered from the IDE (e.g. when the user saves a file) thus reloading the application without any additional user involvement. Although the application is reloaded transparently to the user, it still takes the same amount of time as when hitting the “Reload” button in the admin console, so code changes are not immediately visible in the browser, for example. Another problem with redeployment in general and hot deployment in particular is classloader leaks. As we reviewed in Reloading Java Classes 201, it is amazingly easy to leak a classloader and quickly run out of heap causing an OutOfMemoryError. As each deployment creates new classloaders, it is common to run out of memory in just a few redeploys on a large enough application (whether in development or in production). Exploded Deployment An additional feature supported by the majority of web containers is the so called “exploded deployment”, also known as “unpackaged” or “directory” deployment. Instead of deploying a .WAR archive, one can deploy a directory with exactly the same layout as the .WAR archive: Why bother? Well, packaging an archive is an expensive operation, so deploying the directory can save quite a bit of time during build. Moreover, it is often possible to set up the project directory with exactly the same layout as the .WAR archive. This means an added benefit of editing files in place, instead of copying them to the server. Unfortunately, as Java classes cannot be reloaded without a redeploy, changing a .java file still means waiting for the application to reinitialize. With some servers it makes sense to find out exactly what triggers the hot redeploy in the exploded directory. Sometimes the redeploy will be triggered only when the “web.xml” timestamp changes, or as in the case of GlassFish only when a special ”.reload” file timestamp changes. In most servers any change to deployment descriptors or compiled classes will cause a hot redeploy. If your server only supports deploying by copying to a special directory (e.g. Tomcat “webapps”, JBoss “deploy” directories) you can skip the copying by creating a symlink from that special directory to your project workspace. On Linux and Mac OS X you can use the common “ln -s” command to do that, whereas on Windows you should download the Sysinternals “junction” utility. If you use Maven, then it’s quite complicated to set up exploded development from your workspace. If you have a solo web application you can use the Maven Jetty plugin, which uses classes and resources directly from Maven source and target project directories. Unfortunately, the Maven Jetty plugin does not support deploying multiple web applications, EJB modules or EARs so in the latter case you’re stuck doing artifact builds. Session Persistence Since we’re on the topic of reloading classes, and redeploying involves reinitializing an application, it makes sense to talk about session state. An HTTP session usually holds information like login credentials and conversational state. Losing that session when developing a web application means spending time logging in and browsing to the changes page – something that most web containers have tried to solve by serializing all of the objects in the HttpSession map and then deserializing them in the new classloader. Essentially, they copy all of the session state. This requires that all session attributes implement Serializable (ensuring session attributes can be written to a database or a file for later use), which is not restricting in most cases. Session persistence has been present in most major containers for many years (e.g. Restart Persistence in Tomcat), but was notoriously absent in Glassfish before v3. OSGi There is a lot of misunderstanding surrounding what exactly OSGi does and doesn’t do. If we ignore the aspects irrelevant to the current issue, OSGi is basically a collection of modules each wrapped in its own classloader, which can be dropped and recreated at will. When it’s recreated, the modules are reinitialized exactly the same way a web application is. The difference between OSGi and a web container is that OSGi is something that is exposed to your application, that you use to split your application into arbitrarily small modules. Therefore, by design, these modules will likely be much smaller than the monolithic web applications we are used to building. And since each of these modules is smaller and we can “redeploy” them one-by-one, re-initialization takes less time. The time depends on how you design your application (and can still be significant). Tapestry 5, RIFE & Grails Recently, some web frameworks, such as Tapestry 5, RIFE and Grails, have taken a different approach, taking advantage of the fact that they already need to maintain application state. They’ll ensure that state will be serializable, or otherwise easily re-creatable, so that after dropping a classloader, there is no need to reinitialize anything. This means that application developers use frameworks’ components and the lifecycle of those components is handled by the framework. The framework will initialize (based on some configuration, either xml or annotation based), run and destroy the components. As the lifecycle of the components is managed by the framework, it is easy to recreate a component in a new classloader without user intervention and thus create the effect of reloading code. In the background, the old component is destroyed (classloader is dropped) and a new one created (in a new classloader where the classes are read in again) and the old state is either deserialized or created based on the configuration. This has the obvious advantage of being very quick, as components are small and the classloaders are granular. Therefore the code is reloaded instantly, giving a smooth experience in developing the application. However such an approach is not always possible as it requires the component to be completely managed by the framework. It also leads to incompatibilities between the different class versions causing, among others, ClassCastExceptions. We’ve Covered a Lot – and simplified along the way It’s worth mentioning that using classloaders for code reloading really isn’t as smooth as we have described here – this is an introductory article series. Especially with the more granular approaches (such as frameworks that have per component classloaders, manual classloader dropping and recreating, etc), when you start getting a mixture of older and newer classes all hell can break loose. You can hold all kinds of references to old objects and classes, which will conflict with the newly loaded ones (a common problem is getting a ClassCastException), so watch what you’re doing along the way. As a side note: Groovy is actually somewhat better at handling this, as all calls through the Meta-Object Protocol are not subject to such problems. This article addressed the following questions: How are dynamic classloaders used to reload Java classes and applications? How do Tomcat, GlassFish (incl v3), and other servers reload Java classes and applications? How does OSGi improve reload and redeploy times? How do frameworks (incl Tapestry 5, RIFE, Grails) reload Java classes and applications? Coming up next, we continue our explanation of classloaders and the redeploy process with an investigation into HotSwap and JRebel, two tools used to reduce time spent reloading and redeploying. Stay tuned! From http://www.zeroturnaround.com/blog/
January 23, 2010
by Dave Booth
· 26,400 Views
article thumbnail
Struts 2 Tutorial: Create Struts 2 Application in Eclipse
Welcome to the Part 2 of 7-part series where we will explore the world of Struts 2 Framework. In we went through the basics of Struts2, its Architecture diagram, the request processing lifecycle and a brief comparison of Struts1 and Struts2. If you have not gone through the previous article, I highly recommend you to do that before starting hands-on today. Struts 2 Tutorial List Part 7: Struts 2 Ajax Tutorial with Example Related: Create Struts Application with Eclipse Things We Need Before we starts with our first Hello World Struts 2 Example, we will need few tools. JDK 1.5 above (download) Tomcat 5.x above or any other container (Glassfish, JBoss, Websphere, Weblogic etc) (download) Eclipse 3.2.x above (download) Apache Struts2 JAR files:(download). Following are the list of JAR files required for this application. commons-logging-1.0.4.jar freemarker-2.3.8.jar ognl-2.6.11.jar struts2-core-2.0.12.jar xwork-2.0.6.jar Note that depending on the current version of Struts2, the version number of above jar files may change. Our Goal Our goal is to create a basic Struts2 application with a Login page. User will enter login credential and if authenticated successfully she will be redirected to a Welcome page which will display message ”Howdy, …!“. If user is not authenticated, she will be redirected back to the login page. Getting Started Let us start with our first Struts2 based application. Open Eclipse and goto File -> New -> Project and select Dynamic Web Project in the New Project wizard screen. After selecting Dynamic Web Project, press Next. Write the name of the project. For example StrutsHelloWorld. Once this is done, select the target runtime environment (e.g. Apache Tomcat v6.0). This is to run the project inside Eclipse environment. After this press Finish. Once the project is created, you can see its structure in Project Explorer. Now copy all the required JAR files in WebContent -> WEB-INF -> lib folder. Create this folder if it does not exists. Mapping Struts2 in WEB.xml As discussed in the previous article (Introduction to Struts2), the entry point of Struts2 application will be the Filter define in deployment descriptor (web.xml). Hence we will define an entry of org.apache.struts2.dispatcher.FilterDispatcher class in web.xml. Open web.xml file which is under WEB-INF folder and copy paste following code. Struts2 Applicationstruts2org.apache.struts2.dispatcher.FilterDispatcherstruts2/*Login.jsp The above code in web.xml will map Struts2 filter with url /*. The default url mapping for struts2 application will be /*.action. Also note that we have define Login.jsp as welcome file. The Action Class We will need an Action class that will authenticate our user and holds the value for username and password. For this we will create a package net.viralpatel.struts2 in the source folder. This package will contain the action file. Create a class called LoginAction in net.viralpatel.struts2 package with following content. package net.viralpatel.struts2;public class LoginAction {private String username;private String password;public String execute() {if (this.username.equals("admin")&& this.password.equals("admin123")) {return "success";} else {return "error";}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;} Note that, above action class contains two fields, username and password which will hold the values from form and also contains an execute() method that will authenticate the user. In this simple example, we are checking if username is admin and password is admin123. Also note that unlike Action class in Struts1, Struts2 action class is a simple POJO class with required attributes and method. The execute() method returns a String value which will determine the result page. Also, in Struts2 the name of the method is not fixed. In this example we have define method execute(). You may want to define a method authenticate() instead. The ResourceBundle ResourceBundle is very useful Java entity that helps in putting the static content away from the source file. Most of the application define a resource bundle file such as ApplicationResources.properties file which contains static messages such as Username or Password and include this with the application. ResourceBundle comes handy when we want to add Internationalization (I18N) support to an application. We will define an ApplicationResources.properties file for our application. This property file should be present in WEB-INF/classes folders when the source is compiled. Thus we will create a source folder called resources and put the ApplicationResources.properties file in it. To create a source folder, right click on your project in Project Explorer and select New -> Source Folder. Specify folder name resources and press Finish. Create a file ApplicationResources.properties under resources folder. Copy following content in ApplicationResources.properties. label.username= Usernamelabel.password= Passwordlabel.login= Login The JSP We will create two JSP files to render the output to user. Login.jsp will be the starting point of our application which will contain a simple login form with username and password. On successful authentication, user will be redirected to Welcome.jsp which will display a simple welcome message. Create two JSP files Login.jsp and Welcome.jsp in WebContent folder of your project. Copy following content into it. Login.jsp Struts 2 - Login Application Welcome.jsp Howdy, ...! Note that we have used struts2 tag to render the textboxes and labels. Struts2 comes with a powerful built-in tag library to render UI elements more efficiently. The struts.xml file Struts2 reads the configuration and class definition from an xml file called struts.xml. This file is loaded from the classpath of the project. We will define struts.xml file in the resources folder. Create file struts.xml in resources folder. Copy following content into struts.xml. Welcome.jspLogin.jsp Note that in above configuration file, we have defined Login action of our application. Two result paths are mapped with LoginAction depending on the outcome of execute() method. If execute() method returns success, user will be redirected to Welcome.jsp else to Login.jsp. Also note that a constant is specified with name struts.custom.i18n.resources. This constant specify the resource bundle file that we created in above steps. We just have to specify name of resource bundle file without extension (ApplicationResources without .properties). Our LoginAction contains the method execute() which is the default method getting called by Sturts2. If the name of method is different, e.g. authenticate(); then we should specify the method name in tag. Almost Done We are almost done with the application. You may want to run the application now and see the result yourself. I assume you have already configured Tomcat in eclipse. All you need to do: Open Server view from Windows -> Show View -> Server. Right click in this view and select New -> Server and add your server details. To run the project, right click on Project name from Project Explorer and select Run as -> Run on Server (Shortcut: Alt+Shift+X, R) But there is one small problem. Our application runs perfectly fine at this point. But when user enters wrong credential, she is redirected to Login page. But no error message is displayed. User does not know what just happened. A good application always show proper error messages to user. So we must display an error message Invalid Username/Password. Please try again when user authentication is failed. Final Touch To add this functionality first we will add the error message in our ResourceBundle file. Open ApplicationResources.properties and add an entry for error.login in it. The final ApplicationResources.properties will look like: label.username= Usernamelabel.password= Passwordlabel.login= Loginerror.login= Invalid Username/Password. Please try again. Also we need to add logic in LoginAction to add error message if user is not authenticated. But there is one problem. Our error message is specified in ApplicationResources.properties file. We must specify key error.login in LoginAction and the message should be displayed on JSP page. For this we must implement com.opensymphony.xwork2.TextProvider interface which provides method getText(). This method returns String value from resource bundle file. We just have to pass the key value as argument to getText() method. The TextProvider interface defines several method that we must implement in order to get hold on getText() method. But we don’t want to spoil our code by adding all those methods which we do not intend to use. There is a good way of dealing with this problem. Struts2 comes with a very useful class com.opensymphony.xwork2.ActionSupport. We just have to extend our LoginAction class with this class and directly use methods such as getText(), addActionErrors() etc. Thus we will extend the LoginAction class with ActionSupport class and add the logic for error reporting into it. The final code in LoginAction must look like: package net.viralpatel.struts2;import com.opensymphony.xwork2.ActionSupport;public class LoginAction extends ActionSupport {private String username;private String password;public String execute() {if (this.username.equals("admin")&& this.password.equals("admin123")) {return "success";} else {addActionError(getText("error.login"));return "error";}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;} And that’s it. Our first Hello World Struts2 Application is now ready. That’s All Folks Execute the application in Eclipse and run it in your favorite browser. Login page Welcome page Login page with error Download Source Code Click here to download Source Code without JAR files (9KB). Moving On Now that we have created our first webapp using Struts2 framework, we know how the request flows in Struts2. We also know the use of struts.xml and properties file. In this application we implemented a preliminary form of validation. In we will learn more about Validation Framework in Struts2 and implement it in our example. Original article: http://viralpatel.net/blogs/2009/12/tutorial-create-struts-2-application-eclipse-example.html
January 15, 2010
by Viral Patel
· 289,983 Views
article thumbnail
Groovy AST Transformations by Example: Adding Methods to Classes
What can you do with a Groovy AST Transformation? A difficult question, considering the answer is "almost anything".
January 8, 2010
by Hamlet D'Arcy
· 46,508 Views
article thumbnail
Java Content Repository: The Best Of Both Worlds
Learn the basics of Java Content Repositories, including how they work, and how they're used.
January 4, 2010
by Bertrand Delacretaz
· 144,894 Views · 5 Likes
article thumbnail
Spring Integration and Apache Camel
Spring Integration and Apache Camel are open source frameworks providing a simpler solution for the Integration problems in the enterprise, to quote from their respective websites: Apache Camel - Apache Camel is a powerful open source integration framework based on known Enterprise Integration Patterns with powerful Bean Integration. Spring Integration - It provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns while building on the Spring Framework's existing support for enterprise integration. Essentially Spring Integration and Apache Camel enable applications to integrate with other systems. This article seeks to provide an implementation for an integration problem using both Spring Integration and Apache Camel. The objective is to show how easy it is to use these frameworks for a fairly complicated integration problem and to recommend either of these great products for your next Integration challenge. Problem: To illustrate the use of these frameworks consider a simple integration scenario, described using EIP terminology: The application needs to get a "Report" by aggregating "Sections" from a Section XML over http service. Each request for Report consists of a set of request for sections – in this specific example there are requests for three sections, the header, body and footer. The XML over http service returns a Section for the Section Request. The responses need to be aggregated into a single report. A sample test for this scenario is of the following type: ReportGenerator reportGenerator = reportGeneratorFactory.createReportGenerator(); List sectionRequests = new ArrayList(); String entityId="A Company"; sectionRequests.add(new SectionRequest(entityId,"header")); sectionRequests.add(new SectionRequest(entityId,"body")); sectionRequests.add(new SectionRequest(entityId,"footer")); ReportRequest reportRequest = new ReportRequest(sectionRequests); Report report = reportGenerator.generateReport(reportRequest); List sectionOfReport = report.getSections(); System.out.println(report); assertEquals(3, sectionOfReport.size()); The “ReportGenerator” is the messaging gateway, hiding the details of the underlying messaging infrastructure and in this specific case also the integration API – Apache Camel or Spring Integration. To start with, let us implement a solution to this integration problem using Spring Integration as the Framework, followed by Apache Camel. The complete working code using Spring Integration and Apache Camel is also available with the article. Solution Using Spring Integration: The Gateway component is easily configured using the following entry in the Spring Configuration. Internally Spring Integration uses AOP to hook up a component which routes the requests from an internal input channel and waits for the response in the response channel. The component to Split the Input Report Request to Section Request is fairly straightforward: public class SectionRequestSplitter { public List split(ReportRequest reportRequest){ return reportRequest.getSectionRequests(); } } and to hook this splitter with Spring Integration: Next, to transform the Section Request to an XML format - The component is the following: public class SectionRequestToXMLTransformer { public String transform(SectionRequest sectionRequest){ //this needs to be optimized...purely for demonstration of the concept String sectionRequestAsString = "" + sectionRequest.getEntityId() + "" + sectionRequest.getSectionId() + ""; return sectionRequestAsString; } } and is hooked up in the Spring Integration configuration file in the following way: To send an XML over http request using the Section Request XML to a section Service: To transform the Section Response XML to a Section Object - The component is the following: public class SectionResponseXMLToSectionTransformer { public Section transform(String sectionXML) { SAXReader saxReader = new SAXReader(); Document document; String sectionName = ""; String entityId = ""; try { document = saxReader.read(new StringReader(sectionXML)); sectionName = document .selectSingleNode("/section/meta/sectionName").getText(); entityId = document.selectSingleNode("/section/meta/entityId") .getText(); } catch (DocumentException e) { e.printStackTrace(); } return new Section(entityId, sectionName, sectionXML); } } and is hooked up in the Spring Integration configuration file in the following way: To aggregate the Sections together into a report, the component is the following:: public class SectionResponseAggregator { public Report aggregate(List sections) { return new Report(sections); } } and is hooked up in the Spring Integration configuration file in the following way: This completes the Spring Integration implementation for this Integration Problem. The following is the complete Spring Integration configuration file: A working sample is provided with the article(Download, extract and run "mvn test") Solution using Apache Camel: Apache Camel allows the route to be defined using multiple DSL implementations – Java DSL, Scala DSL and an XML based DSL. The recommended approach is to use Spring CamelContext as a runtime and the Java DSL for route development. The following is to build the Spring Camel Context: The route is configured by the Java based DSL: public class CamelRouteBuilder extends RouteBuilder { private String serviceURL; @Override public void configure() throws Exception { from("direct:start") .split().method("sectionRequestSplitterBean", "split") .aggregationStrategy(new ReportAggregationStrategy()) .transform().method("sectionRequestToXMLBean", "transform") .to(serviceURL) .transform().method("sectionResponseXMLToSectionBean", "transform"); } public void setServiceURL(String serviceURL) { this.serviceURL = serviceURL; } } Apache Camel does not provide an out of the box Message Gateway feature, however it is fairly easy to create a wrapper component that can hide the underlying details in the following way: Reader davsclaus has provided references to two mechanisms with Apache Camel to provide an out of the box Messaging Gateway - Messaging Gateway EIP and Camel Proxy which allows a POJO to be used as a Mesaging Gateway. Camel Proxy will be used with the article, and can be configured in the Camel Configuration files in the following way: Per davsclaus, there is a bug in Apache Camel(2.1 or older) when invoking a bean later in the route(the splitter bean), which is to be fixed in Apache Camel 2.2. To work around this bug, a convertBody step will be introduced in the route: from("direct:start") .convertBodyTo(ReportRequest.class) .split(bean("sectionRequestSplitterBean", "split"), new ReportAggregationStrategy()) .transform().method("sectionRequestToXMLBean", "transform") .to(serviceURL) .transform().method("sectionResponseXMLToSectionBean", "transform"); The component to Split the Input Report Request to Section Request is exactly same as Spring Integration component: public class SectionRequestSplitter { public List split(ReportRequest reportRequest){ return reportRequest.getSectionRequests(); } } To hook the component with Apache Camel: from("direct:start") .split().method("sectionRequestSplitterBean", "split") .... Next to transform the Section Request to an XML format, again this is exactly same as the implementation for Spring Integration, with hook being provided in the following manner: ...... .transform().method("sectionRequestToXMLBean", "transform") ...... To send an XML over http request using the Section Request XML to a section Service: ...... .transform().method("sectionRequestToXMLBean", "transform") .to(serviceURL) ......... To transform the Section Response XML to a Section object, the component is exactly same as the one used with Spring Integration, with the following highlighted hook in the Camel route: ...... .transform().method("sectionResponseXMLToSectionBean", "transform"); To aggregate the Section responses together into a report, the component is a bit more complicated than Spring Integration. Apache Camel supports a Scatter/Gather pattern using a route of the following type: ...... .split().method("sectionRequestSplitterBean", "split") .aggregationStrategy(new ReportAggregationStrategy()) with an aggregation strategy being passed on to the Splitter, the aggregation strategy implementation is the following: public class ReportAggregationStrategy implements AggregationStrategy { @Override public Exchange aggregate(Exchange oldExchange, Exchange newExchange) { if (oldExchange == null) { Section section = newExchange.getIn().getBody(Section.class); Report report = new Report(); report.addSection(section); newExchange.getIn().setBody(report); return newExchange; } Report report = oldExchange.getIn().getBody(Report.class); Section section = newExchange.getIn().getBody(Section.class); report.addSection(section); oldExchange.getIn().setBody(report); return oldExchange; } } This completes the Apache Camel based implementation. A working sample for Camel is provided with the article - just download, extract and run "mvn test". Conclusion: Spring Integration and Apache Camel provide a simple and clean approach for the Integration problems in a typical enterprise. They are lightweight frameworks – Spring Integration builds on top of Spring portfolio and extends the familiar programming model for the Integration domain and is easy to pick up, Apache camel provides a good Java based DSL and integrates well with Spring Core, with a fairly gentle learning curve. The article does not recommend one product over the other but encourages the reader to evaluate and learn from both these frameworks. References: Spring Integration Website: http://www.springsource.org/spring-integration Apache Camel Website: http://camel.apache.org/ Spring Integration Reference: http://static.springsource.org/spring-integration/reference/htmlsingle/spring-integration-reference.html Apache Camel User Guide: http://camel.apache.org/user-guide.html Plug for my blog: http://biju-allandsundry.blogspot.com/
December 31, 2009
by Biju Kunjummen
· 102,449 Views · 3 Likes
article thumbnail
How to Create a Java EE 6 Application with JSF 2, EJB 3.1, JPA, and NetBeans IDE 6.8
Develop a web-based app based on technologies in the JEE6 specs such as Enterprise Java Beans 3.1 and JPA with the help of NetBeans IDE 6.8.
December 29, 2009
by Christopher Lam
· 723,501 Views · 3 Likes
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,164 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,472 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,562 Views · 1 Like
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,883 Views
article thumbnail
Integrating JBoss RESTEasy and Spring MVC
Building websites is a tough job. It's even tougher when you also have to support XML and JSON data services. Developers need to provide increasingly sophisticated AJAXy UIs. Marketing groups and other business units are becoming more savvy to the benefits of widgets and web APIs. If you're a Java developer who needs to implement those sexy features, you're likely going to accomplish that work with a dizzying variety of frameworks for web development, data access and business logic. The Spring Framework has a strong presence based on the premise of seamless (no pun intended) integration of all of those frameworks. The Spring framework integrates with a host of JEE standard technologies, such as EJBs and JSP. Spring MVC is a sub-project of the larger Spring Framework that has its own Controller API and also integrates other web development frameworks such as JSF, Struts and Tiles. While the Spring Framework also integrates with new JEE technologies as they develop, however, for a variety of reasons the Spring framework has not integrated with the tour de force JAX-RS standard which delivers an API for constructing RESTful services. There are six implementations of the JAX-RS standard, and each provides some level of integration with Spring. Most of those integrations work with the Spring framework proper, but don't take advantage of the benefits of Spring MVC. JBoss RESTEasy integrates with both the Spring Framework proper and also with the Spring MVC sub-project. In this article, we're going to explore how to use RESTEasy along with Spring MVC application. We'll deep dive into the internals of Spring MVC, we'll discuss JAX-RS and how they related to MVC web development. We'll also touch on quite a few technologies beyond Spring MVC and RESTEasy, including Jetty and maven. We're also going to discuss theoretical concepts relating to REST and Dependency Injection. This article has to cover quite a bit of ground and you'll be gaining quite a few tools you can use to develop complex web applications. If you follow this article, you'll be constructing an end-to-end web application, however, feel free to skim the article to find material that's relevant to you. REST and JAX-RS REST has been an increasingly trendy topic over the last three years. We as a development community have been looking at REST as an effective way to perform distributed programming and data-oriented services. In fact, the Java community's REST leaders got together and created a standard spec to standardize some RESTful ideas in JSR 311 - JAX-RS the Java API for XML and RESTful Services. The focus of JAX-RS was to create an API that Java developers could use to perform RESTful data exchanges. However, the Java community quickly saw the similarities between JAX-RS and MVC (Model View Control) infrastructures. James Strachan, a long time Java community member and open source contributor (to things like DOM4J, Groovy - he created the language, and recently the Apache Camel and CXF ESBs) suggested that JAX-RS as the one Java web framework to rule them all?. Jersey, the production ready JAX-RS reference implementation, has a built in JSP rendering mechanism. The RESTEasy community built a similar mechanism in HTMLEasy. The Jersey and and HTMLEasy approaches work well for simpler websites, but they don't solve some of the more complex needs of an application. If you want more complex functionality, you'll need a more sophisticated web-development platform, such as Spring MVC. A combination of Spring MVC and RESTEasy will have the following benefits compared to the simpler approaches: Session based objects Freedom of choice - chose the right tool for the job Spring MVC integrates with a whole bunch of MVC frameworks, including Spring MVC, Struts2 and now RESTEasy Spring MVC integrates with a whole bunch of View frameworks, including JSP, JSF, Tiles and much more Integrated AJAX components - the freedom of choice can make end-to-end AJAX calls a breeze, assuming you chose the appropriate framework More control over URL mapping This article tackles some more advanced topics. If you want some relevant background, we have a reference section at the end of this article. Before we take a look at code, let's take a more in depth view of Spring MVC. Spring MVC Spring MVC is broken down into three pluggable sub-systems: Handler Mapping - Map a URL to Spring Bean/Controller. Spring allows quite a few methods to perform this mapping. It can be based on the name of a Spring bean, it could be a URL to bean map, it could be based on an external configuration file or it could be based on annotations. Handler Mappings allow you to configure complex mappings without resorting to complex web.xml files. Handler Adapter - Invoke the Controller. Hander Adapters know what type of spring beans they can call and performs invocations on the types of beans it knows about. There are Handler Adapters for Spring MVC classic, spring @MVC, Struts, Struts2, Servlets, Wicket, Tapestry, DWR and more. View Mapping - Invoke the View. View Mappers know how to translate a logical view name produced by a Controller into a concrete View implementation. A name like "customers" may translate into any of the following technologies: JSP/JSTL, JSF, Velocity, FreeMarker, Struts Tiles, Tiles2, XSLT, Jasper Reports, XML, JSon, RSS, Atom, PDF, Excel, and more RESTEasy plugs into Spring MVC in all three sub-systems. JAX-RS Resources/Controllers are defined by annotations; therefore RESTEasy provides a ResteasyHandlerMapper that knows how to convert a URL to a RESTEasy managed JAX-RS controller method. Once RESTEasy determines which method to invoke, the ResteasyHandlerMapping performs the invocation. The invocation can either be an object, which invokes the default JAX-RS behavior which transforms the resulting Object to a Represetation such as XML or JSON. Additionally, you return a traditional Spring ModelAndView which can refer to a logical view name and a map of data to be rendered by the View. The default JAX-RS behavior creates a ResteasyView which uses JAX-RS's configurable MessageBodyReader and MessageBodyWriter transformation framework. RESTEasy can produce XML and JSON using JAXB, but can be configured to use other view technologies such as Jackson, which is a performant and flexible JSON provider, Flex AMF. This separation of Controller and View concepts allows you to mix and match your Controller and View technologies. RESTEasy Resources can call any Spring managed Views and other Controller technologies can be rendered by a ResteasyView. You can either use RESTEasy as your sole MVC framework, if it fits your needs, or you can augment an existing Controller infrastructure with data services provided by RESTEasy. Just as importantly, you can leverage all of the other functionality that Spring provides, such as DAO abstraction, transaction management and AOP. Your First SpringMVC/RESTEasy Application Before we start reviewing the project, let's review a quick checklist of items we will be reviewing. The project files fall into two categories: configuration and source code. All of the code that will be covered is available in the RESTEasy repository and can be downloaded (as a tar.gz file), or browsed. Here is a list of files that each category will require. Configuration Files: web.xml - servlet configuration with Spring MVC artifacts - Spring MVC's DispatcherServlet, and map to /contacts/* springmvc-servlet.xml - a Spring application context configuration with all of the Spring beans this project needs, including RESTEasy setup (one line) and JSP configuration pom.xml - maven 2 dependency configuration, including required repositories, RESTEasy dependencies and embedded Jetty setup Source Code: The code we're going to show you can be broken down into four layers: Controller - Controlling the flow between the HTTP request, the Model and the View ContactsResource.java - a RESTful Controller with JAX-RS annotations and some traditional HTML controller methods. It will be annotated with Spring's @Controller and @Autowired annotations as well. Model - the domain model and service objects in our case. In our case, we have 2 domain objects: Contact and Contacts; and 1 Service object: ContractService Contact.java - a JAXB domain object with contact information Contacts.java - a JAXB wrapper object that wraps a Contact List ContactService.java - a Map based repository of Contact instances View - How the domain model is transformed for consumer use. JAX-RS performs automated conversion to XML based on annotations on our domain model. We'll be using JSP for object to HTML conversion. contacts.jsp - a bare bones HTML view of our Contacts Test - JAX-RS provides quite a bit of functionality, we're writing quite a bit of code, and all of that is wrapped in quite a bit of configuration. This article will focus on testing our code, configuration and deployment in an automated JUnit test. ContractTest.java - a RESTEasy ReSTful Unit test for the ContractsResource functionality, embedded server included There's a lot of ground to cover, and we'll cover the most interesting pieces of the source first. Our first pass will cover the web.xml and springmvc-servlet.xml configuration files as well as the ContactsResource.java and ContactTest.java source files. Our second pass will cover the remaining topics. Core RESTEasy/Spring MVC artifacts web.xml Spring MVC's entry point is the DispatcherServlet. There are two parts in setting up the DispatcherServlet, the first is to map the servlet to the URL pattern which must follow the rules specified in Section 11.2 of Servlet API Specification. The next step is configure the behavior of the the servlet by providing the configuration file which we call 'springmvc-servlet.xml'. By default, DispatcherServlet looks for a configuration file at "WEB-INF/{servlet-name}-servlet.xml" to find it's configuration, but we're going to use a Spring configuration from the classpath so that the configuration can be reused later in our junit test case. springmvc org.springframework.web.servlet.DispatcherServlet contextConfigLocation classpath:springmvc-servlet.xml springmvc /contacts/* All requests will be forwarded to the Spring MVC DispatcherServlet. One can get much more sophisticated, but this is one of the simplest simplest web.xml you can create to integrate with Spring. Note that there isn't any reference here to a RESTEasy servlet. Other JAX-RS/Spring integrations require you to have an implementation specific Servlet to serve XML or JSon and a separate Spring MVC DispatcherServlet mapping to server HTML requests. RESTEasy integrates with DispatcherServlet to allow Spring MVC to direct the URL to either RESTEasy Resources or Spring MVC Controllers. Next, let's take a look at the Spring MVC configuration. springmvc-servlet.xml In our basic project, there are five things we need to do in the springmvc-servlet.xml file. Register the Spring namespace Register the package(s) to scan for Spring MVC annotations. Configure the context annotation processor. Import the springmvc-resteasy.xml configuration file which specifies the default RESTEasy/Spring MVC integration Spring beans. Configure the ViewResolver bean to configure the presentation layer to use JSP. Let's inspect the springmvc-servlet.xml file and focus on each of the above items. The springmvc-servlet.xml file itself is pretty short and shows off some of the features from Spring 2.5: Demystifying the Spring Configuration Spring allows for custom namespaces to reduce the verbosity of the configuration files. We make use of the namepsace by registering it in lines 3 and 4. Line 6 (component-scan) informs spring about which package(s) we want to scan and create the custom component object instances, such as controllers and service objects. We tell Spring about the packages we're interested in by using the custom namespace and set the base-package attribute with the packages we're interested in (org.jboss.resteasy.examples.springmvc ). Later on, you'll see that we're going to be using two Spring annotations that allow the Spring runtime to glean Dependency Management information directly from the object itself: @Controller and @Service. Line 7 (annotation-config) tells Spring that our application will be using annotations on how to configure the beans created by the (component-scan) operation of line 6. Spring looks for annotations such as Spring's @Autowired and @Required; JEE's @Resource; and JPA's @PersistenceContext and @PersistenceUnit to describe dependencies between bean instances. annotation-configSpring also looks for life-cycle annotations such as JSR 250's @PostConstruct and @PreDestroy. Our environment requires a dependency between our Controller and Service objects, and the annotation-config declaration will assist us to configure that relationship in Java code. Line 8 (import) is all the XML that is necessary to configure a RESTEasy environment in Spring MVC. The nice thing about the integration with RESTEasy is that most of the configuration is done for you within an embedded configuration file called springmvc-resteasy.xml. Lines 9-14 tell Spring how we intend to handle the rendering of our presentation layer. In our case, we want to use JSTL views that translate view names (such as "contact") to a JSP page found in the /WEB-INF/ directory (specifically /WEB-INF/contacts.jsp in our case). For more information about setting up Spring views, take a look at the spring documentation. Next, let's take a look at how you can mix and match Spring and JAX-RS annotations in a Controller/Resource. ContactsResource.java MVC Controllers control the flow between the Model and the View. Resource is REST's equivalent to Controllers, and we'll be using the term Resource and Controller interchangably. In our case, our resource handles requests to /contracts and /contracts/{id}. Our ContractsResource must perform quite a few functions on those two URL templates: Retrieve all Contacts - Display the results in either HTML, XML or JSon. For clarity, we'll break out the data oriented functionality (XML and JSon) from the user oriented functionality (HTML) into two distinct URLs - /contacts for HTML and /contacts/data for XML and JSon. REST allows a client to select which format it prefers to receive the data in through a process called Content Negotiation. Content Negotiation can happen through HTTP headers, URI or query parameters. Our ContractsResource will use different URIs to differentiate between data oriented and user views, and will use HTTP headers to differentiate between XML and JSon data views. Save a Contact - Create or Updating data is a pretty standard requirement. The Save a Contact functionality mirrors the Content Negotiation needs of Retrieve all Contacts. User oriented data exchange comes in the form of HTML form data, and data oriented exchange usually occurs in XML and JSon. These differing requirements require ContractResource to have two distinct JAX-RS Java methods; we'll also separate the URLs for clarity purposes. View a Contact - We'll create a single view for viewing a single contact that returns XML or JSon. We leave the user oriented view as an exercise for the reader. Here's another view of our requirements: Functionality URL Format Java Method User Oriented View All /contacts HTML viewAll() Data Oriented View All /contacts/data XML or JSon getAll() User Oriented Save /contacts/ Form data saveContactForm() Data Oriented Save /contacts/data XML or JSon saveContact() Data Oriented View Single /contacts/data/{lastName} XML or JSon get() Note that we mixed and matched HTML and data oriented functionality in this requirement. Now that we have our requirements in place, let's take a look at the ContactsResource code. There are quite a few new Spring and JAX-RS annotations which we'll explain right after the code: @Controller @Path(ContactsResource.CONTACTS_URL) public class ContactsResource { public static final String CONTACTS_URL = "/contacts"; @Autowired ContactService service; @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("data") public Contacts getAll() { return service.getAll(); } @GET @Produces(MediaType.TEXT_HTML) public ModelAndView viewAll() { // forward to the "contacts" view, with a request attribute named // "contacts" that has all of the existing contacts return new ModelAndView("contacts", "contacts", service.getAll()); } @PUT @POST @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("data") public Response saveContact(@Context UriInfo uri, Contact contact) throws URISyntaxException { service.save(contact); URI newURI = UriBuilder.fromUri(uri.getPath()).path(contact.getLastName()).build(); return Response.created(newURI).build(); } @POST @PUT @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.TEXT_HTML) public ModelAndView saveContactForm(@Form Contact contact) throws URISyntaxException { service.save(contact); return viewAll(); } @GET @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Path("data/{lastName}") public Contact get(@PathParam("lastName") String lastName) { return service.getContact(lastName); } } This code is packed with annotations and Java code that's indicative of JAX-RS Resources and Spring applications. There is also a RESTEasy custom annotation. The Spring IoC annotations are well documented, but we are using them in unusual ways for our integration: @Controller tells the Spring runtime that it needs to create an instance of ContractsResource at startup time. Do you remember the component-scan directive that was used in the Spring configuration section? The combination of the directive and the annotation tell Spring that a singleton instance of ContractsResource must be created at startup. Spring has a more generic @Component, but the use of @Controller allows for more precise definition of bean usage and also allows for future upgrades that involve AoP to create more precise targeting. While @Controller is usually associated with Spring @MVC annotated controllers and not other Controller infrastructures, but even thought it's not a Spring MVC controller, we use it to tell Spring that this indeed is a Controller That association of @Controller to Spring MVC annotated controllers is a loose coupling in the Spring runtime. We'll use JAX-RS annotations to configure the handling of URL and HTTP handling behavior. You could theoretically add additional Spring @MVC annotations such as @RequestMapping (which is an equivalent of JAX-RS @Path) to our ContactsResource, if you really wanted to @Autowired tells the Spring runtime that instances of ContractResource require an instance of ContactService. We'll be coding the ContactService later in this article. You can take a look at the Spring reference documentation for more information about @Autowired and @Controller. The last Spring artifact that we use is ModelAndView: It is Spring MVC's encapsulation of which logical View to use and which Model variables should be passed into the View. In our case, we're going to create a Model variable called "contacts" that is a List of all Contact objects we have in the system. We're passing that variable to the a logical view named "contacts" which will map to "/WEB-INF/contacts.jsp" based on the Spring configuration that we previously discussed. The JAX-RS annotations are also well documented, but it's definitely worth while to give a brief overview: @Path tells the RESTEasy (or other JAX-RS environments) how to map URLs to java methods. Adding @Path at the class level tells, in our case "/contacts", indicates that all methods must be prefixed with that URL. The @Path value can either be a hard coded URL such as "/contacts" or it can be a URI template such as "data/{lastName}". You can even specify regular expressions for more sophisticated filtering in the URI template. @GET, @PUT and @POST are used in combination with @Path to indicate which specific HTTP methods are handled by individual Java methods @Produces and @Consumes are used to further filter how a request should be handled based on content negotiation based on the Accept and Content_Type HTTP header. JAX-RS provides a set of default mime type values in the MediaType class. @PathParam is a method parameter annotation that indicates how a URI template variable is mapped to a method parameter. There are quite a few other method parameter level annotations that you could use to map HTTP headers, cookies, query parameters and form parameters to member variables @Context is an interesting JAX-RS parameter that allows dependency injection of request level information such as HttpRequest, HttpResponse and UriInfo (which as you can probably guess encapsuldates information about the request URI). It's important to note that Spring by default manages beans such as ContactsResource as a singleton; if ContactsResource was a Prototype or Request scoped bean, you would be able to use the @Context annotation on member variables in addition to method variables. For more on Spring scoping see the Spring Framework documentation. The last annotation we need to talk about is @Form. It's a RESTEasy custom annotation that describes that a member variable encapsulates data from HTML forms. If you recall, we used the JAX-RS @FormParam annotation on our Contact domain object. @Form and @FormParam are used in concert to allow for better maintenance of form based processing systems. JAX-RS 2.0's stated goals include a more robust, uniform Form processing annotation system. The functionality to code ratio is pretty high because of all of the declarative coding conventions of these annotations. Now that we've discussed the most involved pieces of the puzzle, let's take a look at completing the project. Additional Artifacts pom.xml Our pom.xml includes dependency management, description of required Maven repositories, a description of which JDK we're going to use and a Jetty web server configuration. We'll cover the repository selection, the dependencies specific to RESTEasy and a jetty-maven integration External Repositories jboss jboss repo http://repository.jboss.org/maven2 scannotation http://scannotation.sf.net/maven2 java.net http://download.java.net/maven/1 legacy maven repo maven repo http://repo1.maven.org/maven2/ Project Dependencies Now that we've informed Maven which additional repositories are required, we can now include the dependencies the our sample project will require. The section of the pom.xml file, should include the following two dependencies for Spring and RESTEasy functionality - resteasy-spring and resteasy-jaxb-provider: org.jboss.resteasy resteasy-spring 1.2.RC1 org.jboss.resteasy resteasy-jaxb-provider 1.2.RC1 org.mortbay.jetty maven-jetty-plugin 6.1.15 test The resteasy-spring dependency includes the adapter that integrates RESTEasy into Spring's MVC and provides most the required Java dependencies for RESTEasy and Spring. It also contains Spring configuration needed within the embedded spring-resteasy.xml file that will be used in the Spring configuration section. The other RESTEasy dependency that's included, resteasy-jaxb-provider, contains classes that convert the payload into various formats before sending it to the client. The last dependency to focus on is the maven-jetty-plugin which allows us to easily startup our project in a Jetty webserver environment. Note: If you're follow the link above to the RESTEasy repository's version of pom.xml, you will have to modify the version of resteasy-spring and resteasy-jaxb-provider to the latest version that has been deployed, specifically 1.2.RC1 at the time this article was written. The RESTEasy repository contains a soon-to-be-deployed version number which will not work unless you build the entire RESTEasy project. Maven Jetty Plugin One last interesting item of pom.xml is the configuration of the Jetty web server resteasy-springMVC org.mortbay.jetty maven-jetty-plugin 6.1.15 / 2 ... This will allow us to startup Jetty against localhost:8080. You can learn more about the maven Jetty plugin and a variety of configuration options. Let's start with the domain model and move on to the service object. From there, we'll discuss the JAX-RS Resource/Controller. From there, we'll explore the unit test and finally we'll write the JSP View and start up our server. Contact.java Our DTO is going to be deceptively simple. It will perform a dual responsiblity of JAXB XML binding and Form parameter binding. Both sets of functionality will be configured through annotations and will be managed through JAXB and JAX-RS: import javax.ws.rs.FormParam; import javax.xml.bind.annotation.XmlRootElement; @XMLRootElement public class Contact { private String firstName, lastName; // default constructor for JAXB (also required by JPA/Hibernate if you use them) public Contact(){} // helper constructor for our Controller/Service operations public Contact(String firstName, String lastName){ this.firstName = firstName; this.lastName = lastName; } @FormParam("firstName") public void setFirstName(String firstName) { this.firstName = firstName; } public String getFirstName() { return firstName; } @FormParam("lastName") public void setLastName(String lastName) { this.lastName = lastName; } public String getLastName() { return lastName; } // equals and hasCode are added for the Map based Service object public boolean equals(Object other){ .. } public long hashCode(){ .. } } The annotation on the setters tells JAX-RS to bind any incoming form parameters to the appropriate setter. The @XMLRootElement annotation is enough to tell JAXB that the Contract object must be bound to getters and setters must be bound to an XML document that will look like: Richard Burton Contacts.java The Contacts class is a simple wrapper around a List of Contact instances: @XmlRootElement public class Contacts { private Collection contacts; public Contacts() { this.contacts = new ArrayList(); } public Contacts(Collection contacts) { this.contacts = contacts; } @XmlElement(name="contact") public Collection getContacts() { return contacts; } public void setContacts(Collection contact){ this.contacts = contact; } } Contacts has the @XmlRootElement, just like Contact. The @XmlRootElement annotation tells JAXB to transform objects of this type to an XML structure that has as its top level element. In addition, we've added the @XmlElement annotation to the getContacts() method. By default, JAXB renders all JavaBean elements and uses the JavaBean name as the element. JAXB handles Lists as special cases: all List elements are translated to XML elements using the JavaBean name. @XmlElement(name="contact") tells JAXB that we opted to override the default name ("contracts") in favor of our own name ("contract" - no 's'). The Contracts object will bind to XML that looks like: Richard Burton Solomon Duskis Now that we have our Domain model in place, let's start using it in our Service tier. ContactService.java Since the purpose of this article is JAX-RS centric, we're not going to create an elaborate service layer, but we'll add once since creating more robust Spring applications do require service or data access layers. If you're interested in seeing a RESTEasy/Spring application with database access, look here. Our ContractService performs simple in-memory storage of Contacts by last name: @Service public class ContactService { private Map contactMap = new ConcurrentHashMap(); public void save(Contact contact){ contactMap.put(contact.getLastName(), contact); } public Contact getContact(String lastName){ return contactMap.get(lastName); } public Contacts getAll() { return new Contacts(contactMap.values()); } } There are two items of interest that are noteworthy: Notice the use of Spring's @Service annotation. Do you remember the component-scan directive that was used in the Spring configuration section? The combination of the directive and the annotation tell Spring that a singleton instance of ContractService must be created at startup. Spring has a more generic @Component, but the use of @Service allows for more precise definition of bean usage and also allows for future upgrades that involve AoP to create more precise targeting. Notice the use of ConcurrentHashMap. It's a JDK 1.5 addition that adds performance in multi-threaded environments. It's an easy way to boost performance in distributed REST applications Next, let's take a look at the JSP that contacts.jsp We've explored the Model and Controller aspects of MVC. The last piece to the puzzle is the View. Most JAX-RS based interactions perform a more automated conversion of objects like our Contact to a data-oriented view, such as XML or JSon. Traditionally, Java EE MVC has been done with a more manual View management with languages such as JSP. Our JSP will take a Contracts instance created in ContractsResources.viewAll() and render it in basic HTML: Hello Contacts! Hello ${contact.firstName} ${contact.lastName} Save a contact, save the world: First Name: Last Name: This JSP loops over all contacts and adds links to their data-oriented View. It also creates a simple HTML form for creating a new Contact. While this JSP is simple, it will help us exercise three of our ContactsResource Controller: viewAll(), .saveContactForm(), and get(). It could also be a spring board for more complicated AJAX/JSon interaction, but that's beyond the scope of this article. The code and configuration is now complete, so let's run this project! Jetty Running Jetty is rather simple. You've seen most of the details of the pom.xml when we previously discussed it. Running jetty through maven involves running the following command: mvn jetty:run (If you haven't done so already, download the file as a tar ball, and change the pom.xml's version of the two RESTEasy dependencies to 1.2.RC1) That command will launch Jetty, and allow you to browse our project at http://localhost:8080/contacts. Add a few contacts, and view them either as a group at /contacts in HTML, as a group in XML at /contact/data, or individually as XML by following the links found at /contacts. Congratulations. You now have a running Spring MVC/RESTEasy application. We need one more thing to consider this application complete: a JUnit test. ContractTest.java RESTEasy provides a mechanism for easily launching a Spring MVC/RESTEasy application. RESTEasy also comes with a robust REST client framework. This article will cover bits and pieces of the test, but you can view the entire code in the RESTEasy SVN. To start, we're going to set up an interface that the RESTEasy client can use to create a client for our application. It consists of abstract methods annotated with JAX-RS annotations: @Path(ContactsResource.CONTACTS_URL) public interface ContactProxy { @Path("data") @POST @Consumes(MediaType.APPLICATION_XML) Response createContact(Contact contact); @GET @Produces(MediaType.APPLICATION_XML) Contact getContact(@ClientURI String uri); @GET String getString(@ClientURI String uri); } All methods on ContactProxy inherit the ContactsResource.CONTACTS_URL path ("/contacts") as the root URL, just like a server-side JAX-RS resource. This interface's has three methods: Create a contact - the createContact method maps to a POST to "/contacts/data". The method accepts a Contact object which will be converted to XML before it's sent to the server. The result is a JAX-RS Response object which contains the response status and headers. One of those headers includes the LOCATION of the new contact Get an XML Contact - Given a URL to a Contact, such as the URL returned by the createContact method's response's LOCATION header, GET an XML response and create a Contact object from it. Get a Response as a String - Given a URL, such as a Contact URL or anything else on the server, retrieve a String result. This interface will be used by RESTEasy to construct a concrete instance that uses the JAX-RS annotations to perform the actual HTTP calls. Next, let's create the embedded server and use RESTEasy to create that instance of a ContactProxy: private static ContactProxy proxy; private static TJWSEmbeddedSpringMVCServer server; public static final String host = "http://localhost:8080/"; @BeforeClass public static void setup() { server = new TJWSEmbeddedSpringMVCServer("classpath:springmvc-servlet.xml", 8080); server.start(); RegisterBuiltin.register(ResteasyProviderFactory.getInstance()); proxy = ProxyFactory.create(ContactProxy.class, host); } @AfterClass public static void end() { server.stop(); } JUnit invokes methods annotated by @BeforeClass before any test methods run. Methods annotated by @AfterClass are triggered by JUnit before after all test methods are complete. In our case, the setup method will instantiate a server that contains a SpringMVC Servlet on port 8080 that is configured by the same Spring XML configuration file we used in Jetty. It also invokes the two lines of code required to create a RESTEasy client. RegisterBuiltin sets up the RESTEasy run time, and must be run one time per client. ProxyFactory.create tells RESTEasy to read the annotations on the ContactProxy interface and to create a Java Proxy instance that knows how to perform the HTTP requests we'll need for our test: @Test public void testData() { Response response = proxy.createContact(new Contact("Solomon", "Duskis")); String duskisUri = (String) response.getMetadata().getFirst(HttpHeaderNames.LOCATION); Assert.assertTrue(duskisUri.endsWith(ContactsResource.CONTACTS_URL + "/data/Duskis")); Assert.assertEquals("Solomon", proxy.getContact(duskisUri).getFirstName()); ... } This test creates a new Contact, checks the server's response to make sure that the URL is consistent with the test's expectations. It then re-retrieves the Contact and confirms that the firstName is indeed what was sent sent in. While this is a pretty trivial looking test, it performs quite a bit of HTTP activity and business logic. Conclusion This article discussed quite a bit of philosophy and design considerations in building a RESTful web application with RESTEasy and Spring MVC. We also built an end to end application with RESTEasy, Spring MVC, Maven, Jetty and JUnit. Even though the content in this article was significant, the code presented here is relatively short compared to other Java alternatives. We touched on subjects like designing REST Applications, creating Spring applications, the RESTEasy client infrastructure and testing RESTful applications. Each of those subjects merit their own articles. There were also other subjects that we simply couldn't fit into this article (as long as it is), including JavaScript to the toolkit to allow closer integration between the browser and your RESTful application, integrating with Flex and more. The code presented in this article can serve as a spring board (again, no pun intended) for all of those ideas. About the Authors Solomon Duskis Solomon Duskis is a Senior Manager at SunGard Consulting Services. He's been developing for 22 years -- 12 years in professional capacity. He has experience in various industries such as Finance, Media, Insurance and Health. He contributes to Open Source projects such as JBoss Resteasy and the Spring framework. He is a published author of Spring Persistence - A Running Start, and the upcoming book Spring Persistence with Hibernate. Richard Burton Richard Burton is the co-founder of a small independent consulting firm called SmartCode LLC. He is an Open Source fanatic with over 10 years of experience in various industries such as Automotive, Insurance, Finance and fondly remembers the .com era. In his spare time, he contributes to Open Source projects such as SiteMesh 3, Struts 2, and more. Reference REST Roy Fielding's REST Thesis - Architectural Styles and the Design of Network-based Software Architectures(December 2000) Bill Burke's (August 2008 - DZone) How to GET a cup of coffee (October 2008 - InfoQ) Roy Fielding REST APIs Must Be Hypertext Driven (October 2008 - Untagled Roy's blog - take a look at the URI: roy.gbiv.com ) JAX-RS Bill Burke's (September 2008 - DZone) An overview of JAX-RS 1.0 Features James Strachan's JAX-RS as the one Java web framework to rule them all? (January 2009 - James' blog) RESTEasy RESTEasy project A blog about Spring + RESTEasy Getting Started with RESTEasy Spring Spring 2.5 reference Oh, just search google for "spring framework" Spring MVC Spring MVC Reference Spring MVC Step By Step Spring MVC Tutorial
October 15, 2009
by Solomon Duskis
· 141,440 Views · 1 Like
article thumbnail
Managing Eclipse RCP Launch Arguments
in my last post i discussed how to best manage run configurations for eclipse rcp applications . but there was one related topic i wanted to discuss in more detail, and that is how to manage launch arguments. what are launch arguments? launch arguments are arguments that are added to the command line when you execute your application. these arguments come in two flavors: program arguments – arguments that are eclipse-specific. for example, the -clean argument will clear the configuration area on startup. vm arguments – arguments that make sense to the java vm. for example, the -xmx argument allows you to set the maximum heap size for the vm. both of these argument types can be set on the arguments tab in the run configurations dialog. launch arguments and the target platform we oftentimes want to apply the same launch arguments to all of our run configurations, and one way to handle that is to specify them on your target platform . on the target platform preference page there is a section where you can add whatever arguments you wish. the arguments associated with a target platform will be added to run configurations generated from the manifest editor . they will not be added to configurations generated by the product configuration editor. also, because the manifest editor link does not regenerate a configuration each time, you will need to explicitly delete a configuration if you want to recreate it using new target platform arguments. launch arguments and products a second way to manage arguments is to add them using the launching tab of the product configuration editor. when you add arguments in this way, two things will happen: the arguments will be added to your run configurations if you launch using the link in the product configuration editor . because this link regenerates the run configuration each time, consistent use of the link guarantees that your configuration is in synch with your product definition. the arguments will also be added to your deployed application in the form of an ini file. this is a nice feature, but it means that you need to be careful when adding arguments that are only useful during development. for example, you may want to use -clean to clear the configuration area when you’re developing, but you probably do not want to ship this argument to your customers. launch arguments best practices my approach is to add arguments using the product configuration editor and to always launch my applications using the link in that editor. this guarantees that my run configurations are always in synch with my product definition. i also take care to not add arguments that would be detrimental to a deployed application. some, such as -consolelog, i consider harmless in a deployed app and i just leave those in. if for some reason i absolutely have to add an argument that should not be deployed, i usually clean it out of the ini file during the build process. it’s pretty rare for me to have to do this, though. from http://www.modumind.com
September 9, 2009
by Patrick Paulin
· 10,907 Views
article thumbnail
Spring Integration: A Hands-On Tutorial, Part 1
This tutorial is the first in a two-part series on Spring Integration. In this series we're going to build out a lead management system based on a message bus that we implement using Spring Integration. Our first tutorial will begin with a brief overview of Spring Integration and also just a bit about the lead management domain. After that we'll build our message bus. The second tutorial continues where the first leaves off and builds the rest of the bus. I’ve written the sample code for this tutorial as a Maven 2 project. I’m using Java 5, Spring Integration 1.0.3 and Spring 2.5.6. The code also works for Java 6. I've used Maven profiles to isolate the dependencies you’ll need if you’re running Java 5. The tutorials assume that you're comfortable with JEE, the core Spring framework and Maven 2. Also, Eclipse users may find the m2eclipse plug-in helpful. To complete the tutorial you'll need an IMAP account, and you'll also need access to an SMTP server. Let's begin with an overview of Spring Integration. A bird's eye view of Spring Integration Spring Integration is a framework for implementing a dynamically configurable service integration tier. The point of this tier is to orchestrate independent services into meaningful business solutions in a loosely-coupled fashion, which makes it easy to rearrange things in the face of changing business needs. The service integration tier sits just above the service tier as shown in figure 1. Following the book Enterprise Integration Patterns by Gregor Hohpe and Bobby Woolf (Addison-Wesley), Spring Integration adopts the well-known pipes and filters architectural style as its approach to building the service integration layer. Abstractly, filters are information-processing units (any type of processing—doesn’t have to be information filtering per se), and pipes are the conduits between filters. In the context of integration, the network we’re building is a messaging infrastructure—a so-called message bus—and the pipes and filters and called message channels and message endpoints, respectively. The network carries messages from one endpoint to another via channels, and the message is validated, routed, split, aggregated, resequenced, reformatted, transformed and so forth as the different endpoints process it. Figure 1. The service integration tier orchestrates the services below it. That should give you enough technical context to work through the tutorial. Let’s talk about the problem domain for our sample integration, which is enrollment lead management in an online university setting. Lead management overview In many industries, such as the mortgage industry and for-profit education, one important component of customer relationship management (CRM) is managing sales leads. This is a fertile area for enterprise integration because there are typically multiple systems that need to play nicely together in order to pull the whole thing off. Examples include front-end marketing/lead generation websites, external lead vendor systems, intake channels for submitted leads, lead databases, e-mail systems (e.g., to accept leads, to send confirmation e-mails), lead qualification systems, sales systems and potentially others. This tutorial and the next use Spring Integration to integrate several of systems of the kind just mentioned into an overall lead management capability for a hypothetical online university. Specifically we’ll integrate the following: • a CRM system that allows campus and call center staff to create leads directly, as they might do for walk-in or phone-in leads • a Request For Information (RFI) form on a lead generation ("lead gen") marketing website • a legacy e-mail based RFI channel • an external CRM that the international enrollment staff uses to process international leads • confirmation e-mails Figure 2 shows what it will look like when we’re done with both tutorials. For now focus on the big picture rather than the details. Figure 2. This is the lead management system we'll build. For this first tutorial we're simply going to establish the base staff interface, the (dummy) backend service that saves leads to a database, and confirmation e-mails. The second tutorial will deal with lead routing, web-based RFIs and e-mail-based RFIs. Let's dive in. We’ll begin with the basic lead creation page in the CRM and expand out from there. Building the core components [You can download the source code for this section of the tutorial here] We’re going to start by creating a lead creation HTML form for campus and call center staff. That way, if walk-in or phone-in leads express an interest, we can get them into the system. This is something that might appear as a part of a lead management module in a CRM system, as shown in figure 3. Figure 3. We'll build our lead management module with integration in mind from the beginning. Because we’re interested in the integration rather than the actual app features, we’re not really going to save the lead to the database. Instead we’ll just call a createLead() method against a local LeadService bean and leave it at that. But we will use Spring Integration to move the lead from the form to the service bean. Our first stop will be the domain model. DZone readers get 30% off Spring in Practice by Willie Wheeler and John Wheeler. Use code dzone30 when checking out with any version of the book at www.manning.com. Create the domain model We’ll need a domain object for leads, so listing 1 shows the one we’ll use. It’s not an industrial-strength representation, but it will do for the purposes of the tutorial. Listing 1. Lead.java, a basic domain object for leads. package crm.model;... other imports ...public class Lead { private static DateFormat dateFormat = new SimpleDateFormat(); private String firstName; private String middleInitial; private String lastName; private String address1; private String address2; ... other fields ... public Lead() { } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } ... other getters and setters, and a toString() method ...} There is nothing special happening here at all. So far the Lead class is just a bunch of getters and setters. You can see the full code listing in the download. If you thought that was underwhelming, just wait until you see the LeadServiceImpl service bean in listing 2. Listing 2. LeadServiceImpl.java, a dummy service bean. package crm.service;import java.util.logging.Logger;import org.springframework.stereotype.Service;import crm.model.Lead;@Service("leadService")public class LeadServiceImpl implements LeadService { private static Logger log = Logger.getLogger("global"); public void createLead(Lead lead) { log.info("Creating lead: " + lead); } This is just a dummy bean. In real life we’d save the lead to a database. The bean implements a basic LeadService interface that we've suppressed here, but it's available in the code download. Now that we have our domain model, let’s use Spring Integration to create a service integration tier above it. Create the service integration tier If you look back at figure 3, you’ll see that the CRM app pushes lead data to the service bean by way of a channel called newLeadChannel. While it’s possible for the CRM app to push messages onto the channel directly, it’s generally more desirable to keep the systems you’re integrating decoupled from the underlying messaging infrastructure, such as channels. That allows you to configure service orchestrations dynamically instead of having to go into the code. Spring Integration supports the Gateway pattern (described in the aforementioned Enterprise Integration Patterns book), which allows an application to push messages onto the message bus without knowing anything about the messaging infrastructure. Listing 3 shows how we do this. Listing 3. LeadGateway.java, a gateway offering access to the messaging system. package crm.integration.gateways;import org.springframework.integration.annotation.Gateway;import crm.model.Lead;public interface LeadGateway { @Gateway(requestChannel = "newLeadChannel") void createLead(Lead lead);} We are of course using the Spring Integration @Gateway annotation to map the method call to the newLeadChannel, but gateway clients don’t know that. Spring Integration will use this interface to create a dynamic proxy that accepts a Lead instance, wraps it with an org.springframework.integration.core.Message, and then pushes the Message onto the newLeadChannel. The Lead instance is the Message body, or payload, and Spring Integration wraps the Lead because only Messages are allowed on the bus. We need to wire up our message bus. Figure 4 shows how to do that with an application context configuration file. Listing 4. /WEB-INF/applicationContext-integration.xml message bus definition. The first thing to notice here is that we've made the Spring Integration namespace our default namespace instead of the standard beans namespace. The reason is that we're using this configuration file strictly for Spring Integration configuration, so we can save some keystrokes by selecting the appropriate namespace. This works pretty nicely for some of the other Spring projects as well, such as Spring Batch and Spring Security. In this configuration we've created the three messaging components that we saw in figure 3. First, we have an incoming lead gateway to allow applications to push leads onto the bus. We simply reference the interface from listing 3; Spring Integration takes care of the dynamic proxy. Next we create a publish/subscribe ("pub-sub") channel called newLeadChannel. This is the channel that the @Gateway annotation referenced in listing 3. A pub-sub channel can publish a message to multiple endpoints simultaneously. For now we have only one subscriber—a service activator—but we already know we're going to have others, so we may as well make this a pub-sub channel. The service activator is an endpoint that allows us to bring our LeadServiceImpl service bean onto the bus. We're injecting the newLeadChannel into the input end of the service activator. When a message appears on the newLeadChannel, the service activator will pass its Lead payload to the leadService bean's createLead() method. Stepping back, we've almost implemented the design described by figure 3. The only part that remains is the lead creation frontend, which we'll address right now. Create the web tier Our user interface for creating new leads will be a web-based form that we implement using Spring Web MVC. The idea is that enrollment staff at campuses or call centers might use such an interface to handle walk-in or phone-in traffic. Listing 5 shows our simple @Controller. Listing 5. LeadController.java, a @Controller to allow staff to create leads package crm.web;import java.util.Date;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import crm.integration.gateways.LeadGateway;import crm.model.Country;import crm.model.Lead;@Controllerpublic class LeadController { @Autowired private LeadGateway leadGateway; @RequestMapping(value = "/lead/form.html", method = RequestMethod.GET) public void getForm(Model model) { model.addAttribute(Country.getCountries()); model.addAttribute(new Lead()); } @RequestMapping(value = "/lead/form.html", method = RequestMethod.POST) public String postForm(Lead lead) { lead.setDateCreated(new Date()); leadGateway.createLead(lead); return "redirect:form.html?created=true"; } This isn't an industrial-strength controller as it doesn't do HTTP parameter whitelisting (for example, via an @InitBinder method) and form validation, both of which you would expect from a real implementation. But the main pieces from a Spring Integration perspective are here. We're autowiring the gateway into the @Controller, and we have methods for serving up the empty form and for processing the submitted form. The getForm() method references a Countries class that we've suppressed (it's in the code download); it just puts a list of countries on the model so the form can present a Country field to the staff member. The postForm() method invokes the createLead() method on the gateway. This will pass the Lead to the dynamic proxy LeadGateway implementation, which in turn will wrap the Lead with a Message and then place the Message on the newLeadChannel. There are a few other configuration files you will need to put in place, including web.xml, main-servlet.xml and applicationContext.xml. There's also a JSP for the web form. As none of these relates directly to Spring Integration, we won't treat them here. Please see the code download for details. With that, we've established a baseline system. To try it out, run mvn jetty:run against crm/pom.xml and point your browser at http://localhost:8080/crm/main/lead/form.html You should see a very basic-looking web form for entering lead information. Enter some user information (it doesn't matter what you enter—recall that we don't have any form validation) and press Submit. The console should report that LeadServiceImpl.createLead() created a lead. Congratulations! Even though we now have a working system, it isn't very interesting. From here on out (this tutorial and the next) we'll be adding some common features to make the lead management system more capable. Our first addition will be confirmation e-mails; the next tutorial will present further additions. Adding confirmation e-mails [The source for this section is available here] After an enrollment advisor (or some other staff member) creates a lead in the system, we want to send the lead an e-mail letting him know that that's happened. Actually—and this is a critical point—we really don't care how the lead was created. Anytime a lead appears on the newLeadChannel, we want to fire off a confirmation e-mail. I'm making the distinction because it points to an important aspect of the message bus: it allows us to control lead processing code centrally instead of having to chase it down in a bunch of different places. Right now there's only one way to create leads, but figure 2 revealed that we'll be adding others. No matter how many we add, they'll all result in sending a confirmation e-mail out to the lead. Figure 4 shows the new bit of plumbing we're going to add to our message bus. Figure 4. Send a confirmation e-mail when creating a lead. To do this, we're going to need to make a few changes to the configuration and code. POM changes First we need to update the POM. Here's a summary of the changes; see the code download for details: • Add a JavaMail dependency to the Jetty plug-in. • Add an org.springframework.context.support dependency. • Add a spring-integration-mail dependency. • Set the mail.version property. These changes will allow us to use JavaMail. Expose JavaMail sessions through JNDI We'll also need to add a /WEB-INF/jetty-env.xml configuration to make our JavaMail sessions available via JNDI. Once again, see the code download for details. I've included a /WEB-INF/jetty-env.xml.sample configuration for your convenience. As mentioned previously, you'll need access to an SMTP server. Besides creating jetty-env.xml, we'll need to update applicationContext.xml. Listing 6 shows the changes we need so we can use JavaMail and SMTP. Listing 6. /WEB-INF/applicationContext.xml changes supporting JavaMail and SMTP The changes expose JavaMail sessions as a JNDI resource. We've declared the jee namespace and its schema location, configured the JNDI lookup, and created a JavaMailSenderImpl bean that we'll use for sending mail. We won't need any domain model changes to generate confirmation e-mails. We will however need to create a bean to back our new transformer endpoint. Service integration tier changes First, recall from figure 4 that the newLeadChannel feeds into a LeadToEmailTransformer endpoint. This endpoint takes a lead as an input and generates a confirmation e-mail as an output, and the e-mail gets pipes out to an SMTP transport. In general, transformers transform given inputs into desired outputs. No surprises there. Figure 4 is slightly misleading since it's actually the POJO itself that we're going to call LeadToEmailTransformer; the endpoint is really just a bean adapter that the messaging infrastructure provides so we can place the POJO on the message bus. Listing 7 presents the LeadToEmailTransformer POJO. Listing 7. LeadToEmailTransformer.java, a POJO to generate confirmation e-mails package crm.integration.transformers;import java.util.Date;import java.util.logging.Logger;import org.springframework.integration.annotation.Transformer;import org.springframework.mail.MailMessage;import org.springframework.mail.SimpleMailMessage;import crm.model.Lead;public class LeadToEmailTransformer { private static Logger log = Logger.getLogger("global"); private String confFrom; private String confSubj; private String confText; ... getters and setters for the fields ... @Transformer public MailMessage transform(Lead lead) { log.info("Transforming lead to confirmation e-mail: " + lead); String leadFullName = lead.getFullName(); String leadEmail = lead.getEmail(); MailMessage msg = new SimpleMailMessage(); msg.setTo(leadFullName == null ? leadEmail : leadFullName + " <" + leadEmail + ">"); msg.setFrom(confFrom); msg.setSubject(confSubj); msg.setSentDate(new Date()); msg.setText(confText); log.info("Transformed lead to confirmation e-mail: " + msg); return msg; } Again, LeadToEmailTransformer is a POJO, so we use the @Transformer annotation to select the method that's performing the transformation. We use a Lead for the input and a MailMessage for the output, and perform a simple transformation in between. When defining backing beans for the various Spring Integration filters, it's possible to specify a Message as an input or an output. That is, if we want to deal with the messages themselves rather than their payloads, we can do that. (Don't confuse the MailMessage in listing 7 with a Spring Integration message; MailMessage represents an e-mail message, not a message bus message.) We might do that in cases where we want to read or manipulate message headers. In this tutorial we don't need to do that, so our backing beans just deal with payloads. Now we'll need to build out our message bus so that it looks like figure 4. We do this by updating applicationContext-integration.xml as shown in listing 8. Listing 8. /WEB-INF/applicationContext-integration.xml updates to support confirmation e-mails The property-placeholder configuration loads the various ${...} properties from a properties file; see /crm/src/main/resources/applicationContext.properties in the code download. You don't have to change anything in the properties file. The transformer configuration brings the LeadToEmailTransformer bean into the picture so it can transform Leads that appear on the newLeadChannel into MailMessages that it puts on the confEmailChannel. As a side note, the p namespace way of specifying bean properties doesn't seem to work here (I assume it's a bug: http://jira.springframework.org/browse/SPR-5990), so I just did it the more verbose way. The channel definition defines a point-to-point channel rather than a pub-sub channel. That means that only one endpoint can pull messages from the channel. Finally we have an outbound-channel-adapter that grabs MailMessages from the confEmailChannel and then sends them using the referenced mailSender, which we defined in listing 6. That's it for this section. We should have working confirmation e-mails. Restart your Jetty instance and go again to http://localhost:8080/crm/main/lead/form.html Fill it out and provide your real e-mail address in the e-mail field. A few moments after submitting the form you should receive a confirmation e-mail. If you don't see it, you might check your SMTP configuration in jetty-env.xml, or else check your spam folder. Summary In this tutorial we've taken our first steps toward developing an integrated lead management system. Though the current bus configuration is simple, we've already seen some key Spring Integration features, including • support for the Gateway pattern, allowing us to connect apps to the message bus without knowing about messages • point-to-point and pub-sub channels • service activators to allow us to place service beans on the bus • message transformers • outbound SMTP channel adapters to allow us to send e-mail The second tutorial will continue elaborating what we've developed here, demonstrating the use of several additional Spring Integration features, including • message routers (including content-based message routers) • outbound web service gateways for sending SOAP messages • inbound HTTP adapters for collecting HTML form data from external systems • inbound e-mail channel adapters (we'll use IMAP IDLE, though POP and IMAP are also possible) for processing incoming e-mails Enjoy, and stay tuned. Willie is a solutions architect with 12 years of Java development experience. He and his brother John are coauthors of the upcoming book Spring in Practice by Manning Publications (www.manning.com/wheeler/). Willie also publishes technical articles (including many on Spring) to wheelersoftware.com/articles/.
August 18, 2009
by Willie Wheeler
· 249,676 Views · 3 Likes
article thumbnail
JPA 2.0 Concurrency and Locking
Optimistic locking lets concurrent transactions process simultaneously, but detects and prevent collisions, this works best for applications where most concurrent transactions do not conflict. JPA Optimistic locking allows anyone to read and update an entity, however a version check is made upon commit and an exception is thrown if the version was updated in the database since the entity was read. In JPA for Optimistic locking you annotate an attribute with @Version as shown below: public class Employee { @ID int id; @Version int version; The Version attribute will be incremented with a successful commit. The Version attribute can be an int, short, long, or timestamp. This results in SQL like the following: “UPDATE Employee SET ..., version = version + 1 WHERE id = ? AND version = readVersion” The advantages of optimistic locking are that no database locks are held which can give better scalability. The disadvantages are that the user or application must refresh and retry failed updates. Optimistic Locking Example In the optimistic locking example below, 2 concurrent transactions are updating employee e1. The transaction on the left commits first causing the e1 version attribute to be incremented with the update. The transaction on the right throws an OptimisticLockException because the e1 version attribute is higher than when e1 was read, causing the transaction to roll back. Additional Locking with JPA Entity Locking APIs With JPA it is possible to lock an entity, this allows you to control when, where and which kind of locking to use. JPA 1.0 only supported Optimistic read or Optimistic write locking. JPA 2.0 supports Optimistic and Pessimistic locking, this is layered on top of @Version checking described above. JPA 2.0 LockMode values : OPTIMISTIC (JPA 1.0 READ): perform a version check on locked Entity before commit, throw an OptimisticLockException if Entity version mismatch. OPTIMISTIC_FORCE_INCREMENT (JPA 1.0 WRITE) perform a version check on locked Entity before commit, throw an OptimisticLockException if Entity version mismatch, force an increment to the version at the end of the transaction, even if the entity is not modified. PESSIMISTIC: lock the database row when reading PESSIMISTIC_FORCE_INCREMENT lock the database row when reading, force an increment to the version at the end of the transaction, even if the entity is not modified. There are multiple APIs to specify locking an Entity: EntityManager methods: lock, find, refresh Query methods: setLockMode NamedQuery annotation: lockMode element OPTIMISTIC (READ) LockMode Example In the optimistic locking example below, transaction1 on the left updates the department name for dep , which causes dep's version attribute to be incremented. Transaction2 on the right gives an employee a raise if he's in the "Eng" department. Version checking on the employee attribute would not throw an exception in this example since it was the dep Version attribute that was updated in transaction1. In this example the employee change should not commit if the department was changed after reading, so an OPTIMISTIC lock is used : em.lock(dep, OPTIMISTIC). This will cause a version check on the dep Entity before committing transaction2 which will throw an OptimisticLockException because the dep version attribute is higher than when dep was read, causing the transaction to roll back. OPTIMISTIC_FORCE_INCREMENT (write) LockMode Example In the OPTIMISTIC_FORCE_INCREMENT locking example below, transaction2 on the right wants to be sure that the dep name does not change during the transaction, so transaction2 locks the dep Entity em.lock(dep, OPTIMISTIC_FORCE_INCREMENT) and then calls em.flush() which causes dep's version attribute to be incremented in the database. This will cause any parallel updates to dep to throw an OptimisticLockException and roll back. In transaction1 on the left at commit time when the dep version attribute is checked and found to be stale, an OptimisticLockException is thrown Pessimistic Concurrency Pessimistic concurrency locks the database row when data is read, this is the equivalent of a (SELECT . . . FOR UPDATE [NOWAIT]) . Pessimistic locking ensures that transactions do not update the same entity at the same time, which can simplify application code, but it limits concurrent access to the data which can cause bad scalability and may cause deadlocks. Pessimistic locking is better for applications with a higher risk of contention among concurrent transactions. The examples below show: reading an entity and then locking it later reading an entity with a lock reading an entity, then later refreshing it with a lock The Trade-offs are the longer you hold the lock the greater the risks of bad scalability and deadlocks. The later you lock the greater the risk of stale data, which can then cause an optimistic lock exception, if the entity was updated after reading but before locking. The right locking approach depends on your application: what is the risk of risk of contention among concurrent transactions? What are the requirements for scalability? What are the requirements for user re-trying on failure? For More Information: Preventing Non-Repeatable Reads in JPA Using EclipseLink Java Persistence API 2.0: What's New ? What's New and Exciting in JPA 2.0 Beginning Java™ EE 6 Platform with GlassFish™ 3 Pro EJB 3: Java Persistence API (JPA 1.0)
August 3, 2009
by Carol McDonald
· 51,631 Views · 1 Like
article thumbnail
Introduction to the Open eHealth Integration Platform
The Open eHealth Integration Platform (IPF) is an extension of the Apache Camel routing and mediation engine and comes with comprehensive support for message processing and connecting information systems in the healthcare sector. It is available under the Apache License version 2.0. IPF and Camel both focus on a domain-specific language (DSL) to implement and combine Enterprise Integration Patterns (EIPs) in integration solutions. IPF leverages the Groovy programming language for application development and for extending the Apache Camel DSL. One example of a healthcare-related use case of IPF is the implementation of interfaces for transactions specified in IHE profiles. The use of IPF to implement actor interfaces for the IHE PIX and PDQ profiles was tested successfully at the 2009 Connect-a-thon. The actual actors were proprietary systems that were IHE-enabled via IPF-based integration solutions. It is important to note that usage of IPF is not just limited to the healthcare domain. It can also be used to build integration solutions for several other domains. However, this article will focus primarily on the healthcare-specific features of IPF. Riding the Camel IPF is built on top of the Apache Camel routing and mediation engine. This section deals briefly with the concepts behind Camel. For a more detailed overview, read Jonathan Anstey's excellent introductory article Apache Camel: Integration Nirvana. Apache Camel is about Enterprise Integration Patterns (EIPs). EIPs have previously been described by Gregor Hohpe and Bobby Woolf in their book Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions. They represent experiences of integration architects and can be used as building blocks for designing integration solutions. These patterns were published as recommendations without implying a concrete implementation. This is where Apache Camel comes in. Camel was created to provide implementations for EIPs. With Apache Camel, integration solutions are developed by combining integration patterns using a domain-specific language (DSL). In addition to EIP implementations, Camel also provides more than 60 components for connecting to a great variety of transports and APIs. The four major concepts in Camel are components, endpoints, processors and the domain-specific language (DSL). Components provide connectivity to other systems. From components, endpoints are created for sending and receiving messages. Endpoints are uniquely identified by their URIs. Processors are used to route and transform messages between endpoints. To wire endpoints and processors together, Camel provides a DSL for Java. Consider a simple example: from("jms:queue:validated") .filter().xpath("/person[@name='Martin']") .to("http://www.example.com/camel"); In this route definition, messages are read from a JMS queue (identified by the jms:queue:validated endpoint URI) and sent through a filter. The filter criterion is an XPath predicate. Any message that passes the filter will be POSTed to the http://www.example.com/camel endpoint. Camel also supports a Spring-based XML configuration for creating message processing routes (not shown here). Riding IPF Any feature provided by Camel can be used in combination with any other features provided by IPF. IPF makes its features available via extensions to the Camel DSL. These extensions have been implemented via Groovy meta-programming. For these extensions to be used in an IPF application, route definitions must be written in Groovy. Here is an example of a route definition that uses IPF's DSL extensions: from('file:input') // read HL7 message from file .unmarshal().ghl7() // create HL7 message object .validate().ghl7() // validate HL7 message object .filter {exchange -> // filter message using criteria defined by closure def msg = exchange.in.body // use exchange.in.body to access HL7 message object msg.PID[8].value == 'F' // use HL7 DSL to access and compare PID-8 field value } .to('http://...') // send message to destination (via HTTP In this route, an HL7 message is read from a file, validated and then filtered based on the value of the 8th field in the PID segment. To obtain this field value, the filter closure uses IPF's HL7 DSL. This DSL is explained in detail in the next section. If the message passes the filter it is forwarded to its destination via HTTP. The route definition uses the DSL elements from, unmarshal, filter and to from Camel directly, all other DSL elements are extensions provided by IPF, including the use of closures for filter criteria. IPF DSL extensions can be used as if they are native Camel DSL elements. Furthermore, the DSL used in applications is not just limited to the DSL provided by Camel and IPF. Application-specific DSL extensions can also be written using IPF's DSL extension mechanism. This mechanism also supports modularization of DSL definitions. Any component can contribute its own DSL extensions. Consequently, the scope of the overall DSL depends on which components were deployed for the application. Inside an OSGi environment, IPF can even automatically detect and activate DSL extensions provided by different bundles. The following sections will explore the healthcare-specific features of IPF in greater detail. For a detailed description of all IPF features consult the IPF reference documentation. For a more hands-on guide on how to write IPF applications, the IPF tutorials are a good starting point. HL7 message processing HL7 (Health Level 7) is an ANSI-accredited standards developing organization (SDO) in the healthcare sector. Among other standards it focuses on developing messaging standards for the clinical and administrative domain. This standard is often referred to as the HL7 messaging standard. There are several versions of this standard. HL7 version 2.x is widely used, the most recent update was version 2.6 in 2007. It differs significantly from the XML-based HL7 version 3. The following subsections focus on IPF's support for HL7 version 2.x. Support for HL7 version 3 is currently under development. IPF uses the open source HAPI library as its basis for HL7 version 2 message processing. HL7 version 2 at a glance HL7 version 2 messages have a hierarchical structure and are organized into groups, segments, fields and datatypes which can also repeat. Message elements are referenced by their path within the hierarchy (see navigation syntax in the following figure). HL7 DSL The core of IPF's HL7 message processing capabilities is the HL7 DSL. This is a domain-specific language for accessing and manipulating HL7 version 2 messages. The IPF library that implements this DSL (modules-hl7dsl) can also be used standalone (i.e. independent from other IPF components) in any Groovy application. Seamless integration into the IPF DSL is provided as well. The following examples presume a certain degree of familiarity with HL7 version 2 message structures and terms. Constructing messages The entry point to the HL7 DSL is IPF's MessageAdapter. To create a MessageAdapter instance from an HL7 file we use the load method from the MessageAdapters utility class. import org.openehealth.ipf.modules.hl7dsl.MessageAdapter import org.openehealth.ipf.modules.hl7dsl.MessageAdapters MessageAdapter message = MessageAdapters.load('ADT-A01.hl7') This loads the HL7 file ADT-A01.hl7 from the classpath. Accessing message content The following example obtains the PID segment contained in the PATIENT group which itself is contained in the first repetition of the repeatable PATIENT_RESULT group. // repeating elements are indexed from 0 to n def segment = message.PATIENT_RESULT(0).PATIENT.PID The function call operator () is used to refer to an element in a repetition. The element index is passed as argument. Obtaining fields is similar to obtaining groups and segments except that fields are often referred to by index rather than by name. To obtain the MSH-3 field from a message we can write: // fields are indexed from 1 to n def composite = message.MSH[3] If the field is a composite we access the second component with: // components of a composite field are indexed from 1 to n def primitive = message.MSH[3][2] or, equivalently, def primitive = message.MSH.sendingApplication.universalIDType As shown above, navigation is also possible using field names instead of indices. Care must be taken, because along with the change of internal message structures, individual field names change between HL7 versions, even when they refer to the same position of the field in a segment. If the version of the HL7 message is not known in advance, it is better to use the more concise index notation. Fields may also repeat. To obtain a given element of a repeating field the function call operator () is used, just like with groups and segments. In the next example we obtain the first element of the repeating NK1-5 field. Because NK1 is a repeating segment, the function call operator is used on segment-level, too. def field = message.NK1(0)[5](0) def fieldList = message.NK1(0)[5]() Omitting the repetition index returns a list of repeating elements. Omitting the function call operator, the first repetition of a group, segment or field is assumed. This is called smart navigation: assert message.NK1(0)[5](0)[1].value == message.NK1[5](0)[1].value assert message.NK1(0)[5](0)[1].value == message.NK1[5][1].value assert message.PATIENT_RESULT(0).PATIENT.PID[5][1] == message.PATIENT_RESULT.PATIENT.PID[5][1] If a component is omitted, the first component or subcomponent of a composite is assumed assert message.NK1(0)[5](0)[1].value == message.NK1[5].value assert message.NK1(0)[5](1)[1].value == message.NK1[5](1).value assert message.NK1(0)[2][1][1].value == message.NK1[2].value Using smart navigation, the expressions are usually shorter and less error-prone. Moreover, in many cases the same expression can be used for different HL7 versions, making the DSL more portable. Modifying message content A segment of one message can be assigned the segment value of another message using the assigment operator (=). The following example copies the EVN segment from message2 to message1. message1.EVN = message2.EVN To change a field value we navigate to that field (either by name or index, as shown above) and assign it a string or another field value. def msh = message.MSH def nk1 = message.NK1(0) msh[5] = nk1[4][4] msh[5] = 'abc' Composite fields may also be changed by assigning other composite fields. In the following example we copy the composite NK1(0)[4] field from message2 to message1. message1.NK1(0)[4] = message2.NK1(0)[4] Externalizing messages The left-shift operator (<<) appends the string-represenation of a MessageAdapter object to a writer. In the following example, we write an HL7 message to System.out. MessageAdapter message = ... System.out << message To obtain the string-representation directly, we can use the MessageAdapter.toString() method. MessageAdapter message = ... def rendered = message.toString() Usage in route definitions This section shows a few examples how to combine the HL7 DSL with IPF's route definition DSL. The unmarshal().ghl7() extension should be used to create a MessageAdapter object from an external HL7 message representation. The created MessageAdapter object can then be used in subsequent processors. from('file:input') .unmarshal().ghl7() .process {exchange -> MessageAdapter message = exchange.in.body ... } ... The reverse operation marshal().ghl7() marshals a MessageAdapter object into a stream. This is often needed for transmitting HL7 messages over a variety of transports such as JMS, for example. from('file:input') .unmarshal().ghl7() ... .marshal().ghl7() .to(jms:queue:validated) Another usage example is content-based routing. In the following example a message is routed to different destinations depending on the content of the MSH[4] field. Here we use closures in combination with Camel's when DSL element for implementing routing rules. The it variable inside closures represents a message exchange. from(...) .unmarshal().ghl7() ... .choice() .when { it.in.body.MSH[4].value == 'ABC' } .to(...) .when { it.in.body.MSH[4].value == 'DEF' } .to(...) .otherwise() .to(...) HL7 validation IPF also adds support for specifying validation rules in a way that is easy to write and simple to understand. It facilitates the definition of custom validation rules by providing a dedicated validation DSL. Like the HL7 DSL, the validation DSL can also be used standalone but also integrates well into the IPF DSL for defining message processing routes. The IPF component that implements HL7 validation is modules-hl7. Validation rules are defined by extending the ValidationContextBuilder class of IPF. The validation rules DSL is provided by the RuleBuilder class. The following example defines a subset of segments from the HL7 version 2.2 specification. package example import ca.uhn.hl7v2.validation.ValidationContext import org.openehealth.ipf.modules.hl7.validation.builder.RuleBuilder import org.openehealth.ipf.modules.hl7.validation.builder.ValidationContextBuilder class SampleRulesBuilder extends ValidationContextBuilder { RuleBuilder forContext(ValidationContext context) { new RuleBuilder(context) .forVersion('2.2') .message('ADT', 'A01').abstractSyntax( 'MSH', 'EVN', 'PID', [ { 'NK1' } ], 'PV1', [ { INSURANCE( 'IN1', [ 'IN2' ] , [ 'IN3' ] )}] ) } } The sequence and cardinality of groups and segments is defined in a syntax that is very closely related to the HL7 Abstract Message Syntax. The message must contain the segments MSH, EVN, PID and PV1; it may contain zero or more NK1 segments and it may contain a repeatable INSURANCE group. In a next step we configure our SampleRulesBuilder in a Spring application context along with a ValidationContextFactoryBean. The ValidationContextFactoryBean auto-detects any beans of type ValidationContextBuilder and adds their validation rules to a ValidationContext that is used in route definitions. The validate().ghl7() DSL extension, which we have already seen, can be configured with a custom validation profile using the profile() DSL extension. The validation context is looked up from the Spring application context via bean(ValidationContext.class). import ca.uhn.hl7v2.validation.ValidationContext import org.apache.camel.spring.SpringRouteBuilder class SampleRouteBuilder extends SpringRouteBuilder { void configure() { from(...) .unmarshal().ghl7() .validate().ghl7().profile(bean(ValidationContext.class)) ... .to(...) } } Code mapping HL7 message processing often involves mapping between code systems i.e. from one set of codes into a corresponding different set of codes. For example, HL7 version 2 and HL7 version 3 use different code systems for most coded values such as message type, gender, clinical encounter type, marital status codes, address and telecommunication use codes, just to mention a few. IPF defines a mapping service that provides the mapping logic. This may be a simple map but it can also be a facade to a remote mapping or terminology service. IPF's default mapping service implementation, the BidiMappingService, supports bidirectional mappings and reads custom mapping definitions from mapping files. An instance of the BidiMappingService can be created with the following bean definition. The mapping service references a mapping file example.map on the classpath. If there is more than one mapping file, a list can be provided via the mappingScripts property. Here is the content of example.map: mappings = { encounterType(['2.16.840.1.113883.12.4','2.16.840.1.113883.5.4'], E : 'EMER', I : 'IMP', O : 'AMB' ) } The example mapping file is a Groovy script and contains a single mapping with three entries for encounter type codes. Also defined are the ISO Object Identifiers (OIDs) for the key and value code systems. The mapping service can now be accessed either directly or via methods on java.lang.String. The String.map() method maps the codes on the left side to the right side. The identifier for the mapping can either be passed as argument assert 'E'.map('encounterType') == 'EMER' assert 'X'.map('encounterType') == null assert 'X'.map('encounterType', 'DEFAULT') == 'DEFAULT' or as part of a method name. assert 'E'.mapEncounterType() == 'EMER' assert 'X'.mapEncounterType() == null assert 'X'.mapEncounterType('DEFAULT') == 'DEFAULT' A dynamic dispatch is used to select the mapping definition from the method name. The method names must therefore correspond to the registered mappings. Mapping in the reverse direction is equally possible. assert 'EMER'.mapReverse('encounterType') == 'E' assert 'EMER'.mapReverseEncounterType() == 'E' Code systems are often associated with a globally unique identifier, usually in form of an OID. The identifier of both sides of a mapping can be obtained as follows. assert 'encounterType'.keySystem() == '2.16.840.1.113883.12.4' assert 'encounterType'.valueSystem() == '2.16.840.1.113883.5.4' Code mapping methods may also be used in combination with the HL7 DSL. MessageAdapter message = ... assert message.PV1.patientClass.value == 'I' assert message.PV1.patientClass.map('encounterType') == 'IMP' assert message.PV1.patientClass.mapEncounterType() == 'IMP' Response messages HL7 messaging often requires the return of an HL7 response message to the sender. With IPF, positive (ACK) or negative (NAK) acknowledgments to messages can be generated. Acknowledgments are in the same HL7 version as the original message and are populated with arguments to the ack() method. MessageAdapter message = ... def ack = message.ack() def nak1 = message.nak('Reason for failure') def nak2 = message.nak(new HL7Exception('Reason for failure', 204)) Generating acknowledgments is, however, only one special case of generating a response to an original message. For responses other than acknowledgements, a response message prototype can be created via the respond(eventType, triggerEvent) method. The MSH and MSA segments of the response message are then populated as required by the HL7 specification. def rsp = msg.respond('RSP','K21') // generates a RSP_K21 message More features So far, the main focus has been on HL7 message processing. IPF has many more features and services to support the development and the operation of production-quality integration solutions. Some of them are briefly described in the following list. A detailed description would far exceed the scope of this paper. For a complete overview refer to the IPF reference documentation. Core features. Collection of domain-neutral message processors and DSL extensions usable for general-purpose message processing including support for Groovy XML processing and support for using closures with Camel DSL elements. OSGi support. Support for running IPF and its services inside an OSGi environment and for the development of OSGi-ready IPF applications. Flow management. A service for monitoring and managing message flows through IPF applications. The flow manager also supports a replay of messages for e.g. recovery from failures. Large message support. Allows for memory-efficient processing of large messages. Event infrastructure. An infrastructure for publishing and consuming system and application events. Can be used e.g. for separating logging, audit or statistics concerns from application-specific route definitions. Can also be used to integrate with complex event processing (CEP) engines. Outlook Upcoming IPF releases will provide support for CDA (Clinical Document Architecture) and IHE (Integrating the Healthcare Enterprise). CDA is an XML-based document markup standard that specifies the structure and semantics of a clinical document for the purpose of exchange. IHE is an initiative of healthcare professionals and industry to improve the way computer systems in the healthcare sector share information. The goal of IPF is to make it as easy as possible for developers to implement the CDA, IHE (and other clinical) standards in their applications. Here are a few examples of what to expect in the next IPF release. CDA support IPF's CDA support will focus on building CDA documents using a domain-specific language. This DSL supports the creation of structurally correct CDA documents by enforcing CDA-relevant schema definitions but without dealing with low-level XML details. The DSL is implemented by a custom Groovy builder, the CDABuilder. In the following code snippet we use the CDABuilder to create a CDA document using CDA-specific terms such as clinicalDocument, code, title, recordTarget and so on. For printing the created document to stdout we use the left-shift (<<) operator. // Create a CDA builder CDABuilder builder = new CDABuilder() // Create a new CDA document def document = builder.build { clinicalDocument { id(root:'2.16.840.1.113883.19.4', extension:'c266') code( code:'11488-4', codeSystem:'2.16.840.1.113883.6.1', codeSystemName:'LOINC', displayName:'Consultation note' ) title('Good Health Clinic Consultation Note') recordTarget { patientRole { id { extension="12345" root="2.16.840.1.113883.19.5" } patient { name { given('John') family('Doe') } birthTime('19320924') } //... } //... } //... } //... } // Write document XML to stdout System.out << document CDA support will also include support for selected CDA profiles from IHE, HL7/ASTM and HITSP specifications, for example XPHR and CCD. Profile-specific CDA DSL extensions will enforce the constraints imposed by the profile specifications. As an example, predefined CDA sections could then be added without knowing their templateID-OIDs or their exact nested XML structure. DSL support for parsing, validating, transforming and rendering CDA documents will complete the feature set. IHE support IPF's IHE support is a framework for creating actor interfaces as specified in IHE profiles. Most likely, support for the XDS profile will be the first to come. XDS stands for Cross-Enterprise Document Sharing and deals with registration and distribution of, and access to clinical documents across health enterprises. Central to this profile are the actors document registry and document repository. A number of document management systems could in principle act as registry and/or repository in the XDS profile. Most of these, however, do not support the XDS actor interface specifications right out of the box. This is were IPF comes in. It helps developers to build IHE actor interfaces for existing information systems. Consider this example: from('ihe:xds.b:iti-41?port=8080') .process { exchange -> def document = exchange.in.body // do further document processing here ... } // communicate with your document management system .to('http://...') // notify about availability of new document .to('ihe:nav:iti-25:[email protected]') This route starts a server to receive documents according to the ITI-41 transaction of the XDS.b IHE profile. ITI-41 is the Provide and Register Document Set transaction in XDS.b. XDS.b requires documents to be transported via SOAP and ebXML standards. To free developers from having to deal with low-level SOAP/ebXML handling, these communication details are hidden inside an ihe component (eventually there may be more than one). Subsequent processors can access the transported document without having to deal with ITI-41 details. After processing, the incoming document is uploaded to a document management system and, finally, [email protected] is notified about the availability of a new document. Notifications are sent according to the IHE NAV profile where NAV stands for Notification of Document Availability. This example is of course oversimplified (for instance it does not address responses, etc) but it still gives an idea of the abstraction level on which IHE interfaces can be implemented for existing systems. Conclusion Apache Camel is a good answer to many of today's integration problems. It provides a DSL for implementing Enterprise Integration Patterns and offers developers a simple and efficient way to deal with the diversity of applications and transports in distributed systems. IPF brings the power of Apache Camel to the healtcare domain and makes healthcare IT standards usable by means of a domain-specific language that closely resembles the language of domain experts. The DSL extension mechanism permits the evolution of even more specialized healthcare DSLs. IPF's support for DSL modularization makes these DSLs and their implementing components reusable in different integration scenarios. Author Martin Krasser is a software architect and engineer working for InterComponentWare AG. He focuses on distributed systems, application integration and application security. Martin is the founder and project lead of the open source IPF project.
May 11, 2009
by Martin Krasser
· 46,386 Views · 2 Likes
article thumbnail
Enterprise Integration Patterns with Apache Camel Refcard Now Available!
Apache Camel is a powerful open source integration platform based on Enterprise Integration Patterns with Bean Integration. This Refcard provides you with eleven of the most essential patterns that anyone working with integration must know. This Refcard is targeted for software developers and enterprise architects, but anyone in the integration space can benefit as well. Download Now! About the Author: Claus Ibsen is a passionate open-source enthusiast who specializes in the integration space. As an engineer in the FuseSource Open Source Division he works full time on Apache Camel, FUSE Mediation Router (Apache Camel Enterprise) and related projects. Claus is very active in the Apache Camel and Fuse communities, writing blogs, twittering, assisting on the forums, irc channels and is driving the Apache Camel roadmap.
March 30, 2009
by Wei Ling Chen
· 5,139 Views
article thumbnail
Apache Camel: Integration Nirvana
Take any integration project and you have multiple applications talking over multiple transports on multiple platforms. As you can imagine, in large enterprise applications this can get complex very fast. Much of the complexity stems from two issues: 1. dealing with the specifics of applications and transports, and 2. coming up with good solutions to integration problems. Making your applications speak transports and APIs is relatively easy on its own. I'm sure everyone knows how to send JMS messages to their broker of choice; though it still requires in depth knowledge of the JMS specification, which many developers may not have. On top of that, what happens when you want to route that JMS message to another application? You then have to take care of mapping the JMS message to the application plus handle any new concepts related to the application. Add a dozen other applications into the mix and you've got quite a headache on your hands. Ignoring the mechanics of how to connect with multiple transports and APIs, we can focus on the high level design of how applications interact. Fortunately, most solutions to enterprise integration problems have been formalized already. Gregor Hohpe and Bobby Woolfe's book, Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions, boils down years of experience from enterprise architects into a set of sixty five Enterprise Integration Patterns (EIPs). This is great but we still have to hand code all parts of these patterns; these are not packaged solutions, only recommendations. Apache Camel was created with the intention of addressing these two issues. In this article I'll show you how it actually does this. What is Camel? Apache Camel is an open source Java framework that focuses on making integration easier and more accessible to developers. It does this by providing: • concrete implementations of all the widely used EIPs • connectivity to a great variety of transports and APIs • easy to use Domain Specific Language (DSL) to wire EIPs and transports together Figure 1 shows how these three items actually map to Camel concepts. To give you a good understanding of how Camel is organized, we will discuss Components, Endpoints, Processors, and the Domain Specific Language (DSL). There is of course a lot more going on here under the hood but we'll leave that for another discussion. Figure 1: High level view of Camel's architecture. Components are the extension point in Camel to add connectivity to other systems. The core of Camel is very small to keep dependencies low, promote embeddability, etc. and as a result contains only 12 essential components. There are over 60 components outside the core. To expose these systems to the rest of Camel, Components provide an Endpoint interface. By using URIs, you can send or receive messages on Endpoints in a uniform way. For instance, to receive messages from a JMS queue aQueue and send them to a file system directory "c:/tmp", you could use URIs like "jms:aQueue" and "file:c:\tmp". Processors are used to manipulate and mediate messages in between Endpoints. All of the EIPs are defined as Processors or sets of Processors. As of writing, Camel supports 41 patterns from the EIP book, 6 other integration patterns, and many other useful Processors. To wire Processors and Endpoints together, Camel defines a Java DSL. The term DSL is used a bit loosely here as it usually implies the involvement of a compiler or interpreter that can process keywords specific to a particular domain. In Camel, DSL means a fluent Java API that contains methods named like terms from the EIP book. Its best explained with an example from("jms:aQueue") .filter().xpath("/person[@name='Jon']") .to("file:c:\tmp"); Here we define a routing rule in a single Java statement that will consume messages from the "jms:aQueue" Endpoint, send them through a Message Filter Processor, which will then send on messages passing the XPath condition to the "file:c:\tmp" endpoint. Messages failing the condition will be dropped. You can also configure your routes in a XML-based Spring configuration file. This configuration file is a lot more verbose and less auto complete friendly than the Java DSL; many prefer it though because of its direct access to Spring concepts and no requirement for compilation after changes. Here is what the earlier example would look like in Spring: /person[@name='Jon'] These are the concepts that Camel was built upon. Since then many other interesting features have been added. Details of these are left up to the reader to investigate. To get you started, some of these include: • Pluggable data formats and type converters for easy message transformation between Artix Data Services, CSV, EDI, Flatpack, HL7, JAXB, JSON, XmlBeans, XStream, Zip, Camel-bindy, etc. • Pluggable languages to create expressions or predicates for use in the DSL. Some of these languages include: EL, JXPath, Mvel, OGNL, BeanShell, JavaScript, Groovy, Python, PHP, Ruby, SQL, XPath, XQuery, etc. • Support for the integration of beans and POJOs in various places in Camel. • Excellent support for testing distributed and asynchronous systems using a messaging approach • and much more... Example A motorcycle parts business, Rider Auto Parts, supplies parts to motorcycle manufacturers. Over the years they've changed the way they receive orders several times. Initially, orders were placed by uploading CSV files to an FTP server. The message format was later changed to XML. Currently they provide a web site to submit orders as XML messages over HTTP. All of these messages are converted to an internal POJO format before processing. Rider Auto Parts states to any new customers to use the web interface to place orders. However, because of existing agreements with customers, they must keep all the old message formats and interfaces up and running. Solution using EIPs Rider Auto Parts faces a pretty common problem; over years of operation businesses acquire software baggage in the form of transports/data formats that are popular at the time. Using patterns from the EIP book we can envision the solution as something like Figure 2. Figure 2: This shows the solution to Rider Auto Parts integration problem using notation from the Enterprise Integration Patterns book. So we have several patterns in use here. 1. There are two Message Endpoints; one for FTP connectivity and another for HTTP. 2. Messages from these endpoints are fed into the incomingOrderQueue Message Channel 3. The messages are consumed from the incomingOrderQueue and routed by a Content-Based Router to one of two Message Translators. As the EIP name implies, the routing destination depends on the content of the message. In this case we need to route based on whether the content is a CSV or XML file. 4. Both Message Translators convert the message content into a POJO, which is fed into the orderQueue Message Channel. The whole section that uses a Content-Based Router and several Message Translators is referred to as a Normalizer. This composite pattern has a unique graphic to depict it but was left out here in favor of its sub-patterns to make things clearer. Implementation using Camel As mentioned before, Camel has a small core set of components included by default. The rest of the components exist as separate modules. In applications that require many types of connectivity it is useful to figure out what Camel modules to include. Listing 1 shows the dependencies using Apache Maven for the Camel implementation of the Rider Auto Parts example. Of course, you don't need to use Apache Maven for dependencies - it is just the easiest way to rapidly add new dependencies to your applications. The list of dependencies includes support for core Camel, ActiveMQ, JAXB marshaling, CSV marshaling, and HTTP. To make the example easier to try out, I've opted to use the File endpoint instead of the FTP. If we were using the FTP endpoint we would need to add a dependency on the camel-ftp module as well. Listing 1: Maven dependencies for the Camel implementation org.apache.camel camel-core ${camel-version} org.apache.camel camel-spring ${camel-version} org.apache.activemq activemq-camel ${activemq-version} org.apache.camel camel-jaxb ${camel-version} org.apache.camel camel-csv ${camel-version} org.apache.camel camel-jetty ${camel-version} org.apache.activemq activemq-core ${activemq-version} org.apache.xbean xbean-spring ${xbean-spring-version} While it is perfectly legitimate to use Camel as a standalone Java application, it is often useful to embed it in a container. In this case, we will be loading Camel from Spring. The Spring beans XML file is shown in Listing 2. First we start an embedded Apache ActiveMQ broker and connect Camel to it. We also load up some helper beans that we will reference from the DSL. Finally, the camelContext element tells Camel to look for routes in the org.fusesource.camel package. Routes are Java classes that extend the RouteBuilder class in Camel. Listing 2: Spring XML file that configures an embedded ActiveMQ broker, several beans used in the Camel route, and initializes the Camel Context to search for routes in the org.fusesource.camel package. org.fusesource.camel The real meat of the Camel implementation lies in the OrderRouter class (shown in Listing 3). This class extends RouteBuilder, so it will be automatically picked up and loaded by Camel's runtime. Looking back at Figure 2, we need to receive orders from an FTP (substituted with File) and HTTP endpoint, formatted as shown in Listing 4. In the DSL we can specify these incoming endpoints with two from elements. Both from elements are connected to a to("jms:incomingOrderQueue") element, which will send the messages to a queue on the ActiveMQ broker. Listing 3: Route definitions for the example. The routing rules are specified using a fluent API, referred to as Camel's DSL. public class OrderRouter extends RouteBuilder { @Override public void configure() throws Exception { JaxbDataFormat jaxb = new JaxbDataFormat("org.fusesource.camel"); // Receive orders from two endpoints from("file:src/data?noop=true").to("jms:incomingOrderQueue"); from("jetty:http://localhost:8888/placeorder") .inOnly().to("jms:incomingOrderQueue") .transform().constant("OK"); // Do the normalization from("jms:incomingOrderQueue") .convertBodyTo(String.class) .choice() .when().method("orderHelper", "isXml") .unmarshal(jaxb) .to("jms:orderQueue") .when().method("orderHelper", "isCsv") .unmarshal().csv() .to("bean:normalizer") .to("jms:orderQueue"); } } In the case of the HTTP endpoint, there are a couple of extra things to mention. First off the HTTP client will be expecting a response from the application so we have to handle that. In Camel, we have full control over what the client gets back from the HTTP endpoint. Each response is determined by the last method in our current route definition (each Java statement is a route definition). In our case we use the transform method to set the response to the constant string "OK". Since we handle the response ourselves, we don’t want any response to come from the JMS incomingOrderQueue. To send to this queue in a fire-and-forget fashion we add the inOnly modifier. It is important to note at this point that when writing Camel DSL in a modern Java IDE, selection of the next processing step is easy because of auto complete. The auto complete feature basically gives you a list of processors (i.e. EIPs) to choose from at any point in your route. Since fluent APIs chain methods together, the only method you need to remember is the from; all other methods are shown via auto complete. Listing 4: Incoming message formats; XML on top, CSV below. "name", "amount" "brake pad", "2" The next section of DSL in Listing 3 specifies the Normalizer, complete with Content-Based Router and two Message Translators. First we specify that we want to consume messages from the incomingOrderQueue on the ActiveMQ broker. The content based routing of the messages is done with the choice and when methods. In our case, we want to send CSV messages to one Message Translator and XML messages to another. To check what type of message we have we will be using a simple Java bean shown in Listing 5. Of course, this is demonstration code only; for production cases you would want to add more thorough checking of content types. Listing 5: Java bean that contains helper methods to be used in the DSL. public class OrderHelper { public boolean isCsv(String body) { return !body.contains("> body) { List orderHeaders = body.get(0); List orderValues = body.get(1); return new Order(orderValues.get(0), Integer.parseInt(orderValues.get(1))); } } At this point, successfully normalized messages are sent to the orderQueue for processing by some other application at the Rider Auto Parts business. Conclusion In this article I've shown two common problems that an integration developer may face: dealing with the specifics of applications and transports, and coming up with good solutions to integration problems. The Apache Camel project provides a nice answer to both of these problems. As the example has shown, solving integration problems with Camel is straight forward and results in relatively concise code. In my opinion it is the closest thing to integration nirvana that we have today. Links Apache Camel – http://camel.apache.org FUSE Mediation Router (based on Apache Camel) – http://fusesource.com/products/enterprise-camel Enterprise Integration Patterns – http://www.enterpriseintegrationpatterns.com Jon’s Blog – http://janstey.blogspot.com Camel in Action book - http://www.manning.com/ibsen Article source code - http://repo.fusesource.com/maven2/org/fusesource/examples/rider-auto-example/1.0/rider-auto-example-1.0.zip Author Jonathan Anstey is a senior engineer working for Progress Software Corporation specializing in the enterprise integration space. Jon focuses mostly on Apache Camel and its Progress endorsed likeness, FUSE Mediation Router. He also works on the Apache ActiveMQ and Apache ServiceMix projects
March 23, 2009
by Jonathan Anstey
· 224,137 Views · 8 Likes
  • Previous
  • ...
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 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
×