Вы находитесь на странице: 1из 36

Issue October 2011 | presented by

www.jaxenter.com
TM

Spec Disco ial un JAX L t for ondo Inside n !


Frameworks are often an essential part of a developers working life, especially when it comes to developing web apps, web services and dynamic websites, but the framework market is a cluttered and potentially confusing place. In this issue of Java Tech Journal, we cut through the Which is the best Java web framework? debate, to bring you a series of no-no-nonsense articles examining the particular strengths of several popular Java web frameworks like JSF 2, Apache Wicket, Struts 2, ZK and Stripes.

#12

Java Web Frameworks


JSF 2 And HTML5 Server Sent Events
How to incorporate HTML5 Server Sent Events into a JSF UI

Apache Wicket

The Fun Web Framework

Introducing ZK

Develop dynamic and robust Java web apps with ZK

Stripes

A lean, mean Java web framework

Apache Struts 2 Soup to Nuts


A practical introduction

Editorial

Java Web Frameworks


In the world of modern software development, there's no shortage of web application frameworks for Java, and their popularity is undeniable. In fact, often the question isnt is a framework right for my project? but WHICH framework is right for my project? The rise of the application framework is intrinsically linked to the popularity of graphical user interfaces (GUIs), for the simple reason that GUIs promote a standard application structure. In this new world of GUIs, Struts 1 was one of the first Java web application tools. It used and extended the Java Servlet API, to separate the model from the view and the controller, and was eventually donated to Apache in 2000 (where it became known as Jakarta Struts.) At the time, the two options were hand-coding everything, or use Struts 1. Unsurprisingly, Struts 1 enjoyed huge popularity in the Java world even giving rise to the WebWork framework, which was ultimately merged into Struts 2. Nowadays, Struts is far from the only MVC framework on the market, with Spring MVC, Stripes, Play!, JSF, ZK Framework, Tapestry and others, all providing stiff competition not to mention frameworks that move beyond the realms of MVC, and even the cross-platform Adobe Flex. The list is endless! Inevitably, there are no shortage of Which Is the Best Java Framework? blog posts, but the fact that there are so many developers willing to fight their corner for their favourite Java framework, proves how essential and prized - frameworks have become to the modern developer. In this issue of Java Tech Journal, we look at a range of frameworks available to the Java developer. We deep dive into JSF, ZK and Wicket, which are all component-based frameworks, meaning that artifacts that are rendered on the page are first developed as individual components. Generally, code is ignorant of the HTTP request cycle and processing. Struts2 and Stripes are action frameworks, so users can map URLs to activities and code on the back end. As a general rule, developers interact with the HTTP request cycle directly. However, these are only the basic differences! Stripes also uses Java technologies such as annotations and generics that were introduced in Java 1.5, to achieve "convention over configuration; and the ZK Ajax web application framework is a server-centric framework, geared towards the creation of graphical user interfaces for web applications. In this issue of Java Tech Journal, we will deep dive into each of these frameworks, with articles by Oracles Principal Software Engineer, Roger Kitain; Stripes ...and Java Web Development is Fun Again author Fred Daoud; co-author of Struts in Action Ted Husted and more! Jessica Thornsby

Index

JSF 2 And HTML5 Server Sent Events


How to incorporate HTML5 Server Sent Events into a JSF UI
Roger Kitain

Apache Wicket
The Fun Web Framework
Jeremy Thomerson

10

Introducing ZK
Develop dynamic and robust Java web apps with ZK
Timothy Clare

17

Stripes
A lean, mean Java web framework
Fred Daoud

24

Apache Struts 2 Soup to Nuts


A practical introduction
Ted Husted

30

www.JAXenter.com | October 2011

Composite Components

Introducing the world to composite components

JSF 2 and HTML5 server sent events


The world of HTML5 offers many features to facilitate the creation of exciting and dynamic web sites. There are web communication specifications under the HTML5 umbrella that define a standard way to perform real-time communication between browser clients and servers. One such specification is the Server Sent Events specification. In this article, we will explore how we can incorporate HTML5 Server Sent Events into a JavaServer Faces (JSF) User Interface using some of the new component features available since JSF 2.0.
by Roger Kitain
HTML5 Server Sent Events (SSE) is a W3C specification that defines a standard API for opening an HTTP connection for receiving push notifications (data) from the server. Operationally, it works the same as Comet. However, Comet attempts to facilitate server push over the existing HTTP request/response protocol through various hacks such as appending scripts to iframes. The SSE specification introduces a new EventSource HTML element that can be used with JavaScript to establish a connection to a server end point. The client also registers event callback JavaScript functions for handing pushed data from the server. Lets look at a client example (Listing 1). It shows a simple page that will establish a connection to a server endpoint when the page is loaded. On line 4, we create a new EventSource object, feeding it the URL of a server endpoint. The server endpoint could be a PHP script, NodeJS implementation, or even a Java Servlet. When a new EventSource instance is created, an initial GET request to the server endpoint is done to establish the initial connection. On line 5, we register a message callback that will populate the events div with the event data. We could have also registered a message handler on the EventSource instance this way: source. addEventListener('message', 'msgCallback', false);. As data is pushed from the server, this callback will update the div area in the page. It is also possible to handle multiple event types from the server:
source.addEventListener('ticker', 'tickerCallback', false); source.addEventListener('time', 'clockCallback', false);

Server requirements
The SSE specification specifies requirements for the server response. The specification states that the response content type must be text/event-stream. To send a single line of data (Hello World!): data: Hello World!\n\n. To send multiple lines of data:
data: This is the first line\n data: This is the second line\n\n

Here, a single string of data concatenated with the newline character will be sent to the client side event handler function. It is also possible to send the response as JSON data:
data: {\n data: "msg":"hello world",\n data: "id:"12345\n data: }\n\n

Listing 1: Client page


1. <!DOCTYPE html> 2. <head> 3. <script type='text/javascript'> 4. var source = new EventSource('serverevents'); 5. source.onmessage = function(event) { 6. var ev = document.getElementById('events'); 7. ev.innerHTML += event.data; 8. }; 9. </script> 10. </head> 11. <body> 12. <div id=events /> 13. </body> 13. </html>

The event data for these events would be pushed over the same EventSource connection. It should be mentioned that SSE (namely the EventSource API) is not yet available in all browsers. Google Chrome is one such browser that has SSE support.

www.JAXenter.com | October 2011

Composite Components

Figure 1: Stock view application

quote information real-time as it is updated on the server. The quote numbers are randomly generated on the server, but real quotes could be retrieved by tying into a quote service. The third area consists of a link to retrieve RSS news feeds for the stocks, and a scrollable area that displays the news feed. The news feed is also pushed from the server real-time. Corresponding to these three areas are three SSE event types: time, ticker and rss. When the user interface is first displayed, the clock will tick real time. You enter space delimited stock symbols, press the Get Quotes button and a table is dynamically displayed with streaming quotes. Pressing the Get Stock News link causes news feeds to stream from the server.

In all cases, notice that two successive newline characters end the response.

The user interface markup


JSF 2.0 introduced three big features that make it easier to develop dynamic user interfaces. Facelets becomes the primary view technology Composite components make it easier to develop complex components Ajax support Lets see how these three features are used in this user interface. Listing 2 is the markup for the main user interface.

The user interface


Well look at a simple stock view application (figure 1) that will cause the streaming of three event types to the JSF user interface. This user interface consists of three areas of information. The first area is the time bar. The second area is the stock quote area that consists of an input field to enter stock quotes, buttons to retrieve stock quote information and reset (clear) the input area, and a table that displays the stock

Listing 2: stock.xhtml facelets view


1. <!DOCTYPE html> 2. <html xmlns="http://www.w3.org/1999/xhtml" 3. xmlns:h="http://java.sun.com/jsf/html" 4. xmlns:f="http://java.sun.com/jsf/core" 5. xmlns:ui="http://java.sun.com/jsf/facelets" 6. xmlns:h5="http://java.sun.com/jsf/composite/h5" 7. xmlns:ez="http://java.sun.com/jsf/composite/stockinfo"> 8. <h:head> 9. <meta charset="UTF-8" /> 10. </h:head> 11. 12. <h:body style="background: #fefeef"> 13. 14. <h:form> 15. <h:panelGrid styleClass="title-panel"> 16. <h:panelGrid columns="2" cellpadding="20"> 17. <h:outputText value="S t o c k V i e w" styleClass="title-panel-text"/> 18. </h:panelGrid> 19. <h:outputText value="Powered By JavaServer Faces 2.1 and Html 5 Server Sent Events "

20. 21. 22. 23. 24. 25.

styleClass="title-panel-subtext"/> </h:panelGrid> <h:outputStylesheet name="stylesheet.css" /> <h5:sse url="/JSFStock1/sse/stockticker" events="{stock:stockHandler, time:clockHandler,rss:rssHandler}"/>

26. 27. <br/> 28. <ez:clock/> 29. <br/> 30. <br/> 31. <ez:stock/> 32. 33. <h:messages/> 34. 35. </h:form> 36. 37. <a href="doc.xhtml">Documentation</a> 38. </h:body> 39. </html>

www.JAXenter.com | October 2011

Composite Components

This user interface uses four composite components. Well look at these in more detail later on, but I summarize them here: sse: Server Sent Events component used to establish a connection to a server end point. clock: Clock component displays the ticking time bar stock: Stock component that produces the input field for entering stock symbols, the two buttons, and a placeholder for the dynamic table that will display stock ticker information. rss: Component that produces the link Get Stock News and a placeholder for the dynamic scrollable area that will display stock news. This component is actually contained in the implementation of the stock component which is why you dont see it in this view. The first thing youll notice is that on line 1 were using an HTML5 document type declaration. That makes this document an HTML5 polyglot document because it has an HTML5 document type /namespace and well-formed XHTML syntax which works great for JSF views. This would allow us to use

other HTML5 features as well. Lets take a look at the other relevant sections of this view: Lines 3 7: Here we declare the namespaces used in the user interface. Lines 3 and 4 are just the standard JSF namespaces. Line 5 is the Facelets namespace. Line 6 declares the namespace that well use for our SSE component. Line 7 declares the namespace that will be used for the clock, stock and rss components. Line 25: This is the usage of the SSE component. This component uses two attributes: url: The URL of the server endpoint that we are connecting to events: Specifies event type : event handler pairings. The event handler is the name of the JavaScript function that will handle the associated event type data coming from the server. Line 28: This is the usage of the clock component. Line 31: This is the usage of the stock component. Its easy for a page author to use well defined components in a view. Now lets see how these components are defined.

The composite components

Listing 3: sse.xhtml SSE composite com ponent


1. <!DOCTYPE html> 2. 3. <html xmlns="http://www.w3.org/1999/xhtml" 4. xmlns:h="http://java.sun.com/jsf/html" 5. xmlns:f="http://java.sun.com/jsf/core" 6. xmlns:ui="http://java.sun.com/jsf/facelets" 7. xmlns:composite="http://java.sun.com/jsf/composite"> 8. <head> 9. 10. <title>Server Sent Event Composite Component</title> 11. 12. </head> 13. 14. <body> 15. 16. <composite:interface> 17. <composite:attribute name="url" required="true"/> 18. <composite:attribute name="events" required="false"/> 19. </composite:interface> 20. 21. <composite:implementation> 22. <h:outputScript name="js/jsf-sse.js" target="head" /> 23. <script type="text/javascript"> 24. JSF.sse.connect("#{cc.attrs.url}", #{cc.attrs.events}); 25. </script> 26. </composite:implementation> 27. 28. </body> 29. 30. </html>

Recall that JSF composite components consist of two areas: interface section implementation section The interface section is where you define the usage contract for the component. It is where you define the attributes that a page author would use with your component. The implementation section is the code that produces the component. It may consist of HTML markup, JavaScript and/or other JSF components. Lets take a look at the composite components that are used in this application.

The SSE composite component


The Server Sent Events (SSE) composite component is used to establish a connection to a server endpoint. As mentioned earlier, this component has two attributes. Lets see how this component is implemented in Listing 3, and lets take a look at the relevant sections of this component: Lines 4 7: This is just our namespace declarations. Line 7 is declaring a composite namespace that will be used to define the relevant sections of our composite component. Lines 16 19: This is where we define the interface or usage contract for our composite component. On line 17 we define a required url attribute whose value will be the server endpoint. On line 18 we define the events attribute whose value will contain event type : event handler name mappings as shown earlier. Lines 21 26: This is the implementation of the composite component. JavaScript and JSF work together nicely to create dynamic components. On line 22, we are loading a small JavaScript library that contains functions for performing SSE operations for JSF. Notice that were using

www.JAXenter.com | October 2011

Composite Components

Listing 4: jsfsse.js the JSF SSE JavaScript Library


1. if (!JSF) { 2. 3. /** 4. * The top level global namespace for JavaServer Faces Server Sent Event 5. * functionality. 6. * @name JSF 7. * @namespace 8. */ 9. var JSF = {}; 10. 11. /** 12. * The namespace for Server Sent Event functionality. 13. * @name JSF.sse 14. * @namespace 15. * @exec 16. */ 17. JSF.sse = function() { 18. 19. var eventSource = null; 20. 21. var getEventSource = function getEventSource(url) { 22. url = 'http://' + document.location.host + url; 23. eventSource = new EventSource(url); 24. }; 25. 26. return { 27. 28. /** 29. * Connect to a server end point. 30. * <p><b>Usage:</b></p> 31. * <pre><code> 32. * JSF.sse.connect(url, {events: * 'stock:stockHandler time:clockHandler'}); 33. * ... 34. * function stockHandler(event) { 35. * ... 36. *} 37. * </pre></code> 38. * 39. * @member JSF.sse 40. * @param url The URL of a valid server end point that will deliver * messages. 41. * @param eventOptions The set of events consisting of event * name:handler name pairs 42. * associating an event name from the server, and the name of the 43. * handler that will process the event.. 44. */ 45. connect: function connect(url, eventOptions) { 46. if (url === null) { 47. throw new Error("Must specify URL"); 48. } 49. getEventSource(url); 50. if (eventSource !== null) { 51. if (eventOptions !== null) { 52. for (var i in eventOptions) { 53. JSF.sse.addOnEvent(i, eventOptions[i]); 54. }

55. } 56. } 57. 58. }, 59. 60. /** 61. * Register a callback for error handling. 62. * <p><b>Usage:</b></p> 63. * <pre><code> 64. * JSF.sse.addOnError(handleError); 65. * ... 66. * var handleError = function handleError(data) { 67. * ... 68. *} 69. * </pre></code> 70. * 71. * @member JSF.sse 72. * @param callback a reference to a function to call on an error 73. */ 74. addOnError: function addOnError(callback) { 75. if (eventSource !== null) { 76. if (typeof callback === 'function') { 77. eventSource.addEventListener('error', callback, false); 78. } 79. } 80. 81. }, 82. 83. /** 84. * Register a callback for event handling. 85. * <p><b>Usage:</b></p> 86. * <pre><code> 87. * JSF.sse.addOnEvent('timeEvent', handleEvent); 88. * ... 89. * var handleEvent = function handleEvent(data) { 90. * ... 91. *} 92. * </pre></code> 93. * 94. * @member JSF.sse 95. * @param eventName the event name associated with the message. 96. * @param callback a reference to a function to call for processing 97. *messages with a specific event name. 98. */ 99. addOnEvent: function addOnEvent(eventName, callback) { 100. if (eventSource !== null) { 101. if (typeof callback === 'function' && eventName !== null 102. && typeof eventName !== 'undefined') { 103. eventSource.addEventListener(eventName, callback, false); 104. } 105. } 106. 107. } 108. }; 109. 110. }(); 111. }

www.JAXenter.com | October 2011

Composite Components

a JSF component <h:outputScript> to specify the target location of the JavaScript file. On line 24 we are using a function from the JSF SSE JavaScript library to establish a connection to the server endpoint using the url and events attribute values. So, the idea is that you can drop one of these components in your JSF view to connect to a server endpoint. Lets take a look at the JavaScript library that contains the functions for performing SSE actions (Listing 4): Line 9: JSF namespace declaration. Line 21: A private function that creates an EventSource instance to connect to the server endpoint specified by the provided url. Line 45: The public connect function that is used in the SSE composite component in Listing 3. This function calls through to the private function getEventSource and registers the application callback functions using a public addOnEvent function (line 99).

Listing 7: stock.xhtml stock ticker com posite component


1. <!DOCTYPE html> 2. 3. <html xmlns="http://www.w3.org/1999/xhtml" 4. xmlns:h="http://java.sun.com/jsf/html" 5. xmlns:f="http://java.sun.com/jsf/core" 6. xmlns:ui="http://java.sun.com/jsf/facelets" 7. xmlns:ez="http://java.sun.com/jsf/composite/stockinfo" 8. xmlns:composite="http://java.sun.com/jsf/composite"> 9. 10. <composite:interface> 11. 12. </composite:interface> 13. 14. <composite:implementation> 15. <br/> 16. <h:panelGrid columns="4"> 17. <h:outputText value="Space delimited symbol(s):" style="font-size: 18px;"/> 18. <h:inputText id="symbol" value="#{stockTickerBean.symbols}"/> 19. <h:commandButton id="submit" value="Get Quotes" action= "#{stockTickerBean.getStockInfo}"> 20. <f:ajax execute="@this symbol"/> 21. </h:commandButton> 22. <h:commandButton id="clear" value="Reset" action= "#{stockTickerBean.reset}"> 23. <f:ajax execute="@this symbol" render="symbol"/> 24. </h:commandButton> 25. </h:panelGrid> 26. 27. <br/> 28. 29. <div id="stockInfo" style="font-size: 16px;"> 30. <table id="stockTable" border="8" bordercolor="#000080" cellspacing= "10" style="visibility:hidden"> 31. <tr> 32. <th style="background-color:#b0c4de;text-align:left">Symbol </th><th style="background-color:#b0c4de;text-align:left">Open</th> 33. <th style="background-color:#b0c4de;text-align:left">Trade </th><th style="background-color:#b0c4de;text-align:left">Chg</th> 34. </tr> 35. </table> 36. </div> 37. 38. <br/> 39. 40. <ez:rss symbols="#{stockTickerBean.symbols}"/> 41. 42. <h:outputScript name="js/app.js" target="head"/> 43. 44. </composite:implementation> 45. 46. </html>

Listing 5: clock.xhtml the clock composite component


1. <!DOCTYPE html> 2. 3. <html xmlns="http://www.w3.org/1999/xhtml" 4. xmlns:h="http://java.sun.com/jsf/html" 5. xmlns:f="http://java.sun.com/jsf/core" 6. xmlns:ui="http://java.sun.com/jsf/facelets" 7. xmlns:composite="http://java.sun.com/jsf/composite"> 8. 9. <composite:interface> 10. 11. </composite:interface> 12. 13. <composite:implementation> 14. #{timeBean.time} 15. <div id="clock" style="font-size: 20px; border:2px solid blue"/> 16. <h:outputScript name="js/app.js" target="head"/> 17. 18. </composite:implementation> 19. 20. </html>

Listing 6: app.js partial JavaScript listing for clock component


1. 2. 3. 4. 5. 6. 7. 8. /** * Clock message handling function. */ function clockHandler(event) { var eventData = event.data.toString().replace(/^\s*/,"").replace(/\s*$/,""); var clock = document.getElementById("clock"); clock.innerHTML = eventData; }

www.JAXenter.com | October 2011

Composite Components

Line 74: A public utility function for registering an error processing callback function. With SSE you can register a function with the error event type. Line 99: A public utility function for registering callback functions for processing event types.

The clock composite component


The clock composite component is used to display the current time (Listing 5): Lines 4 7: Namespace declarations Lines 9 11: Notice this component has no attributes which is perfectly fine. If we wanted to make this clock component fancier we could, for example, define an attribute to indicate that our clock could display in analog or digital mode. Lines 13 18: The implementation of our component. On line 14, we are using the Expression Language (EL) to in-

voke a method on a managed bean to start the clock ticking. The managed bean could just utilize a java.util.Timer method to compose and send the current date/time string back to the client. Line 15 is a placeholder for where we will display the time event data from the server. On Line 16, we load a JavaScript file that contains application callback functions that will process the event data returned from the server. Lets take a look at the relevant section of code from this application JavaScript file for this clock component (Listing 6). Line 5: We obtain the event data Line 6: We obtain our div placeholder element (created in Listing 5, line 15). Line 7: We write the event data string (which is the current data / time)

The stock ticker composite component


This composite components implementation uses standard JSF components (Listing 7):

Listing 8: partial JavaScript Listing for stock ticker component


1. /** 2. * Server Sent Event message handling function dynamically builds a table 3. * based on the message data. 4. */ 5. function stockHandler(event) { 6. var eventData = event.data.toString().replace(/^\s*/,"").replace(/\s*$/,""); 7. var stockTable = document.getElementById("stockTable"); 8. var rowCount = stockTable.rows.length - 1; 9. if (eventData.length == 0) { 10. stockTable.style.visibility="hidden"; 11. clearTableRows(stockTable, rowCount); 12. return; 13. } 14. var quotes = eventData.split(" "); 15. if (quotes.length !== rowCount || quotes.length == 0) { 16. clearTableRows(stockTable, rowCount); 17. } 18. if (quotes !== null) { 19. stockTable.style.visibility="visible"; 20. var newRow, newCell; 21. for (var i = 0; i < quotes.length; i++) { 22. var fields = quotes[i].split(":"); 23. if (document.getElementById(fields[0]) !== 'undefined' && 24. document.getElementById(fields[0]) !== null) { 25. document.getElementById(fields[0]).innerHTML = fields[0]; 26. document.getElementById(fields[0]+1).innerHTML = fields[1]; 27. document.getElementById(fields[0]+2).innerHTML = fields[2]; 28. if (fields[3] == "UP") { 29. document.getElementById(fields[0]+3).innerHTML = 30. "<img src='resources/up_g.gif'/>"; 31. } else if (fields[3] == "DOWN") { 32. document.getElementById(fields[0]+3).innerHTML = 33. "<img src='resources/down_r.gif'/>"; 34. } else {

35. document.getElementById(fields[0]+3).innerHTML = ""; 36. } 37. } else { 38. newRow = stockTable.insertRow(stockTable.rows.length); 39. newCell = newRow.insertCell(newRow.cells.length); 40. newCell.id = fields[0]; 41. newCell.innerHTML = fields[0]; 42. newCell.align = "center"; 43. newCell.width = "20%"; 44. newCell = newRow.insertCell(newRow.cells.length); 45. newCell.id = fields[0]+1; 46. newCell.innerHTML = fields[1]; 47. newCell.align = "center"; 48. newCell.width = "20%"; 49. newCell = newRow.insertCell(newRow.cells.length); 50. newCell.id = fields[0]+2; 51. newCell.innerHTML = fields[2]; 52. newCell.align = "center"; 53. newCell.width = "20%"; 54. newCell = newRow.insertCell(newRow.cells.length); 55. newCell.id = fields[0]+3; 56. if (fields[3] == "UP") { 57. document.getElementById(fields[0]+3).innerHTML = 58. "<img src='resources/up_g.gif'/>"; 59. } else if (fields[3] == "DOWN") { 60. document.getElementById(fields[0]+3).innerHTML = 61. "<img src='resources/down_r.gif'/>"; 62. } else { 63. document.getElementById(fields[0]+3).innerHTML = ""; 64. } 65. 66. newCell.align = "center"; 67. newCell.width = "20%"; 68. } 69. } 70. } 71.}

www.JAXenter.com | October 2011

Composite Components

Line 18: The input text field that will store the entered stock symbol data to a managed bean. Lines 19 21: The button that, when activated, will fire a request over Ajax to invoke a method getStockInfo on a

Listing 9: rss.xhtml RSS composite com ponent


1. <!DOCTYPE html> 2. 3. <html xmlns="http://www.w3.org/1999/xhtml" 4. xmlns:h="http://java.sun.com/jsf/html" 5. xmlns:f="http://java.sun.com/jsf/core" 6. xmlns:ui="http://java.sun.com/jsf/facelets" 7. xmlns:composite="http://java.sun.com/jsf/composite"> 8. 9. <composite:interface> 10. <composite:attribute name="symbols" required="true"/> 11. </composite:interface> 12. 13. <composite:implementation> 14. <br/> 15. <h:panelGrid columns="4"> 16. <h:commandLink id="submit" value="Get Stock News" action="#{rssBean.getStockNews}"> 17. <f:setPropertyActionListener value="#{cc.attributes.symbols}" target="#{rssBean.symbols}"/> 18. <f:ajax execute="@this"/> 19. </h:commandLink> 20. </h:panelGrid> 21. <br/> 22. 23. <div id="rssInfo" style="font-size: 16px; border:2px solid blue; height : 150px; overflow : auto; visibility:hidden"/> 24. 25. <h:outputScript name="js/app.js" target="head"/> 26. 27. 28. </composite:implementation> 29. 30. </html>

managed bean. This method could utilize a java.util.Timer method to reach out to a stock quote service periodically, and send the event data back to the client. Lines 29 36: This is the placeholder area for our dynamic table to display the stock data from the server. Line 40: This component uses the rss composite component (more about that next), (Listing 8). The stockHandler function receives the event data, that is the stock quote information and performs some JavaScript magic to dynamically build and display the stock table.

The RSS composite component


The rss composite component displays a link, that when activated, will dynamically display stock company news relevant to the stock symbols that were entered (Listing 9): Line 10: This component defines an attribute for accepting stock symbols. The stock symbols are used to get the rss information. Lines 16 19: The link, that when activated, will propagate the stock symbols to a managed bean and invoke the method getStockNews on the managed bean over Ajax. Line 23: A div placeholder for displaying the returned rss information from the server (Listing 10). The rssHandler callback function writes the rss event data into the div that was created in Listing 9.

Server implementation considerations


In the Server Requirements section, we mentioned some of the requirements for sending SSE event data to the client. Server implementations need to maintain an open connection to stream event data to the client. For Java implementations, a Servlet utilizing the Servlet 3.0 Asynchronous API is one choice. For other implementations, NodeJS or PHP could be used as well. Server implementation details are not mentioned, since the main focus of this article is the JSF user interface and components.

Conclusion
This article has been all about creating JSF composite components that make up the user interface for a stock quote application that uses HTML5 Server Sent Events. JSF 2 introduced the world to composite components, and together with JavaScript, provides a component author with a multitude of options for creating dynamic components. HTML5 Server Sent Events are the second class citizen to HTML5 WebSockets, but it does offer an HTTP solution to event streaming without switching to another protocol.

Listing 10: Partial JavaScript Listing for RSS composite component


1. function rssHandler(event) { 2. var eventData = event.data.toString().replace(/^\s*/,""). replace(/\s*$/,""); 3. var rssInfo = document.getElementById("rssInfo"); 4. if (eventData.length == 0) { 5. rssInfo.style.visibility="hidden"; 6. } else { 7. rssInfo.style.visibility="visible"; 8. } 9. rssInfo.innerHTML=""; 10. rssInfo.innerHTML = eventData; 11. }

Roger Kitain is a Principal Software Engineer at Oracle where he has spent most of his time in the web technology space since 1997. Roger has been involved with the JavaServer Faces technology since its inception, and has co-led the JavaServer Faces Specification since JSF 1.2. He has presented at many conferences including JAX, JSF Summit, JavaOne, Dexoxx, Jazoon, Ajax Experience, Ajax World.

www.JAXenter.com | October 2011

Apache Wicket

Working with REAL Java objects

The Fun Web Framework


There is no lack of variety when choosing your Java technology stack. In attempts to get away from both the roll your own [everything] thinking that so many companies fall prey to, as well as the everything must be a standard philosophy of others, a wide range of varying approaches to each layer of the Java architecture has sprung up over the past years. The UI layer is no stranger to the struggle of competing technologies. With all of the options that you are presented with, how are you ever to choose? While no writer can make that choice for you, what we can do is introduce you to another option that you may want to consider, with the hopes that it will intrigue you enough to try it out. In this article, Ill introduce you to Apache Wicket.

by Jeremy Thomerson
As you may suspect by the articles title, Wicket is my preferred UI framework for most of the applications I write. Whether you end up sharing that same passion for this great framework or whether it fits the type of application you desire to write is up to you and your circumstances. But, read on and you may find another great technology to add to your go-to stack.

nent, as well as all the others, automatically retain their state throughout the various other requests that the user makes.

How does it work?


To achieve the level of UI complexity described above, many methodologies require that each component on the page has some level of knowledge of the other components on the page. In these other technologies, when I click a link in one component, it needs to embed the state of the other components into its request. Perhaps this goes in the URL, or perhaps it is stored in the session. Maybe each component has a cookie prefix and stores its state in a cookie. Or, perhaps your programmers get to spend most of their time configuring interactions between components in a complex XML file that ties the inputs and outputs of various components together. Whatever the case, its not simple programming some of it isnt even programming at all and it requires a constant awareness of the fact that you are writing a stateful application on a stateless protocol. Wicket gets around this by introducing a sort of state engine to the HTTP interactions of our web applications. When a user first visits a page, an instance of a Java class is instantiated. When constructing that class, you construct its components just like you would instantiate any other Java class, i.e. new MyComponent("SomeID"). When the state of those components change, they store that state within themselves as real variables with real types. After that initial page render, though, Wicket does not discard the page object that was instantiated. The entire component hierarchy is stored in the users session (as well as disk in an efficient manner not detailed in this article). So, when they click a link to take some action on the page, submit a form, et cetera, all of that state is still contained in those classes. This is what makes it so simple (and fun!) to work with. Now, the first thing that most people think is wont that use a ton of memory? The answer is no! Many people have fallen for the trap of assuming that this method is a memory-waster, but then find that this assumption amounts to premature optimization. Thats not to say that you cant kick yourself while using Wicket you can certainly do things that will make your ses-

What is Wicket?
Wicket is a component-oriented Java web framework, which focuses on making it easy to write reusable code. It requires no XML configuration (aside from a few lines in your standard web.xml deployment descriptor), making it refreshing to work with. It encourages a clean separation between your logic and your markup, appealing to most programmers desire for a sense of order. With Wicket your code is just Java and your markup is just HTML. This makes it much easier for HTML guys to assist with the project without fear of messing something up and without having to learn a complex templating language, parameter names and values, et cetera. Wicket appeals to a person who loves object-oriented programming. Each component on your page is a real Java object. It can hold state and perform useful functions just like any Java object. The nice thing about this is that this state persists through web requests to abstract the complexities of the stateless hypertext transfer protocol from you. Imagine that you have a page that has an accordion-style panel in the side navigation bar, as well as a complex data table in the main content area. A user comes to this page and expands a section of the accordion. In your code, you may call setExpandedSection(index), or you may have setExpanded(true) on it and false on the others. However it is that you model your component, you can store that user-selection as a regular Java member variable inside your accordion component or one of its children. Now, when the user clicks a link to re-sort your complex data table, the table itself does not need to know about the state of the accordion component or any other component on the page. But, the accordion compo-

www.JAXenter.com | October 2011

10

Apache Wicket

sion size explode. We will discuss more about that below in the section What Are Models?. If youre really concerned about being able to validate my assertion that Wicket will not use more memory than other frameworks, you may want to check out http://tinyurl.com/wicket-perf-1 and for a more elaborate comparison of Wicket versus several alternative frameworks, see http://tinyurl.com/wicket-perf-2 (both written by Peter Thomas). If you can just trust me for now, continue on.

How to get started


Without further ado, how do you jump right in and try Wicket out? If you have Maven installed, it could not be any easier. Simply jump over to http://wicket.apache.org/start/quickstart. html, fill in your desired package group and artifact ID's and run the provided command. A working quick-start application will be generated for you. Running mvn eclipse:eclipse (or the equivalent for your IDE) will set up the project dependencies. If you are using Eclipse go to the file menu, select Import, then Import an existing project and select the directory where your quickstart was generated. Find the Start.java file, open it, and run it as a Java application. Navigate to http://localhost:8080 and you will see your hello world application in action. By running the Start class in your IDE's debug mode (Eclipse: Debug as | Java application) instead of the normal run mode, you will be able to set breakpoints and debug your application to see how it works. For more complex quick-start applications featuring Spring, Guice, JPA, et cetera, see jWeekends excellent LegUp resources at http://tinyurl.com/wicket-legup.

controls it you simply add the wicket:id attribute to it. We had two things in this markup that were dynamic. The most obvious was the link. The second is a span that renders the value of the counter on each page render. We use a span tag simply because we need a markup placeholder for the value to be inserted, and a span tag will not disrupt the structure of our other markup (Listing 1). Now, lets look at the associated Java code in Listing 2. The first thing you should note is the name and placement of the files. By default, for any Wicket component (pages, as we are using here, are also components, so the same rule applies), Wicket will look in the same package directory on the classpath for a file with the same name, with the extension .html (if you are rendering XML, this would still apply, but with a .xml extension). This behavior can be re-configured, but for this article we will not get into that. There are online resources that can assist you with that if needed. When you examine the actual code, you will see several parts. The first thing you see is the counterModel. You notice that it implements IModel. Models are extremely important in Wicket. Theyre also generally one of the least understood concepts when programmers first adopt Wicket. Well discuss them more later. For now, suffice to say that they are a wrapper for retrieving or setting a piece of data, and this AbstractReadOnlyModel, as its name implies, is simply a wrapper for retrieving data. We implement the getObject method to retrieve the current value of counter on every invocation. This model is then passed to a Component. In this case the component is

Hello world
The hello world part is already done for you by the archetype. So, lets create a simple example of a link that increments a counter on the page. To get started (assuming you have the simple quickstart above running), find the HomePage.java and HomePage.html files and open them in your editor. Note that unless otherwise mentioned, all examples in this article will be based on the latest stable release, 1.5.1. Lets look at the HTML first. The first thing that you probably notice is that it is just regular HTML. This is by design. Markup should not contain logic thats Wickets philosophy. To tie a piece of markup to corresponding Java code that

Listing 2: HomePage.java
public class HomePage extends WebPage { private static final long serialVersionUID = 1L; private int counter = 0; public HomePage() { IModel<Integer> counterModel = new AbstractReadOnlyModel<Integer>() { private static final long serialVersionUID = 1L; @Override public Integer getObject() { return counter; } }; Label label = new Label("counter", counterModel); add(label); Link<Void> link = new Link<Void>("increment") { private static final long serialVersionUID = 1L; @Override public void onClick() { counter++; } }; add(link); } }

Listing 1: HomePage.html
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4strict.dtd" > <head> <title>Wicket Quickstart Archetype Homepage</title> </head> <body> <strong>Wicket Quickstart Archetype Homepage</strong> <br/><br/> Click <a href="#" wicket:id="increment">this link</a> to increment the following counter:<br /> Counter: <span wicket:id="counter">123</span> </body> </html>

www.JAXenter.com | October 2011

11

Apache Wicket

Figure 1: Example of a simple form

What about AJAX?


Okay, so its easy to make a link. So what, right? Now watch how easy it is to make that link an AJAX link that fully supports non-AJAX requests (Listing 3). First, we make our label instance final so that we can access it within the anonymous inner class and we call setOutputMarkupId(true) so that its unique ID is rendered in the span tag and it can be found in the DOM on the client-side. We change our Link class to AjaxFallbackLink and change the onClick method signature to match the superclass. The AjaxRequestTarget that is passed in can be thought of as a queue of things to send back in XML to the client side for processing. By adding the label to that queue, it will be re-rendered, streamed across the wire in XML and replaced in the DOM on the client-side. When it is re-rendered, it will use its model (remember counterModel?) to get the up-to-date value to render. All without us writing a line of code that does any transformations or DOM manipulation! Why do we check if the AjaxRequestTarget is null? Because this link will automatically work for you on browsers that do not have JavaScript enabled. In this event, the page would simply re-render just like it did with a regular link. Yes, you heard me it degrades gracefully without any additional work! Almost too good to be true, right? Youll find that Wicket works this way for you by default most of the time. Form submissions and even file uploads can be done in either regular HTTP or AJAX with very little, if any, extra work. And in the recently-released 1.5 version, a very handy event mechanism is added to make the work of adding components to the AjaxRequestTarget even easier.

a Label. A label simply takes whatever tag it is associated to in the markup and replaces the body of that tag with the value retrieved from the model it is given. In this case, our span tag will replace 123 (its static body in the markup) with the value of our counter, which on the first page render will be zero. The next thing you see is the link. It gives you just a glimpse of the power of Wicket. Were using an anonymous inner class here to implement the link. If you had multiple places in your application that needed to increment an integer, you could replace this with a concrete class simply by extracting the anonymous inner class into a real top-level class. Now, look at how simple it is to implement an action of any sort on a link. You simply override the onClick method and put your business logic in there. Obviously incrementing a counter is a simple example, but you could just as easily call a service-layer method that deleted or edited something in your domain, sent an email, or made a web service call. Wicket does the hard part for you. You implement the logic and you dont have to worry about how to get a URL that will invoke that small bit of logic. You dont have to worry about where to store the current state of the counter. All you have to do is write your code that performs the work that your application is designed to do. Thats why I love Wicket!

Working with user input


In many web applications, a lot of the work to be done in building the app goes into the forms that accept user input. In Wicket, forms are regular objects just like all other components. To see an example, lets look at a simple form that accepts a users name, email, and date of birth (figure 1). Looking at the HTML (Listing 4), you see that there is nothing special about it. Your designers can give you an HTML

Listing 3: HomePage.java (only the con structor is shown)


public HomePage() { IModel<Integer> counterModel = new AbstractReadOnlyModel<Integer>( ){} // above code folded for brevity final Label label = new Label("counter", counterModel); add(label.setOutputMarkupId(true)); AjaxFallbackLink<Void> link = new AjaxFallbackLink<Void>("increment") { private static final long serialVersionUID = 1L; @Override public void onClick(AjaxRequestTarget target) { counter++; if (target != null) target.add(label); } }; add(link); }

Listing 4: Example of a simple form


<html xmlns:wicket="http://wicket.apache.org/dtds.data/ wicket-xhtml1.4-strict.dtd" > <head> <title>Quickstart Homepage</title> </head> <body> Add / Edit Person: <div wicket:id="feedback"></div> <form wicket:id="form"> First Name: <input type="text" wicket:id="firstName" /><br /> Email Address: <input type="text" wicket:id="email" /><br /> Date of Birth: <input type="text" wicket:id="dob" /><br /> <input type="submit" value="Save" /> </form> </body> </html>

www.JAXenter.com | October 2011

12

Apache Wicket

form and you can add wicket:id attributes to the input fields and the form itself. The div with the wicket:id feedback is a placeholder for a built-in Wicket component that shows the user all feedback messages that were generated by the form. In the picture above, the user has just submitted the form with bad data which caused validation messages to appear in our feedback panel component. These can easily be customized to have a feedback panel near each form field that only shows the messages for that particular field a common requirement in many applications. Now looking at the Java code (Listing 5), you see that we created two constructors. This is so the form can be used as both an add person and an edit existing person form. By default, the no-argument constructor is called which makes this an add person form because it is using a model that holds a new person. But, a link could easily be written that shows the user an edit person page simply by passing a model to the page with an existing person. (Note that we dont cover that example in this article, but if you were doing this, you would likely want to use a LoadableDetachableModel, which is discussed more in the section on models.) Next you see that we instantiate our Form object. We implement the onSubmit method and make it contain our

business logic in this case a simple call to a service-layer class. Moving along, you see where we create each field and configure it with our UI rules which fields are required, and what is required of them (for instance, a valid email address format). What you dont see is refreshing no calls to HttpRequest to get strings out, no conversion of strings to dates, no manual retrieval of data from our form post and no manual setting of data on our backing Person object. In long forms, this saves hundreds of lines of copy-and-paste and highly error-prone code. This is because we are dealing with real Java objects not a bunch of strings that have to be manually manipulated. See the form processing image in the top ten list and the link to the full top ten list below for more information. Note that we are using a service-layer object (IPersonService) to do our persistence. This is a Spring-managed bean, and it is extremely simple to use because of Wickets built-in Spring (or Guice, if you prefer) integration.

What are models?


In the code examples, youve seen several mentions of models, earlier described as a wrapper for retrieving or setting a piece of data. So, just what is a model, and why is it so important? As mentioned earlier, Wicket stores your entire component hierarchy (the page and all the components you added to it, as well as components added to those components and so on) in memory, and then to disk so that you have a stateful way of working with Java objects over the stateless HTTP. But these components that display this data do not necessarily need to store the data itself between requests. They only need to store their state perhaps a flag indicating if they are visible or invisible, enabled or disabled, expanded or collapsed. It is very likely that the actual data they are displaying is already persisted elsewhere likely in the database meaning that we don't really need to save it to the users HTTP sessions. This is one reason models exist to cut down on the amount of memory needed to persist our component hierarchy. A second, and just as important reason, is to abstract the retrieval and storage of data from the component itself. Think of our simple TextField component in our form example above. It does not need to know if the string that it is editing is coming from the session, from a web service, or from a field on a POJO. It simply needs to be able to get a string from somewhere and set an edited string somewhere. The IModel interface has two methods for this getObject and setObject that allow it to do just that. Before you start using Wicket, you should review my resource page on them at http://wickettraining.com/resources/wicket-models.html

Listing 5: Form object


public class HomePage extends WebPage { @SpringBean IPersonService personService; public HomePage() { this(new Model<Person>(new Person())); } public HomePage(IModel<Person> model) { Form<Person> form = new Form<Person>("form", model) { }; TextField<String> firstName = new TextField<String>("firstName", new PropertyModel<String>(model, "firstName")); firstName.setRequired(true); form.add(firstName); TextField<Date> dob = new TextField<Date>("dob", new PropertyModel<Date>(model, "birthDate")); dob.setRequired(true); form.add(dob); TextField<String> email = new TextField<String>("email", new PropertyModel<String>(model, "emailAddress")); email.setRequired(true); email.add(EmailAddressValidator.getInstance()); form.add(email); add(form); add(new FeedbackPanel("feedback")); } }

Ten things every Wicket Programmer should know


This is a condensed version of my list of the top ten things that every Wicket programmer should know. For the complete version, see http://wickettraining.com/resources/ten-thingsevery-wicket-programmer-should-know.html 1. Models: Really make sure that you understand models before writing any large application in Wicket.

www.JAXenter.com | October 2011

13

Apache Wicket

Figure 2: Form processing lifecycle

2. Pull, dont push: In general, your components should be able to pull their state rather than having some other component push the state on it. The example in Listing 6 demonstrates what this means and why its important. The key is that the constructor only runs once, but many things on the page might change state after the constructor is run. If you push your state into components in your constructor, they are out-of-date as soon as another component changes state. The only alternative is that every component must know about all other components that share state and thats not the Wicket way. Your components should be independent and reusable. 3. Wicket is a UI framework: Dont write middle tier or persistence code in Wicket. 4. Keep markup and code clean and compact: Become familiar with and use the various aspects of Wicket that allow for reusability panels, markup inheritance, and fragments as examples. 5. Match your hierarchies: It wont take you long at all to learn this rule, but the hierarchy of components in your markup (tags with a wicket:id attribute) must match the hierarchy in your Java code. 6. Form processing lifecycle: When dealing with forms, it is important to understand the order of operations of the form post processing. If any step in the process fails the

onError method of your form and submitting button will be called rather than the onSubmit method (figure 2). 7. Java nuances: There are two Java nuances that catch many Wicket newcomers off-guard serialization and the presence of anonymous inner classes. Become more familiar with both. 8. Unit testing: Testing your Wicket code is made relatively easy by using WicketTester. Try it out. 9. i18n: Internationalization is made very easy with Wicket. Become familiar with things like wicket:message and file naming standards for Wickets built-in i18n support. 10. Where to find help: Wicket code is well documented, so reading JavaDocs is a good start. Wicket examples can be viewed online at http://wicketstuff.org/wicket. Additionally, Wicket has one of busiest and most helpful mailing lists of any open source project. For more information on the Wicket mailing lists, see http://wicket. apache.org/help/email.html.

In conclusion
I chose Apache Wicket because other frameworks sucked the fun out of web programming (okay, this is subjective, but I can say that I didnt personally enjoy them). Most of my time seemed to be spent dealing with pushing state around or writing configuration in XML. Every little change required changes in multiple files many times in XML, Java, and specialized markup files. It was hard to make cohesive reusable components. A few days with Wicket made me see how drastically different it was. I was writing real Java object-oriented code, and easily creating reusable components. I hope that you will give it a few days for your own project or experiment so that you too can discover how much fun web programming can be. For more information on Wicket, see http://wickettraining. com/resources

Listing 6: Independent and reusable compo nents


// assuming children is an instance of IModel<Collection<DomainObject>> // DON'T do this: this is PUSHING data: link.setVisible(children.getObject().isEmpty()); // DO this instead: Label label = new Label("label", someModel) { public boolean isVisible() { return children.getObject().isEmpty(); } }; // WHY? Because you may have this elsewhere on the page, and your label would not appear after you press this link and the page is re-rendered because the 'setVisible' line above would not run again: Link<Void> link = new Link<Void>("link") { public void onClick() { children.getObject().add(new DomainObject()); } };

Jeremy Thomerson has helped numerous companies efficiently utilize leading Java open source technologies, including Wicket, Spring, Lucene, Hibernate and more. For the past several years, he has owned and operated the leading U.S. company providing Wicket training and consulting services.

www.JAXenter.com | October 2011

14

Special 20% discount for JavaTech Journal readers!


Enter promo code JAXMAGF2 when registering!

31st October 2nd November 2011 Park Plaza Victoria

The Conference for Java, Cloud, Android & Agile

www.jaxlondon.com
Java Core JBoss Spring
Technical Architecture

Java EE Agile

Cloud

Android

Java Tech & Tools

follow us:
Presented by:

twitter.com/jaxlondon

JAX London

JAX London
Organized by:

TM

Europes #1 Conference Series for Enterprise Java


Learn about the latest developments and technologies in the Java ecosystem. Sessions include:
Workshops:
EST R

Java EE Day:
Modular Apache Java

in Practice A Workshop on Web-based Distributed Systems


Ian Robinson (Neo Technology) & Jim Webber (Neo Technology)

EJBs for Enterprise OSGi

Tim Ward (IBM)

TomEE Java EE Web Profile on Tomcat

Java he T

EE 6/7: Productivity with Joy

Jonathan Gallimore (Wave2 Media Solutions)

Adam Bien (Independant Consultant, Java EE Expert)

EE 7: Developing for the Cloud

Busy Java Developers Workshop on Android

Arun Gupta (Oracle)

Ted Neward (Neward & Associates)

Agile Day:
Think

Java Tech & Tools:


ig B

you don't need software craftsmanship?

Blobs: moving big data in and out of the cloud in the Java enterprise

Sandro Mancuso (UBS)


essons L

Adrian Cole (Cloudsoft)


rails G sing U

Peter Ledbrook (VMware)

a pull system for Just-In-Time development and Continuous delivery the writing is on the wall
John Stevenson (Atlassian)

Learned from Becoming Agile at Electronic Arts: Using Scrum and Kanban to develop EA's Physics Engine and Romans Top Ten Product Backlog Tips
Roman Pichler (Pichler Consulting Ltd) & Mike Bassett (Electronic Arts)

apping, M ocial S pring S The

GIS and geolocating data in Java

Spring Day:
Data

Joachim Van der Auwera (Geosparc nv)

access 2.0? Please Welcome Spring Data! and Scala

Media Programming in Java cleaning your code base with Java 7

Oliver Gierke (SpringSource - a division of VMware)


Spring

Khanderao Kand (GloMantra Inc) Martijn Verburg (Ikasan) & Ben Evans

Eberhard Wolff (adesso AG)


WaveMaker

Future of Messaging: RabbitMQ and AMQP

Spring Roo SpringSource Tool Suite: Choosing the right tool for the right job 3.1 in a Nutshell

Eberhard Wolff (adesso AG)

Martin Lippert (SpringSource a division of VMware)


pring S

Big Data & Cloud Day:


Public Open Cloud n A

Sam Brannen (Swiftmind)

vs Private Cloud: A Convenient Fiction

Sam Newman (ThoughtWorks)

Android Day:
uilding B

Source PaaS Storage Simplified

Paul Fremantle (WSO2) Adrian Cole (Cloudsoft)

Learned

The Guardian's Android app Lessons

Rupert Bates (Guardian.co.uk)


Busy

Java Developers Guide to Android: UI Getting Git onto Android

Introduction to Neo4j (and Doctor Who)

Ted Neward (Neward & Associates)


reating Agit: C Roberto Tyley ndroid A

Ian Robinson (Neo Technology)

Java Core Day: To Java 8 and Beyond!


Martijn Verburg (Ikasan) & Ben Evans
Concurrency To

activity launch modes and tasks

Gonalo Silva (Novoda)

in the Java language and platform

Architecture Day:
Thinking Busy

Fredrik Ohrstrom (Oracle)

Distributed to Improve Agility

Java SE 8 and Beyond!

Jamie Allsop (NYSE-Euronext)

Simon Ritter (Oracle)

Java Developers Guide to NoSQL

Ted Neward (Neward & Associates)

www.jaxlondon.com

ZK

Ajax without JavaScript

Introducing ZK
ZK is a highly productive open source Java framework for building amazing enterprise web and mobile applications. This article introduces the reader to using ZK for development of dynamic and robust Java web applications. The author explores mainstay ZK features, which are employed for ZK development, and touched upon more complex patterns.

by Timothy Clare
In this article, we will cover the following ZK features and topics: ZK: History and Architecture Implementing a ZK application

Model: Employee.java, EmployeeService.java View: index.zul Controller: EmployeeController.java

Model
This section introduces the implementation of the model using ZK. The model contains two files, Employee.java and EmployeeService.java. These files are a simplified version of the model and therefore do not include any database functionality. As ZK is predominantly server-side, database functionality is trivial to add. Server-side resources can be accessed directly without any need for connectors. In this example application the model's implementation is kept simple using a synchronized list. The following code outlines the service:
package org.zkoss.jtjexample.service; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.zkoss.jtjexample.bean.Employee; import org.zkoss.zul.ListModelList; public enum EmployeeService { INSTANCE; private List<Employee> _employees = Collections.synchronizedList (new ArrayList<Employee>()); private EmployeeService() { _employees.add(new Employee("Roger", "Charles", 21)); _employees.add(new Employee("Gary", "Peters", 27)); _employees.add(new Employee("Edward", "Daniels", 35)); } public ListModelList getModel() {

ZK: history and architecture


ZK has been renowned for its Ajax without JavaScript approach since 2005, enabling developers to build rich internet applications transparently, without any knowledge of Ajax and JavaScript. The client engine and update engine in ZK play the roles of pitcher and catcher, rendering Ajax communication transparent to developers. Events triggered by users are encapsulated and marshaled to event listeners running at the server. In 2010, ZK introduced Server+client Fusion architecture which combines the server-centric approach with optional client-side control. The server-centric solution to Ajax brings a productivity boost, robustness, and security to Web application development; while client side solutions endow Web applications with greater controllability, and the ability to leverage client side resources. Throughout the years, ZK has provided developers which a highly productive way of building Java based web applications. The best way to show ZK's power is to introduce a non-trivial example of working with ZK. The next section introduces an example application in digestible chunks.

Implementing a ZK application
This example application follows the MVC architectural pattern, separating business logic from the user interface, enabling the separation of user interfaces (contained in zul files) from java business logic. This separation of concerns leads to cleaner and more maintainable code. The attached example contains numerous files. The table below categorizes these files with respect to the MVC pattern:

www.JAXenter.com | October 2011

17

ZK

Figure 1: Main.zul output

return new ListModelList(_employees, true); } }

other. In general terms the majority of components in ZK can be children of any other components. This is called the nesting of components.

The service is basic Java except for the method getModel(). This method returns a class of type ListModelList which is used to provide ZK with a representation of data. The ListModelList is an intermediary between raw data in Java and ZKs representation of the raw data. When constructing the model, a List is passed along with a boolean. This indicates whether ZKs model will copy the available data into its own internal list or use the provided list. In this case, as the application is simple the model is instructed to use the _employees list directly. If this application was more complex it would be beneficial to add another layer between ZKs representative model and the application's model layer. A good example of this can be found in the ZK Essentials documentation.

Nesting ZK components
In this example it is better to split the functionality between departments and employees and not have the two areas over-

Listing 2: Nested components


<?page title="Employee manager" contentType="text/html;charset=UTF-8"?> <div id="employeediv" apply="org.zkoss.jtjexample.controller.EmployeeController" hflex="true"> <vlayout> <listbox> <auxhead> <auxheader label="Employees" colspan="4" /> </auxhead> <listhead> <listheader label="ID" hflex="2" /> <listheader label="First Name" hflex="3" /> <listheader label="Last Name" hflex="3" /> <listheader label="Age" hflex="1" /> </listhead> </listbox> <groupbox hflex="true"> <caption label="Employee" /> First Name: <textbox id="txtFirstName" cols="20" constraint="no empty" /> Last Name: <textbox id="txtLastName" cols="20" constraint="no empty" /> Age: <intbox id="intAge" cols="3" constraint="no empty, no zero" /> <button id="btnAddEmployee" label="Add" width="60px" height="24px" /> <button id="btnUpdateEmployee" label="Update" width="60px" height="24px" /> <button id="btnDeleteEmployee" label="Delete" width="60px" height="24px" /> </groupbox> </vlayout> </div>

View
In this section, we discuss the planning and implementation of the GUI using the vast array of Ajax controls provided by ZK. Designing the interface: The ZK framework uses ZUML markup to describe GUIs; storing markup within *.zul files. ZUML is a powerful concept enabling developers to rapidly implement complex GUIs. In the following sections we will demonstrate using ZUML to implement powerful interfaces. Using ZK components: Nowadays, most people are familiar with markup languages due to the extensive use of both HTML and XML, hence ZKs ZUML should instantly have a familiar feel. Firstly, a simple div is defined. As shown in Listing 1, attribute id is used to set certain properties of the window. id is ZKs reference to the control. One of the most powerful concepts in ZK is its component model; the model affords developers the ability to place components inside each

Listing 1: Simple zul file


<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./employeediv"?> <?page title="Employee manager" contentType="text/html;charset=UTF-8"?> <div id="employeediv"> </div>

www.JAXenter.com | October 2011

18

ZK

Listing 3: Example controller


public class EmployeeController extends GenericForwardComposer { /** * */ private static final long serialVersionUID = -9089818718875587898L; }

lap. Therefore an easy method of separation is needed while enabling one to switch back and forth quickly. Luckily ZK has hundreds of components to choose from. In this instance it would seem like a tabbox would work best. Therefore the

Listing 4: A part of index.zul


<div id="employeediv" apply="org.zkoss.jtjexample.controller.EmployeeController" hflex="true">

Listing 5: EmployeeController.java
public class EmployeeController extends GenericForwardComposer { /** * */ private static final long serialVersionUID = -9089818718875587898L; private static final Log log = Log.lookup(EmployeeController.class); private Employee _currentEmployee; private ListModelList _model = EmployeeService.INSTANCE.getModel(); Listbox lstEmployee; Textbox txtFirstName, txtLastName; Intbox intAge; public Employee getCurrentEmployee() { return _currentEmployee; } public void setCurrentEmployee(Employee currentEmployee) { this._currentEmployee = currentEmployee; } public ListModel getEmployeeModel() { return _model; } // click events public void onClick$btnAddEmployee() { String firstName = txtFirstName.getText(); String lastName = txtLastName.getText(); int iAge = Integer.parseInt(intAge.getText()); Employee employee = new Employee(firstName, lastName, iAge); if (!_model.add(employee)) { reportError(Messages.getString("EmployeeController.0"), employee); } }

public void onClick$btnUpdateEmployee() { if (lstEmployee.getSelectedItem() != null) { Employee employee = (Employee) (lstEmployee.getSelectedItem() .getValue()); employee.setFirstName(txtFirstName.getText()); employee.setLastName(txtLastName.getText()); employee.setAge(Integer.parseInt(intAge.getText())); } else { UiUtils.showMessage(Messages.getString("EmployeeController.2")); } } public void onClick$btnDeleteEmployee() { if (lstEmployee.getSelectedItem() != null) { Employee employee = (Employee) (lstEmployee.getSelectedItem() .getValue()); if (!_model.remove(employee)) { reportError(Messages.getString("EmployeeController.3"), employee); } } else { UiUtils.showMessage(Messages.getString("EmployeeController.4")); } } private void reportError(String message, Employee employee) { StringBuilder sb = new StringBuilder(message).append(Messages.getString("Em ployeeController.5")).append(employee); final String error = sb.toString(); UiUtils.showMessage(error); log.error(error); } }

www.JAXenter.com | October 2011

19

ZK

tabbox is nested inside the window as demonstrated in Listing 2. The output of Listing 2 is shown in Figure 1. A couple of concepts needs to be highlighted here, first an observer will notice the apply and hflex attribute on the div. An apply attribute is used when one wants to link the ZK UI to a GenericForwardComposer. The GenericForwardComposer will be discussed in detail in the next section. For now, all one needs to know is that it acts as the controller in the MVC paradigm for ZK. The hflex attribute is used to layout components horizontally. This is complimented by vflex which enables vertical layout control. Both hflex and vflex inform ZK how the components parent should distribute the space among its children. In this case, the author used true as the tabbox is the only child of the window. Setting hflex to true indicates that the component should fill the entire space available. Us-

ing hflex and vflex one can create complicated layouts efficiently. Looking into hflex and vflex in more detail is beyond the scope of this article, for more information please refer to the ZK Developers Reference guide. Defining a UI as demonstrated is a simple affair when using ZK. This tutorial uses the XML option, however, it is also possible to define a UI entirely using Java. Having introduced the basic view it is time to move on to discuss the controller and databinder.

Controller and databinding


This section provides a step by step guide of the Controller and its functions. The controller handles all the business logic of the application and responds to events fired from the user interface. Currently our sample application includes add, update and delete events for both the employees and the departments.

Defining a controller
To create a controller the class org.zkoss.zk.ui.util.GenericForwardComposer should be extended. An example controller is shown in Listing 3. The composer then needs to be associated with a relevant view. Previously, the usage of apply was touched upon in Nesting ZK Components. In the following section the relationship is outlined in more detail.

Listing 6: Function signature for event cap turing


public void onClick$btnAddEmployee(ForwardEvent fe)

Listing 7: Initialize the databinder


<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit"?>

Associating the controller with the view


To implement the interaction between the View and Controller, data binding is used in this example. To implement
<listcell label="@{employee.lastName}" /> <listcell label="@{employee.age}" /> </listitem> </listbox> <groupbox hflex="true"> <caption label="Employee" /> First Name: <textbox id="txtFirstName" cols="20" constraint="no empty" value="@{employeediv$composer.currentEmployee.firstName save-when='btnUpdateEmployee.onClick'}" /> Last Name: <textbox id="txtLastName" cols="20" constraint="no empty" value="@{employeediv$composer.currentEmployee.lastName save-when='btnUpdateEmployee.onClick'}" /> Age: <intbox id="intAge" cols="3" constraint="no empty, no zero" value="@{employeediv$composer.currentEmployee.age save-when='btnUpdateEmployee.onClick'}" /> <button id="btnAddEmployee" label="Add" width="60px" height="24px" /> <button id="btnUpdateEmployee" label="Update" width="60px" height="24px" /> <button id="btnDeleteEmployee" label="Delete" width="60px" height="24px" /> </groupbox> </vlayout> </div>

Listing 8: index.zul complete code


<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" root="./employeediv"?> <?page title="Employee manager" contentType="text/html;charset=UTF-8"?> <div id="employeediv" apply="org.zkoss.jtjexample.controller.EmployeeController" hflex="true"> <vlayout> <listbox id="lstEmployee" multiple="true" rows="5" model="@{employeediv$composer.getEmployeeModel, load-after='btnAddEmployee.onClick, btnDeleteEmployee.onClick'}" selectedItem="@{employeediv$composer.currentEmployee}"> <auxhead> <auxheader label="Employees" colspan="4" /> </auxhead> <listhead> <listheader label="ID" hflex="2" /> <listheader label="First Name" hflex="3" /> <listheader label="Last Name" hflex="3" /> <listheader label="Age" hflex="1" /> </listhead> <listitem self="@{each='employee'}" value="@{employee}"> <listcell label="@{employee.id}" /> <listcell label="@{employee.firstName}" />

www.JAXenter.com | October 2011

20

ZK

data binding, the apply attribute of a component has to be set. Most components support the apply attribute. Listing 4 demonstrates the usage of the apply attribute. The EmployeeController is responsible for handling the user flow. The code of the EmployeeController is demonstrated in Listing 5. Listing 5 introduces two concepts firstly the ability to capture

an event and secondly invalidating a component. These are outlined next.

Capturing events
Event capturing in ZK is easy to implement, providing developers with enormous power. Listing 7 is a function signature to capture the onClick event from the button named btnAddEmployee. The onClick event is fired when a user clicks a button. The method signature in Listing 7 can be broken down into 3 parts. Firstly, the return type is void and method is public. The method name consists of the event name, followed by a dollar sign ($) and the name of the component whose event you want to trap. Then lastly, in this case the event type is a ForwardEvent. Using this technique it is possible to trap any event from any ZK component in a composer which is properly wired to the view (Listing 6).

Listing 9: The listbox with databinding


<listbox id="lstEmployee" multiple="true" rows="5" model="@{employeediv$composer.getEmployeeModel, load-after='btnAddEmployee.onClick, btnDeleteEmployee.onClick'}" selectedItem="@{employeediv$composer.currentEmployee}"> <auxhead> <auxheader label="Employees" colspan="4" /> </auxhead> <listhead> <listheader label="ID" hflex="2" /> <listheader label="First Name" hflex="3" /> <listheader label="Last Name" hflex="3" /> <listheader label="Age" hflex="1" /> </listhead> <listitem self="@{each='employee'}" value="@{employee}"> <listcell label="@{employee.id}" /> <listcell label="@{employee.firstName}" /> <listcell label="@{employee.lastName}" /> <listcell label="@{employee.age}" /> </listitem> </listbox>

Using databinding to load data from our service


The view is tied to the controller using the apply attribute as discussed in Associating the Controller with the view. Now ZKs data binding mechanism needs to be activated for this page. Remember, due to the include mode being deferred each zul is considered a separate entity, thus, they can each have their own data binding instance. To initialize the Annotated data binder, use the line shown in Listing 7.

index.zul and EmployeeController.java functionality step by step

Listing 10: EmployeeController source snip pet getAllEmployees and CurrentEmployee


private ListModelList _model = EmployeeService.INSTANCE.getModel(); public ListModel getEmployeeModel() { return _model; } public Employee getCurrentEmployee() { return _currentEmployee; } public void setCurrentEmployee(Employee e) { this._currentEmployee = e; }

To make it easier to explain how data binding works, Listing 8 contains the complete source of index.zul. This article will now step through each relevant part and include, where necessary the relevant parts of the applied controller.

Loading the data from the controller


It is time to start populating data. This is done by binding our controller functions for retrieving the models data with our listbox. The complete listbox zul is outlined in Listing 9. The controller source code in model="@ {employeediv$composer.getEmployeeModel}" and selectedItem="@{employeediv$composer.currentEmployee}" have return type of ListModelList (ZKs data representation) and a bean of type Employee respectively. The code snippet for this is shown in Listing 10. The controllers method responsible for retrieving all employee data is named getEmployeeModel().This method can be accessed in the view by setting the listboxs model attribute to employeediv$composer.getEmployeeModel as outlined in Listing 11. The data binding expression can be broken down. Readers should note that the expression beginning with employeediv is the name of the root component, which also contains the apply attribute. It is then followed by a dollar sign and composer. ZK evaluates this as look for the component with id employeediv and retrieve its composer. A . is then appended and followed by the function name that is to be accessed. This will assign the model to the result of the getEmployeeModel function in the controller. Secondly, the line shown in Listing 12 uses the same mechanism to retrieve the reference for employeedivs composer. It is

Listing 11: Binding for getEmployeeModel


model="@{employeediv$composer.getEmployeeModel

Listing 12: Databinding selected item


selectedItem="@{employeediv$composer.currentEmployee}"

www.JAXenter.com | October 2011

21

ZK

then followed by currentEmployee. Readers should also note that Listing 10 outlines a function and a bean named current Employee. This demonstrates that data binding the syntax to access beans and functions differ. This is outlined in Table 1. The attribute selectedItem is set to keep track of which bean is selected from the Listbox. When the selection is changed, ZK will automatically update the bean accordingly.

Displaying the data


To display the data within a listbox a template is needed. By creating a template, such as the one outlined in Listing 13, the listbox can effectively represent the data. The data is bounded to and rendered within the listbox. This is achieved by utilizing the self attribute of the listitem to assign variables which would each represent an Employee. The data binder will then loop through each employee and output the template code shown in Listing 13. Each listcell will therefore be bounded to the respective bean and its mutators. A similar methodology

Listing 13: Listbox display template


<listitem> <listhead> <listheader label="ID" hflex="2" /> <listheader label="First Name" hflex="3" /> <listheader label="Last Name" hflex="3" /> <listheader label="Age" hflex="1" /> </listhead> <listitem self="@{each='employee'}" value="@{employee}"> <listcell label="@{employee.id}" /> <listcell label="@{employee.firstName}" /> <listcell label="@{employee.lastName}" /> <listcell label="@{employee.age}" /> </listitem>

Listing 16: Controller click events


// click events public void onClick$btnAddEmployee(ForwardEvent fe) { String firstName = txtFirstName.getText(); String lastName = txtLastName.getText(); int iAge = Integer.parseInt(intAge.getText()); Employee employee = new Employee(firstName, lastName, iAge); if (!_model.add(employee)) { reportError(Messages.getString("EmployeeController.0"), employee); } } public void onClick$btnUpdateEmployee(ForwardEvent fe) { if (lstEmployee.getSelectedItem() != null) { Employee employee = (Employee) (lstEmployee.getSelectedItem() .getValue()); employee.setFirstName(txtFirstName.getText()); employee.setLastName(txtLastName.getText()); employee.setAge(Integer.parseInt(intAge.getText())); } else { UiUtils.showMessage(Messages.getString("EmployeeController.2")); } } public void onClick$btnDeleteEmployee(ForwardEvent fe) { if (lstEmployee.getSelectedItem() != null) { Employee employee = (Employee) (lstEmployee.getSelectedItem() .getValue()); if (!_model.remove(employee)) { reportError(Messages.getString("EmployeeController.3"), employee); } } else { UiUtils.showMessage(Messages.getString("EmployeeController.4")); } }

Listing 14: Extract showing currentEmployee information


First Name: <textbox id="txtFirstName" cols="25" value="@{employeediv$composer.currentEmployee.firstName}" /> Last Name: <textbox id="txtLastName" cols="25" value="@{employeediv$composer.currentEmployee.lastName}" /> Age: <intbox id="intAge" cols="1" value="@{employeediv$composer.currentEmployee.age}" />

Listing 15: CRUD buttons


<button id="btnAddEmployee" label="Add" width="36px" height="24px" /> <button id="btnUpdateEmployee" label="Update" width="46px" height="24px" /> <button id="btnDeleteEmployee" label="Delete" width="46px" height="24px" />

Access identifier
fullFunctionName

Description
To access a function in the controller through data binding, it is necessary to use the full function name When accessing a bean from the controller, it is only required to use the bean name, there is no need to include get or set. However, the bean in question must have both a getter and setter.

beanName

Table 1. databinder access to the controller

www.JAXenter.com | October 2011

22

ZK

lar methodology is applied to the components in the group box which represent the selected item. Each one of them is bounded to specific data of the currentEmployee bean using techniques discussed throughout this chapter. Therefore, as the currentEmployee changes when selecting on a different employee in the listbox, the relevant textboxes are also updated. These techniques apply throughout ZK. The relevant extract is shown in Listing 14. Having loaded and displayed the data, it is time to start manipulating it.

CRUD operations on the UI


So far the data has been loaded and displayed, but the whole point of web applications is to manipulate data. Hence add, create, update and delete methods need to be created. This is achieved via 3 buttons displayed in Listing 15. These buttons are tied to functions in the controller which capture the events. The functions are outlined in Listing 16. Listing 16 highlights the business logic behind the crud operations, most of these are self explanatory and are of basic Java calls. One

item readers may notice is that each component is referenced directly from the code. To enable this function, a developer only needs to specify the component type and its id in the controller and ZK will do the rest through automatic wiring. For example, Listing 17 shows that declarations are enough to make access to components possible in Listing 16. The last talking point is how ZK would know to update the listbox model after updating, adding or deleting an item. This is simply a matter of assigning load-after in the model attribute on the listbox to the relevant button events which update the model. When one of these events are fired the model will be reloaded. Listing 18 demonstrates the code necessary for this. Breaking it down, it is as simple as specifying the component id followed by a . and the event name.

Conclusion
As demonstrated, implementing a representation of Java data which is editable is very easy in ZK. Using 2 ZK specific files (index.zul and EmployeeController.java) it is possible to leverage the power of ZK to create a general CRUD application which can operate on a Java based datastore. ZKs advantage is due to its server-centric nature which provides easy access to all the servers resources, thus eliminating the need for any glue code.

Listing 17: Component declarations


//text boxes Textbox txtFirstName; Textbox txtLastName; //int boxes Intbox intAge;

Going further
The source code for this application is available on Github. If you would like to read more about ZK and other features, such as its transparent server push mechanism, then the documentation is a great place to start.
Timothy Clare is a Technology Evangelist for the Potix corporation which produces the ZK Framework. He has been working with various web and mobile technologies for over ten years.

Listing 18: Loadafter


model="@{employeediv$composer.getEmployeeModel, load-after='btnAddEmployee.onClick, btnDeleteEmployee.onClick'}"

Imprint
Publisher Software & Support Media GmbH Editorial Office Address Geleitsstrae 14 60599 Frankfurt am Main Germany www.jaxenter.com Editor in Chief: Editors: Authors: Copy Editor: Creative Director: Layout: Sebastian Meyen Jessica Thornsby, Claudia Frhling Timothy Clare, Fred Daoud, Ted Husted, Roger Kitain, Jeremy Thomerson Claudia Frhling, Katja Klassen Jens Mainz Dominique Kalbassi Sales Clerk: Mark Hazell +44 (0)20 7401 4845 markh@jaxlondon.com Entire contents copyright 2011 Software & Support Media GmbH. All rights reserved. No part of this publication may be reproduced, redistributed, posted online, or reused by any means in any form, including print, electronic, photocopy, internal network, Web or any other method, without prior written permission of Software & Support Media GmbH The views expressed are solely those of the authors and do not reflect the views or position of their firm, any of their clients, or Publisher. Regarding the information, Publisher disclaims all warranties as to the accuracy, completeness, or adequacy of any information, and is not responsible for any errors, omissions, inadequacies, misuse, or the consequences of using any information provided by Publisher. Rights of disposal of rewarded articles belong to Publisher. All mentioned trademarks and service marks are copyrighted by their respective owners.

www.JAXenter.com | October 2011

23

Stripes

The Hidden Gem of Web Frameworks

Stripes: a lean, mean Java web framework


Stripes [1] is a real hidden gem of a web framework. It is relatively low-key but those who use it, swear by it. And for good reasonit is simple, effective, and tightly focused on doing a few things and doing them really, really well. This gives you a framework that does a lot more for you than you have to do for it, while staying out of your way and letting you do things the way you want to do them. It also lets you pick your favorite tools for the other layers involved in developing a complete web application, such as persistence, security, and a jazzy user interface.
by Fred Daoud
If youve never heard of Stripes, you might wonder if its being used in real-world applications. It certainly is. One example is Modernizing Medicine (http://www.modernizingmedicine.com) where my colleagues and I use Stripes to develop a powerful Electronic Medical Assistant for Dermatologists. Daniel Cane, President and CEO of Modernizing Medicine, states: HOW I heard about Stripes, I have no idea. But, once I did, I was immediately hooked: the ease of binding and validation, and elegance of manipulation of forms, the power of localization, and a solid community of people willing to help. When looking at the Stripes book, the tag line ... and Java Web Development is Fun Again sold me on the platform. I have been so happy with this framework, and each week I learn something new. Stripes uses JSP for templating. It is easy to use, has great support in your IDE, has an enormous user base, copious amounts of third-party libraries and support, and is documented by a ton of reference pages, articles, books, and blog posts. Stripes does not reinvent anything that is already available in standard JSP, such as the forEach tag. Stripes tags are straightforward. The link clearly shows that it targets the com.jaxenter.stripes.action.ProductActionBean class and the showDetail event. You know exactly where to look next. Also, if you rename ProductActionBean or change its package, its a plain search to find where it is referenced in JSPs. Finally, adding a productId parameter to the link is easily (and cleanly) done as well. Lets take a peek at the Java side of things:
/* ProductActionBean.java */ package com.jaxenter.stripes.action; import net.sourceforge.stripes.action.ForwardResolution; import net.sourceforge.stripes.action.Resolution; import com.jaxenter.stripes.model.Product; public class ProductActionBean extends BaseActionBean { private Integer productId; private Product product; public Resolution showDetail() { product = loadProduct(productId); return new ForwardResolution("/WEB-INF/jsp/productDetails.jsp"); } public Product getProduct() { return product; }

Show me some code


Intrigued yet? Lets look at some code. Say you are showing a list of products from your inventory and you want to create a link that goes to the detail page for each product. The code in your page might look something like this:
<%-- sample01.jsp --%> <ul> <c:forEach var="${products}" item="product"> <li> <stripes:link beanclass="com.jaxenter.stripes.action.ProductActionBean" event="showDetail"> <stripes:param name="productId" value="${product.id}"/> ${product.name} </stripes:link> </li> </c:forEach> </ul>

Things to take away from this example:

www.JAXenter.com | October 2011

24

Stripes

public Integer getProductId() { return productId; } public void setProductId(Integer productId) { this.productId = productId; } }

One feature that makes things easy for you, the developer, is, that action beans are thread-safe. A fresh instance is created to handle each request, so you are free to use instance variables without worry. The next thing to know about action beans is that you handle events with methods of the following signature:
public Resolution eventName()

Now we have a few more takeaways: The class includes a method named showDetail, which matches the value of the event="showDetail" attribute in the JSP. This method will automatically be called when the user clicks on the link. The class also includes a productId property. Its value will be set to the product ID associated with the link, because we have <stripes:param name="productId"> tag in the body of the link. Although all parameter values arriving over HTTP are Strings, we can use Integer for our productId property. Stripes will automatically do the type conversion, and also supports Date, BigDecimal, BigInteger, and all primitive and wrapper types, out-of-the-box. Its easy to write type conversions for your own types, as well. The result returned by the showDetail method is a Resolution, which defines what happens next. Here, we are using ForwardResolution which clearly shows that we are forwarding to productDetail.jsp. The information is all there, no need to search in a separate file to figure out what the "success" string means! Stripes uses Action Beans, which are so named because they combine actions with JavaBean properties. Here, the action is showDetail, and the bean is the inclusion of the productId and product properties. In productDetail.jsp, we can easily show the details of the selected product by taking advantage of the automatic presence of the action bean within the JSP, under actionBean, courtesy of Stripes:
<%-- productDetails.jsp --%> <h1>Product details</h1> <ul> <li>Name: ${actionBean.product.name}</li> <li>Description: ${actionBean.product.description}</li> <li>Price: ${actionBean.product.price}</li> </ul>

The method name determines the name of the event that it handles. We already saw how to indicate the action bean class and event name in a link:
<stripes:link beanclass="..." event="...">

We can do the same for a form just as easily:


<stripes:form beanclass="..."> <stripes:submit name="save" value="Save Data"/> <stripes:submit name="cancel" value="Cancel everything"/> </stripes:form>

The name in each <stripes:submit> tag indicates which event handler method to call in the action bean (the value is the button label to show in the browser). This makes it really easy to handle multiple submit buttons in a form! Just write an event handler method for each button:
public Resolution save() { // ... } public Resolution cancel() { // ... }

You can have a default event handler in an action bean in two ways: first, if it is the only event handler method in the action bean, it is automatically the default. Second, you can designate an event handler method as the default by annotating it:
@DefaultHandler public Resolution view() { // ... } public Resolution cancel() { // ... }

Knowing that the current action bean is always available in the JSP under ${actionBean} makes it easy to transfer data to the view: just add a getter method in the action bean class for the information that you want to access.

After you have handled an event, you need to tell Stripes where to go next. You do this with a Resolution. Let's talk about those now.

Where to next? Resolutions


In Stripes, Resolution is a simple interface to tell Stripes how to respond to the browser after handling a request. The interface has just one method:
void execute(HttpServletRequest request, HttpServletResponse response);

More about action beans


Action beans are the workhorses of a Stripes application. These classes are where you receive input and handle events triggered by the user clicking on links or submitting forms.

www.JAXenter.com | October 2011

25

Stripes

As you can see, it is simple and lets you do just about anything in order to send a response to the browser. Of course, Stripes has some built-in implementations for common responses: ForwardResolution forwards to a template, typically a JSP RedirectResolution sends a redirect to the browser, typically to another action bean StreamingResolution makes it easy to send a binary file as a response, such as a PDF JavaScriptResolution sends a Java object in JavaScript, which is very useful when using Ajax ErrorResolution sends an HTTP error, with error code and descriptive message One of these will suit your needs most of the time, but you can extend them or write your own from scratch to get any customized behavior that you require. The two most commonly used resolutions are ForwardResolution and RedirectResolution:
// Forwards to a JSP return new ForwardResolution("/WEB-INF/jsp/productDetails.jsp"); // Redirects to another action bean and its default event handler return new RedirectResolution(AnotherActionBean.class); // Redirects to another action bean and a specific event handler return new RedirectResolution(AnotherActionBean.class, "showDetails"); // Redirects to another action bean and a specific event handler, // with request parameters return new RedirectResolution(AnotherActionBean.class, "showDetails") .addParameter("productId", 42).addParameter("showDescription", true); }

public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } /* Address.java */ package com.jaxenter.stripes.model; public class Address { private String streetName; public String getStreetName() { return streetName; } public void setStreetName(String streetName) { this.streetName = streetName; }

Youd like to enable the user to create a person with an address using an HTML form. With Stripes, it would look something like this first, youd have an action bean with a Person property:
/* PersonActionBean.java */ package com.jaxenter.stripes.action; import net.sourceforge.stripes.action.DefaultHandler; import net.sourceforge.stripes.action.ForwardResolution; import net.sourceforge.stripes.action.Resolution; import com.jaxenter.stripes.model.Person; public class PersonActionBean extends BaseActionBean { private Person person; @DefaultHandler public Resolution view() { return new ForwardResolution("/WEB-INF/jsp/personForm.jsp"); } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }

Resolutions are expressive and let you know right then and there, exactly what the next step is in responding to the browser.

Binding: the superfeature


Many a Stripes user, including myself, feel that the most powerful feature in Stripes is its binding of request parameters to action bean properties. Weve looked at that feature briefly; now lets dig deeper. Suppose you have a model object that has properties which are, in turn, other model objects, such as a Person with an Address:
/* Person.java */ package com.jaxenter.stripes.model; public class Person { private String firstName; private Address address; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; }

Notice that we also have a default event handler that forwards to personForm.jsp; this is where we create the HTML form:
<%-- personForm.jsp --%> <stripes:form beanclass="com.jaxenter.stripes.action.PersonActionBean"> <div> First name: <stripes:text name="person.firstName"/>

www.JAXenter.com | October 2011

26

Stripes

</div> <div> Street name: <stripes:text name="person.address.streetName"/> </div> <div> <stripes:submit name="save" value="Save"/> </div> </stripes:form>

public class PersonValidatedActionBean extends BaseActionBean { @ValidateNestedProperties({ @Validate(field="firstName", required=true), @Validate(field="address.streetName", required=true) }) private Person person; @DefaultHandler @DontValidate public Resolution view() { return new ForwardResolution("/WEB-INF/jsp/personValidatedForm.jsp"); } public Resolution save() { // save the person object... return new ForwardResolution("/WEB-INF/jsp/personSaved.jsp"); } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }

See how simple and straightforward that is? We use the <stripes:form> tag and indicate the target action bean class name. Then we create text inputs with the name attribute that corresponds to the target property: person. firstName and person.address.streetName. When the user submits the form, Stripes will automatically call getPerson().setFirstName(<value>) and getPerson().getAddress(). setStreetName(<value>) on the action bean to populate the person object and its nested properties. It gets better: you might think that youll get a NullPointerException because we never created a new Person() object. Never fear! Stripes does it for you, even on nested properties. When it gets null from a getter when binding request parameters to properties, Stripes creates a new object and sets it. So you can just add properties and let Stripes take care of the housekeeping. Finally, we just need an event handler for the submit button, which is named save:

public Resolution save() { // save the person object... }

By the time the save() method is called by Stripes, the parameters have been bound to the action bean properties, so we can count on the person object to be created, populated, and ready to be saved. Well, that is not entirely true: for that to work, the user has to fill in the form, rather than submit a blank form. We can easily address this with validation.

Validation: easy and awesome


Stripes offers a simple way to perform validation on user input: annotations on action bean properties, and custom validation methods. Continuing our Person form example; say we want to make sure that the user enters values in both the person.firstName and person.address.streetName fields. We use annotations on the person property in the action bean:
/* PersonValidatedActionBean.java */ package com.jaxenter.stripes.action; import net.sourceforge.stripes.action.DefaultHandler; import net.sourceforge.stripes.action.DontValidate; import net.sourceforge.stripes.action.ForwardResolution; import net.sourceforge.stripes.action.Resolution; import net.sourceforge.stripes.validation.Validate; import net.sourceforge.stripes.validation.ValidateNestedProperties; import com.jaxenter.stripes.model.Person;

The @Validate(required=true) annotation marks a property as a required field. We can place this annotation directly on an action bean property if we are submitting a value directly to that property. In our example, were not doing that; we're submitting values to nested properties of the person property. In that case, we need to place our @Validate annotations inside a @ValidateNestedProperties annotation, and use the field attribute to indicate which nested property we are validating. Notice that we also added @DontValidate to the view() method so that the validations are not enforced when the user first arrives to the action beanthey havent had a chance to fill in the form at that point. Now, with these validations, a blank form will not cause our save event handler to be called. Instead, Stripes will catch the validation errors and redisplay the form instead, with error messages at the location where we add the <stripes:errors/> tag:
<%-- personValidatedForm.jsp --%> <stripes:form beanclass="com.jaxenter.stripes.action.PersonValidatedActionBean"> <stripes:errors/> <div> First name: <stripes:text name="person.firstName"/> </div> <div> Street name: <stripes:text name="person.address.streetName"/> </div> <div> <stripes:submit name="save" value="Save"/> </div> </stripes:form>

www.JAXenter.com | October 2011

27

Stripes

Figure 1: Submitting a blank form

MALE("Male"); private String description; private Gender(String description) { this.description = description; } public String getDescription() { return description; } }

Submitting a blank form will result in a page as shown in figure 1. Whats really nice is that if the user fills in one of the fields, but not the other, the page will be redisplayed with the error message concerning the required field that was left blank, but the field that was filled in will automatically be repopulated. Notice that we dont have to do anything in the <stripes:text> tag for that to happen. This keeps your JSP code clean and tight. Stripes comes with the following built-in validations: required field minimum and maximum length minimum and maximum value, for numerical input matching a regular expression mask evaluation of a JSP expression Writing a custom validation method is a breeze, too. Just write a method annotated with @ValidationMethod. For example:
@ValidationMethod public void validateSomething(ValidationErrors errors) { if (!password.equals(confirmPassword)) { errors.add(new SimpleError("The passwords do not match.")); } }

Here is how you could create a form to select one gender with radio buttons, any number of genders with checkboxes, and one gender with a select box:
<%-- formControls.jsp --%> <stripes:form beanclass="com.jaxenter.stripes.action.FormControlsActionBean"> <div> Radio buttons: <c:forEach var="gender" items="<%= com.jaxenter.stripes.model.Gender.values() %>"> <stripes:radio name="radioChoice" value="${gender}"/>${gender.description} </c:forEach> </div> <div> Checkboxes: <c:forEach var="gender" items="<%= com.jaxenter.stripes.model.Gender.values() %>"> <stripes:checkbox name="checkboxChoices" value="${gender}"/> ${gender.description} </c:forEach> </div> <div> Select box: <stripes:select name="selectChoice"> <stripes:option value="">Select...</stripes:option> <stripes:options-enumeration enum="com.jaxenter.stripes.model.Gender" label="description"/> </stripes:select> </div> <div><stripes:submit name="view" value="Send"/></div> </stripes:form>

By adding an error to the errors list, we cause Stripes to return to the form instead of calling the event handler, just like when a built-in validation fails. Finally, note that Stripes only calls the validation method if the built-in validations have passed. Again, this keeps your code clean and tight, because for example you dont have to do null checks on the password and confirmPassword if you made them required fields. If the required validation fails, the custom validation method will not be called. The error messages concerning the fields being required will be shown instead.

More about forms and binding


I said that parameter binding was one of Stripes strongest features. Combined with Stripes form tags, its a powerful one-two punch. So lets explore that further. Suppose you have an enum, Gender, as follows:
package com.jaxenter.stripes.model; public enum Gender { FEMALE("Female"),

As you can see, the Stripes tag library makes it easy to create forms and use form controls. Remember that the form controls automatically repopulate from previous values. Also, Stripes will automatically handle the conversion between String and our Gender enum type. Finally, notice the <stripes:options-enumeration> tag that takes the class name of an enum and automatically creates a list of options from its values. It renders the enumerations constant by default, but we can also use another property as we have done here by specifying the label attribute. Stripes also has a <stripes:options-collection> and a <stripes:options-map> tag to render a list of options from any Collection or Map, respectively.

www.JAXenter.com | October 2011

28

Stripes

One more very nice feature is that we can include a Select... option as the first in the list to prompt the user to select an option, instead of selecting one by default. By doing this, we can make sure that the user makes a selection. Indeed, because the value of the Select... option is a blank string, the corresponding property on the action bean will be null if the user does not make a selection. Using @Validate(required=true), we can enforce the requirement of selecting an option. This is much cleaner than using -1 or some other magic value and then manually checking for that value as meaning no selection was made! We are ready to look at the action bean:
package com.jaxenter.stripes.action; import java.util.List; import net.sourceforge.stripes.action.ForwardResolution; import net.sourceforge.stripes.action.Resolution; import com.jaxenter.stripes.model.Gender; public class FormControlsActionBean extends BaseActionBean { private Gender radioChoice; private List<Gender> checkboxChoices; private Gender selectChoice; public Resolution view() { return new ForwardResolution("/WEB-INF/jsp/formControls.jsp"); } public Gender getRadioChoice() { return radioChoice; } public void setRadioChoice(Gender radioChoice) { this.radioChoice = radioChoice; } public List<Gender> getCheckboxChoices() { return checkboxChoices; } public void setCheckboxChoices(List<Gender> checkboxChoices) { this.checkboxChoices = checkboxChoices; } public Gender getSelectChoice() { return selectChoice; } public void setSelectChoice(Gender selectChoice) { this.selectChoice = selectChoice; } }

stack framework nor a client-side graphical user interface. Its philosophy is that there are many excellent solutions for those tiers of an application, so it does not reinvent the wheel and does not prevent you from choosing your favorite solution for things like persistence, JavaScript widgets, and so on. Here is a summary of more features offered by Stripes: Automatic discovery of your action beans simply by mentioning, once and for all, the root package of your action beans. No need to adjust configuration every time you add, modify, or remove an action bean. Similarly, automatic discovery of your extensions: these are custom type converters, formatters, and other Stripes artifacts that you extend or implement to suit your needs. A layout system that is both simple and powerful. The recurring theme of not requiring configuration holds here as well. Annotations to easily create wizards, forms that span multiple pages. Interceptors, which allow you to tap into the Stripes lifecycle and do virtually anything to customize the framework to meet your requirements. Exception handling to define, in one place, how to handle exceptions, from specific to general. Testing facilities so that you can write automated tests for your Stripes web application. Localization to easily make your application available in multiple languages.

Conclusion
Stripes strikes a perfect balance of powerful features, simplicity, and tight focus to give you a framework that does a lot for you without getting in your way nor suffering from feature bloat. It is easy to learn and intuitive, so you quickly become productive. It is customizable and extendable, so you can tweak it to suit your more advanced or particular requirements. Last but not least, it has one of the friendliest communities in the open source framework space, so if you need help, write a message to the mailing list [2] or drop by the IRC channel [3].

Acknowledgements
Thanks to Jessica Thornsby for contacting me with the idea of writing an article on Stripes for the framework issue of Java Tech Magazine, and to Will Hartung for his review of the article and useful feedback.
Fred Daoud is the author of Stripes ...and Java Web Development is Fun Again [4] and currently uses Stripes at Modernizing Medicine, Inc.[5]. He has been using Java since 1997 and loves web frameworks. He also likes using other JVM-based languages such as Clojure, JRuby, and Groovy. His home page lives at http://www.fdaoud.com.

The properties correspond to the name attributes that we have in the JSP. As I mentioned, Stripes converts from the incoming String to the corresponding Gender. Whats more, for the checkboxes, we have a List<Gender> property. This list will automatically contain the genders that the user has selected. We dont even have to create a new ArrayList; Stripes will do that for us, too!

References
[1] The Stripes main web site: http://www.stripesframework.org [2] Mailing list: http://news.gmane.org/gmane.comp.java.stripes.user [3] The IRC channel: #stripes on FreeNode [4] The Stripes book: http://www.pragprog.com/titles/fdstr [5] Modernizing Medicine: http://www.modernizingmedicine.com

Feature-packed, but without excess


Stripes offers many useful features while staying focused on its raison d'tre: it is a server-side web framework, not a full-

www.JAXenter.com | October 2011

29

Getting Started with Apache Struts 2

An Intro to Apache Struts

Apache Struts 2 Soup to Nuts


Apache Struts 2 [1] simplifies enterprise-ready web development by providing a flexible set of custom tags and an extensible application architecture. The framework is designed for professional developers creating sophisticated web applications that integrate with databases and other enterprise services. Originally known as WebWork, Struts 2 has been continuously maintained since March 2002 [2], and most recently updated with the May 2011 release (2.2.3) [3]. Struts 2 is product of the Apache Software Foundation and distributed to the general public at no charge under the business-friendly Apache Software License 2.0. The ASF provides product support only through a public mailing list [4] frequented by volunteer developers and users.

by Ted Husted
Struts 2 is directly supported by the three most popular integrated development environments (IDEs) for Java: IntelliJ IDEA by JetBrains [5], MyEclipse by Genutec [6], and NetBeans [7]. For example, to create a Struts 2 application in IntelliJ IDEA, you can select the Struts 2 facet, and the IDE will download the JARs and setup a Java web application structure, ready for you to add your own pages and other Struts 2 elements (figure 1). IntelliJ IDEAs support for Struts 2 includes configuration via dedicated Struts 2 facet with fileset manager, library validator, and configuration detector, dedicated Struts 2 structure tool windows, code inspectors that spot Struts 2-specific code issues, support for inplace Javascript and CSS code, smart coding completion within Struts elements, Struts 2-ready refactorings, and Struts 2-aware project navigation across Java, JSP and XML files. Likewise, with MyEclipse you can add Struts 2 capabilities to a web project, including wizards to create new Struts 2 elements or edit existing elements. The wizards are context-sensitive and provide input assistance and validation as you edit Struts 2 elements. Not to be left behind, NetBeans offers its own set of wizards to create an example Struts 2 application, register the necessary library files, and then edit the various Struts 2 elements. In addition, NetBeans supports hyperlinking and code completion in Struts 2 configuration files. Struts 2 also provides a Maven prototype you can use to bootstrap a project, if you are so inclined, and, of course, the distribution has all the usual assets for hardcore hand-coders.

1. 2. 3. 4. 5. 6. 7.

Pages with Struts Tags Message Properties Actions Interceptors Validators Results Annotations and Deployment Descriptors

The elements can be organized into three groups: Pages and Message Properties are used to create the application user interface. Actions, Interceptors, and Validators process an incoming request, in order to render a page, or some other Result.

In brief the elements of struts design


A dynamic Struts 2 application has seven building blocks:
Figure 1: IntelliJ IDEA ready for your Struts 2 elements

www.JAXenter.com | October 2011

30

Getting Started with Apache Struts 2

Figure 2 shows the page rendered in a web browser. The two use cases for Message properties are normalization and localization. Many terms are used more than once, and so should be defined only once. Also, many enterprise applications are presented in multiple languages, and Struts 2 supports adding Message Property files for different locales. The key attribute can also be used as the name of the property used to populate the field from a dynamic value passed to the page.
Figure 2: Struts 2 Data Entry Form Figure 3: Struts 2 Value Stack

Telling it Like it is Value Stack


To manage values being passed to a page, Struts 2 uses a Value Stack. When a Struts tag needs a value, the framework searches the Value Stack in Last In First Out order (LIFO). If you push a JavaBean with a Username property onto the stack last, then the tag will find that value first. The Value Stack encapsulates the standard Java scopes, along with framework elements, and any custom objects you would like to push onto the stack. The Struts 2 Validators use the Value Stack to redisplay incorrect form input. A default value might have been set by a database call, and another value entered by the user into a form. The users value is last on stack, and so its found first if the page is redisplayed. Figure 3 illustrates how the system searches for property values. The Value Stack solves a thorny problem in validating input. You might have an Integer field on a JavaBean, but on the input form, the user enters Blue instead of a number. The framework cant store Blue in an Integer field. So, we either have to throw-away the incorrect value, or complicate how we store a value destined for an Integer property. In Struts 1, for example, we use ActionForms to capture and validate input as Strings. Many developers would then code a similar but different set of JavaBeans to capture the value in its native type, for transfer to a database system. In Struts 2, the framework can validate input and transfer it to a POJO JavaBean with typed properties, without creating and maintaining a special ActionForm. The Struts 2 Validators push the offending input onto the Value Stack, so it can be validated and corrected before populating a value object.

Annotations and Deployment Descriptors are used to define the initial state for the other elements of a Struts 2 application. Lets take a look at each element in turn.

Terminally Pretty Struts Tags


Often, much of the coding effort in a web application goes into the pages. The Struts 2 Tags help us create localized, dynamic web applications with a minimum of coding, reducing effort by reducing code. Listing 1 shows the source code for a simple input form. The key attribute refers to a Message Properties file, in the standard Java format, that contains the text to use as the label, along with other terms, such as error messages. Listing 2 shows a simple properties file for our form.

Listing 1: A localizationready form using Struts tags


<s:actionerror/> <s:form action="RegisterSave" validate="true"> <s:textfield key"username"/> <s:password key="password"/> <s:password key=password2.label" name="Password2"/>e <s:submit key="save"/> <s:submit key="cancel" action="MainMenu" onclick="form.onsubmit=null"/> </s:form>

Hard name, easy code OGNL


Underlying the tags is a powerful expression and binding language called OGNL, or Object Graph Notation Language. Most Java web developers will find the feature set similar to the JST Expression Language, but much more capable. OGNL works hand-in-glove with the Value Stack, making it easy to retrieve a value from a certain scope, or just the last value pushed. Get the username from the User object in Session scope only: <p>Username: <s:property name="#session.user. username" /> </p> Get the username propery last pushed onto the stack: <p>Username: <s:propertyname="username" /> </p>

Listing 2: A message properties file


username = Username password = Password password2.label = Repeat password save = Save cancel = Cancel

New tags for old control, data, and UI


A variety of custom tags are available in Struts 2 [8], which can be grouped into three flavors: Control, Data, and UI. The Control tags allow a page to

www.JAXenter.com | October 2011

31

Getting Started with Apache Struts 2

change its presentation on the fly, by using operations like if, elseif, and else; or generate markup with operations like append, iterator, merge, sort, and subset. The Data tags mange dynamic values and behaviors, with operations like a, action, bean, date, debug, i18n, include, param, property, push, set, text, and url. The Form UI Tags replicate and extend the standard HTML tags, with operations like form, label checkbox, radio, optgroup, textfield, textarea, and password along with enhanced controls like checkboxlist, combobox, doubleselect, among several others. Finally, Non-Form UI Tags, provide error handling with operations like fielderror, actionerror, and actionmessage.

Less is more themes


Most often, the dynamic data emitted by many of the tags is wrapped in a predictable envelope of basic HTML. To make pages easier to build, the UI Tags can include routine markup, so you dont have to. The framework ships with standard themes that include different sets of standard markup. The Simple Theme does not output markup. You can add your own pretty much like a standard HTML tag. The XHMTL Theme is the default theme, and does things like put forms into a two-column table layout, with labels, client and serverside validation, and error handling (just by specifying the field). The CCS XHTML Theme is designed to replicate the XHTML theme, but entirely in CSS.

Figure 4: Struts Request/Response. (Image provided under the Apache Software License 2007 Apache Software Foundation http://struts.apache.org/2.0.6/docs/architecture.html)

Listing 3: HTML source generated by Struts tags


<form id="RegistrationSave" name="RegistrationSave" action= "/struts2-mailreader/RegistrationSave.do" method="post"> <table class="wwFormTable"> <tr> <td class="tdLabel"><label for="Registration_save_username" class="label"> Username:</label></td> <td><input type="text" name="username" value="" id="Registration_save_ username"/></td> </tr> <tr>

<td class="tdLabel"><label for="RegistrationSavePassword" class="label"> Password:</label></td> <td><input type="password" name="password" value="" id= "RegistrationSavePassword"/></td> </tr> <tr> <td class="tdLabel"><label for="RegistrationSavePassword2" class="label"> (Repeat) Password:</label></td> <td><input type="password" name="password2" id= "RegistrationSavePassword2"/></td> </tr> </table></form>

www.JAXenter.com | October 2011

32

Getting Started with Apache Struts 2

Listing 3 shows the code the XHTML template generated for our data entry form. The templating system is designed so that you override the markup for a single control, or replace all the standard markup with your own custom theme.

ror", or "cancel". The framework passes the token returned by an Action to a Result handler for further processing.

Getting there from here results


The result handler either creates output or dispatches to another resource, like a server page, to create the output. There are several result handlers bundled with the framework and several more are available as plugins. For example, there are plugins for rendering reports with JFreeChart or JasperReports. Another plugin converts output to JSON for AJAX applications. Yet another lets Struts 2 applications utilize JavaServer Faces components as a result. Other custom results can be created and plugged into the framework as needed. Each action handler can have one or more result handlers, mapped to whatever result types are needed. Regardless of what type of result is being generated, the action handler only needs to return a logical name. The action does not need to know how the response is being handled.

It takes a village actions, interceptors, validators, results


Web pages are only the last mile between the user and the backend business logic. In order to acquire the data that a dynamic page needs, a request passes through a set of handlers. Figure 4 shows the players in context.

Lights, cameras actions


Actions are the frameworks basic unit of work. Most framework requests are handled by an Action, with help from Interceptors, Results, and the Struts Tags. An application can map an action handler to logical resource names, like Welcome. action or AccountInsert.action. When a browser submits a request for one of these resources, the framework selects an Action class to handle the exchange. The input values from the request (if any) are transferred to properties on an Action class (or some other class of your choosing). The framework then calls a method on the Action to invoke the business logic associated with the request. The class can return a string token to indicate the outcome of the transaction. Usually, these tokens are generic terms like "success", "failure", "input", "er-

Thank you Sir, may I have another interceptors


Most of the frameworks business-logic utility is provided by Interceptors. All requests can be handled by a single set of Interceptors, or different sets of Interceptors can handle different requests. Interceptors can invoke code both before and after the Action executes, encapsulating standard utility that can be shared between Actions into a reusuable object. Services like property population, validation, and authorization are provided by standard Interceptors. The set of Interceptors acts as a gauntlet for the request. The request object passes through each Interceptor in turn. The Interceptor can ignore the request, or act on the request, as appropriate.

Listing 4: Example Logon XML document


<struts> <package name="default" extends="struts-default"> <action name="Logon" class="mailreader2.Logon"> <result type="redirect-action">MainMenu</result> <result name="input">/pages/Logon.jsp</result> <result name="cancel" type="redirect-action">Welcome</result> <result name="expired" type="chain">ChangePassword</result> </action> </package> </struts>

Trust but verify validators


Validators vet incoming data and generate an error message when input is invalid. The framework provides all the validators that most applications will need, though custom Validators are easy to implement for special situations.

Ready, set, go annotations and deployment descriptors


A web application uses a deployment descriptor to initialize resources like filters and listeners. The web deployment descriptor is formatted as a XML document. The web container reads the XML document and creates an internal configuration object. When the container starts up, it loads and configures the components specified by the deployment descriptor. Likewise, Struts uses an internal configuration object to tie together various parts of the application, like the Action and the Result. An application can specify the Struts configuration by using Java annotations or by providing one or more XML documents. web.xml Standard web deployment descriptor with the frameworks bootstrap components, including the FilterDispacther that detects Action URLs. struts.xml Main configuration, contains result/view types, action mappings, interceptors, and so forth.

Listing 5: Example Logon Java annotation


@Results({ @Result(name="success", value="MainMenu"), @Result(name="input", value="pages/Logon.jsp"), @Result(name="cancel", value="Welcome", type="redirect-action"), @Result(name="expired", value="ChangePassword", type="chain")}) public class Logon extends ActionSupport { // .... }

www.JAXenter.com | October 2011

33

Getting Started with Apache Struts 2

struts-plugin.xml Optional configuration file for plugins. Each plugin JAR may have its own descriptor. Listing 4 shows a typical XML-stylenconfiguration for a logon action. Listing 5 shows the corresponding annotations for the same logon action. Tip Configuration by Java annotation or by XML document are not mutually exclusive. We can use either or both in the same application.

At each step in the cycle, developers can provide their own code to define how their application reacts to a particular request. 1. Accept Request: First, a web browser makes a request. The request might be for a resource like a HTML page, a PDF, or (among other things) the special Action resource that can create a dynamic response. 2. Select Action: The incoming request is transferred to a Struts 2 component called a Filter Dispatcher. Whenever this request is for a Struts Action, our dispatcher passes the request through to the rest of the framework. (Otherwise, the request just passes through our dispatcher, untouched.) 3. Push Interceptors: Whenever a request enters the framework, we might want to validate input, or transfer values to an internal object, or upload a file, or any combination of similar operations. (In other words, we want to intercept the request to do some housekeeping before going on to the main event.) The framework Interceptor components handle operations that need to be applied to more than one request. 4. Invoke Action: Aside from the Interceptor operations, we will also want to invoke an operation unique to the request (the main event). For example, we might want to work with a database to store or retrieve information. After a request passes through the outer layer of Interceptors, a method on an Action class can be called to handle any special processing for the request. 5. Select Result: After the Action method fires, we need to tell the rest of the framework what to do next. We've handled the request, and now we need to create the response (or result). As aforementioned, to bootstrap the response process, the Action method returns a string token representing the outcome of the request, such as success, failure, cancel, or something more specific, like logon. The framework matches that token with the name of a Result component. The Result is responsible for handling the response, either by rendering output for the browser, or by transferring control to another resource that will render the response. Most often, another resource will be a JavaServer Page formatted with Struts Tags. 6. Pop Interceptors: After the Result handler fires, the request passes back through the set of Interceptors. Some Interceptors work with incoming requests, some work with outgoing requests, and some work with both. 7. Return Response: The request exits the framework, and the web server sends our response back to the web browser. Architecturally, Struts 2 is an Enterprise Model View Controller [9] framework (see sidebar: MVC divide and conquer), where the Action provides the Model, the Result represents the Controller, and Tags render the View.

Same Stuff, Different Day Struts 2 Life Cycle


A framework is a semi-complete application. By providing a backbone structure, the framework lets developers add the code that makes this application unique, and reuse the underlying architecture again and again. The Struts 2 architecture strives for simple elegance. When a web client sends a request to a Struts 2 application, the framework provides a seven step processing cycle 1. 2. 3. 4. 5. 6. 7. Accept Request Select Action Push Interceptors Invoke Action Select Result Pop Interceptors Return Response

MVC divide and conquer


Once upon a time, in 1978, Trygve Reenskaug, a visiting scientist to Xerox PARC, was working on a SmallTalk application that helped people design and build ships. The users of the application needed to inspect and manipulate a large and complex data set. Reenskaug struck upon the idea of separating the application into three areas of concern: the Model, View, and Controller (MVC). The essential purpose of MVC, says Reenskaug, "is to bridge the gap between the human users mental model and the digital model that exists in the computer. The ideal MVC solution supports the user illusion of seeing and manipulating the domain information directly." (http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html) Behind MVC is the key notion that there might be multiple views, or representations, of the same data. Consequently, a MVC application separates the concerns of presentation, navigation, and business logic, allowing us to change one concern at a time. In the original desktop application implementation, Views are expected to observe the Model. When the Model changes, it alerts the Views, and the Views refresh themselves. The Controller responds to user input by updating the Model or selecting a View. In an enterprise MVC application, the Controller pushes state changes to the View so that the View does not need a direct connection to the Model. The Controller becomes a gobetween for the View and Model. The presentation layer exchanges input with the control layer, the control layer exchanges input with the application logic, the application logic queries or updates the database. For the web, when we modify the classic pattern, Enterprise MVC looks less like a loop and more like a horseshoe or bridge, as shown in the figure Evolution of MVC.

But wait, theres more plugins


Struts 2 provides a simple plugin architecture so that developers can extend the framework just by adding a JAR to the

www.JAXenter.com | October 2011

34

Getting Started with Apache Struts 2

Figure 5: Struts-Blank deployed Figure 6: Struts Blank welcome page

To give you a starting place, the Struts 2 distribution bundles a Struts Blank application. Its a ready-to-deploy WAR, designed to serve as a starting place for your applications (figure 5). The Blank application is internationalized and includes a number of example pages, to help you get started (figure 6). Of course, there are a number of online resources for learning more about Struts 2, most of which are documented on the official website at struts.apache.org. Another great resource is Struts 2 in Action [16] by Don Brown, et al. Highly recommended!

applications classpath. Since plugins are contained in a JAR, they are easy to share with others. Heres a sampling of the many plugins available for Struts 2: JQuery [10]: Ajax functionality and UI Widgets based on the jQuery javascript framework. Hibernate [11]: Hibernate Validator integration, Hibernate Core Sessions and Transactions injection capabilities and a Configuration Management Web Tool. Guice [12]: Actions, Interceptors, and Results to be injected by Guice. OSGI [13]: starting an instance of Apache Felix inside a web application, and scanning installed bundles for Struts configuration REST [14]: provides tools to build RESTful applications Sitemesh [15]: Sitemesh templates functionality access Struts information.

Ted Husted is the co-author of Struts in Action (first edition), a former Struts committer, and served as Release Manager for the initial Stuts 2 distribution. When he can, Ted now helps out with the Vosao CMS project (http://www.vosao.org), an open source web content management system for the Google Apps Engine. Ted will be speaking at ApacheCon NA in November 2010 on the Secret Life of Open Source and .NET @ Apache.org. He works as a Business Analyst with NimbleUser, a technology company helping professional and trade associations do more with web-based applications.

References
[1] Apache Struts 2: http://struts.apache.org/ [2] Web Work Released: http://www.mail-archive.com/jsp-interest@java.sun.com/ msg38573.html [3] Struts Release 2.2.3 Release: http://struts.apache.org/download. cgi#struts223 [4] Public Mailing List: http://struts.apache.org/mail.html [5] IntelliJ IDEA: http://www.jetbrains.com/idea/features/struts2.html [6] My Eclipse: http://www.myeclipseide.com/htmlpages-func-display-pid-444. html [7] NetBeans: http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage. jsp?pluginid=23467 [8] Tag Reference: http://struts.apache.org/2.2.3/docs/tag-reference.html [9] Model View Controller: http://en.wikipedia.org/wiki/Model%E2%80%93view% E2%80%93controller [10] JQuery Plugin: https://cwiki.apache.org/S2PLUGINS/2011/05/09/struts2jquery-plugin-version-300.html [11] Hibernate Plugin: https://cwiki.apache.org/S2PLUGINS/full-hibernate-plugin. html [12] Guice Plugin: https://cwiki.apache.org/S2PLUGINS/guice-plugin.html [13] OSGI Plugin: https://cwiki.apache.org/S2PLUGINS/osgi-plugin.html [14] REST Plugin: https://cwiki.apache.org/S2PLUGINS/rest-plugin.html [15] SiteMesh Plugin: https://cwiki.apache.org/S2PLUGINS/sitemesh-plugin.html [16] Struts 2 in Actio: http://amzn.to/rtnT8Q

Next steps
If youre ready to take Struts 2 for a spin, the simplest thing is to fire up your favorite editor or IDE, and start coding.

Vosao CMS
Extensible
The Vosao Content Management System (CMS) is a pure Java software product. And whats more its free, open source software. You can enhance the CMS with your own features and plugins.

Native
Scalability? Hosting? No worries! Vosao CMS was written from the ground up for the GAE platform, the world leader in remote hosting.

Complete
Create striking, interactive sites with standards based templates. Easily find and update pages with a content tree and visual editor. Instantly integrate with other sites, like Recaptcha and Disqus, with plugins from our growing library. http://www.vosao.org

www.JAXenter.com | October 2011

35

ER

S RE COU CLOUD STO PON AU APP ICS T DIGITA GM LYT L PUBLISHING CONTEN ENT ANA ED R WI S EALITY DG L2 RVICE ETS LOCATION BASED SE HTM MOBI NCE HTM ING RIE LE WEB USER EXPE L5 ORK W PLAT NET FORM S VOIP BLUETOOTH

KIN DL E IOS

4G

AD NET WORK

N ET W

WI N D O W S P H

OR KS M

PAYM O B ILE

TS EN

ONE IPH

comment | analysis | opinion | news | reviews


visit us at

www.mobile360.com

Brought to you by

TIS

IN G

GO

OGL

ONE 7

AC F

PE LO E EV QR D

ID

NT E

TY

ETI

NG

S TABLETS APP

TI E

E M

NF

MA

RK

SM

A RT P H O N E

MO

NT O

EN

VID

NG

AT

E DI SOCIAL M

IPA
IL E B

EO

CH

AND

R OID

OS | Business | Apps Mobile Web & Technology

M ES
SA

S OL

UT

GI

ION
S

SO
AD
V

CI A

Вам также может понравиться