<?xml version="1.0" encoding="UTF-8"?> <rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
> <channel><title>SitePoint » Learn CSS &#124; HTML5 &#124; JavaScript &#124; Wordpress &#124; Tutorials-Web Development &#124; Reference &#124; Books and More &#187; Java EE</title> <atom:link href="http://www.sitepoint.com/category/tech/javaj2ee/feed/" rel="self" type="application/rss+xml" /><link>http://www.sitepoint.com</link> <description></description> <lastBuildDate>Sun, 27 May 2012 15:59:16 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.1</generator> <xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" /> <item><title>Java 6 for Mac OS X Back on the Radar</title><link>http://www.sitepoint.com/java-6-for-mac-os-x-back-on-the-radar/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=java-6-for-mac-os-x-back-on-the-radar</link> <comments>http://www.sitepoint.com/java-6-for-mac-os-x-back-on-the-radar/#comments</comments> <pubDate>Thu, 20 Dec 2007 00:43:18 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2007/12/20/java-6-for-mac-os-x-back-on-the-radar/</guid> <description><![CDATA[Nearly two months on from the release of Mac OS X 10.5 (Leopard) and the resulting uproar from Java developers over Apple’s silent removal of preview builds of Java 6 for Mac, Apple has just as quietly released Java SE 6 Developer Preview 8, the first developer preview of Java 6 that runs on Leopard. [...]]]></description> <content:encoded><![CDATA[<p></p><p>Nearly two months on from the release of Mac OS X 10.5 (Leopard) and the resulting <a
href="http://www.sitepoint.com/missing-in-action-java-6-for-mac/">uproar from Java developers</a> over Apple’s silent removal of preview builds of Java 6 for Mac, Apple has just as quietly <a
href="http://arstechnica.com/journals/apple.ars/2007/12/19/apple-finally-releases-java-6-developer-preview-for-leopard">released Java SE 6 Developer Preview 8</a>, the first developer preview of Java 6 that runs on Leopard.</p><p>Many developers had feared that the removal of the previous preview signalled an intent from Apple to ignore Java 6 in favour of continued minor tweaks to Java 5. It seems now that the optimists were right: Apple just needed more time to get Java 6 right, so it took a step back and made some improvements to Java 5 for the Leopard release before pressing on with its work on Java 6.</p><p>The fact remains that if Apple were only to communicate with its closest allies—software developers—in a meaningful way, we wouldn’t be left playing these guessing games over the company’s intentions.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/java-6-for-mac-os-x-back-on-the-radar/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Missing in Action: Java 6 for Mac</title><link>http://www.sitepoint.com/missing-in-action-java-6-for-mac/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=missing-in-action-java-6-for-mac</link> <comments>http://www.sitepoint.com/missing-in-action-java-6-for-mac/#comments</comments> <pubDate>Fri, 09 Nov 2007 00:47:44 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2007/11/09/missing-in-action-java-6-for-mac/</guid> <description><![CDATA[Java developers are up in arms over the recent release of Mac OS X Leopard, and the sudden silence from Apple regarding the future of Java 6 on the Mac. Not only did Leopard not ship with Java 6, but Apple has quietly taken down the developer preview of Java 6, and is reportedly deleting [...]]]></description> <content:encoded><![CDATA[<p></p><p>Java developers are up in arms over the recent release of <a
href="http://www.apple.com/macosx/">Mac OS X Leopard</a>, and the sudden silence from Apple regarding the future of Java 6 on the Mac. Not only did Leopard not ship with Java 6, but Apple has quietly taken down the developer preview of Java 6, and is reportedly deleting threads in the Apple developer forums asking why.</p><p>As anyone who has attended a developer conference in the past few years can attest, developers as a group are some of Apple&#8217;s best customers. If only Apple treated its developers with as much reverence.</p><p>In a post on <a
href="http://www.javalobby.org/">The Java Lobby</a> entitled <a
href="http://www.javalobby.org/java/forums/t102936.html">So Long Apple. The Party&#8217;s Over</a>, Michael Urban summed up the situation nicely:</p><blockquote><p>Not only did Leopard not ship with Java 6, but Apple, in typical fashion, apparently thinks it has no obligation to its customers to inform them about why the plans changed, and when (or even if at this point?) Apple will ever have a working copy of Java 6.</p></blockquote><p>Now, it&#8217;s obvious that Apple hasn&#8217;t dropped Java completely. As many developers have pointed out, Apple did do plenty of work on its version of Java 5 for the Leopard release. Ben Galbraith recently gave a run-down of <a
href="http://weblogs.java.net/blog/javaben/archive/2007/10/more_on_leopard.html">his favourite Java improvements in Leopard</a>, based on <a
href="http://developer.apple.com/releasenotes/Java/JavaLeopardRN/">Apple&#8217;s Release Notes for Java 5 on Leopard</a>, for example.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>But still, despite what is now going on two weeks of furor in the Java community, there is no word from Apple about the state of Java 6 on Mac OS X.</p><p>On the one hand, there is <a
href="http://stuffthathappens.com/blog/2007/10/28/os-x-java-definitive-timeline/">speculation that its release is imminent</a>, based on Apple&#8217;s history of releasing Java 5 within weeks of Mac OS X Tiger. On the other hand, the significant improvements Apple made to Java 5 for the release of Leopard cast doubt in my mind over whether Apple has done <em>any</em> work on Java 6 lately.</p><p>None of this would be anywhere near as frustrating if Apple would simply break its stony silence. It&#8217;s one thing to hold back announcements of new products to maximize their marketing impact, but keeping your most important allies—developers—in the dark about the future of major technologies like Java is no way to do business.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/missing-in-action-java-6-for-mac/feed/</wfw:commentRss> <slash:comments>16</slash:comments> </item> <item><title>First Look: Google Web Toolkit</title><link>http://www.sitepoint.com/first-look-google-web-toolkit/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=first-look-google-web-toolkit</link> <comments>http://www.sitepoint.com/first-look-google-web-toolkit/#comments</comments> <pubDate>Thu, 25 May 2006 01:29:42 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/?p=1553</guid> <description><![CDATA[Portions of this entry were first published in the SitePoint Tech Times #139. Have you written your own AJAX framework yet? It seems all the big boys are doing it. Microsoft is bringing us Atlas for ASP.NET, Yahoo!&#8217;s User Interface Library is open source, server agnostic and beautifully documented and Adobe is working on Spry, [...]]]></description> <content:encoded><![CDATA[<p></p><p><em>Portions of this entry were first published in the <a
href="http://www.sitepoint.com/newsletter/viewissue.php?id=3&#038;issue=139">SitePoint Tech Times #139</a>.</em></p><p>Have <em>you</em> written your own AJAX framework yet? It seems all the big boys are doing it. <a
href="http://www.sitepoint.com/atlas-disappoints-in-cross-browser-support/">Microsoft is bringing us Atlas</a> for ASP.NET, <a
href="http://www.sitepoint.com/javascript-libraries-and-patterns-yahoo-does-ajax/">Yahoo!&#8217;s User Interface Library</a> is open source, server agnostic and beautifully documented and <a
href="http://labs.adobe.com/technologies/spry/">Adobe is working on Spry</a>, which is off to a shaky start in the web standards department. Do we really need another?</p><p>Google&#8217;s late-but-inevitable entry into this arena is certainly no copycat. The <a
href="http://code.google.com/webtoolkit/">Google Web Toolkit</a> (GWT) is nothing less than a completely original approach to web development that allows server-side Java developers to take their skills to the JavaScript domain&#8230; without having to write any JavaScript.</p><p>In short, you write, test and debug your client-side code in Java and then use a specialized compiler to convert it all into cross-browser JavaScript for use on your site.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><h2>How&#8217;s it work?</h2><p>You can write you client-side code using the usual core Java classes in the <code>java.lang</code> and <code>java.util</code> packages, as well as <a
href="http://code.google.com/webtoolkit/documentation/gwt.html">a nice library of classes</a> that come with GWT that let you access the same browser features that are available in JavaScript (the Docment Object Model, <code>alert</code> boxes, <code>setTimeout</code>, <code>XMLHttpRequest</code>, etc.).</p><p><img
alt="GWT Menu Bar Widget" src="http://i2.sitepoint.com/g/nl/tt/gwt-menubar.png" align="right" border="0" height="135" width="165"/>You also get a bunch of Java classes for adding <a
href="http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.UserInterface.WidgetGallery.html" class="broken_link">widgets</a> to the page, from simple buttons to complex drop-down menus and trees. All of these widgets offer events that you can subscribe listener objects to, and write Java code to respond to them.</p><p><img
src="http://www.sitepoint.com/authors/images/48_gwt-code.gif" alt="Coding for GWT in IntelliJ IDEA" /></p><p>When you&#8217;re ready to test out your application in a browser, you simply compile your classes in your Java IDE of choice and launch the GWT Shell, which pops up a specialized browser window and loads your application. On Windows, that browser window uses the Internet Explorer rendering engine, whereas on Linux it uses Mozilla.</p><p>The GWT Shell acts as a go-between between your Java classes and the special browser window, allowing your application&#8217;s client-side logic to run within the browser even though it is implemented in Java, not JavaScript. This small miracle actually lets you test and debug your client-side logic as you would any other Java code! Set breakpoints to pause and step through client-side event handlers, write unit tests to verify that your user interface works as designed. It all just works.</p><p><img
src="http://www.sitepoint.com/authors/images/48_gwt-shell.gif" alt="the GWT Shell" /></p><p>At this stage, your application is still a collection Java classes, and the final development step is to compile those classes down to efficient cross-browser JavaScript code. The compiler that comes with GWT actually reads <em>the source code of your classes</em> and generates the equivalent JavaScript code!</p><p>You can then take the generated JavaScript code, along with your static HTML, CSS and image files and dump them on a server as you would for any other web site. The resulting code is entirely self-contained &#8212; no browser plugins or special server technology required.</p><h2>What about AJAX?</h2><p>As I mentioned, the class library does give you access to the <code>XMLHttpRequest</code> object normally used in AJAX applications, but GWT also offers an even slicker method of communicating with the server.</p><p>In addition to your client-side code, you can write Java server-side code. Because it doesn&#8217;t get converted to JavaScript, this code can use the full capabilities of the Java platform, and any additional class libraries you may require.</p><p>In your client-side code, you can set up classes that are able to communicate with your server-side code. When your application is compiled, GWT will automatically generate all the JavaScript needed to communicate with the server on the client-side, and will compile your server-side code to a set of Java Servlets.</p><p>You can deploy these Servlets on any Java web server, and let GWT do the rest. GWT manages the conversion between JavaScript variables on the client-side and Java objects on the server side, and again it all just works.</p><p>GWT also includes a full browser history management system, allowing you to involve the browser&#8217;s Back and Forward buttons in your application&#8217;s navigation, even though the browser never actually leaves the page containing your applications.</p><h2>Sticking Points</h2><p>Google has definitely put together an impressive platform with GWT, but as one would expect (especially from a beta product) it&#8217;s not perfect:</p><ul><li><strong>GWT detects and supports browsers by their user agent string.</strong><p>You must rely on Google to add support for future browsers. Right now, for example, GWT applications are incompatible with IE7. You can <a
href="http://groups.google.com/group/Google-Web-Toolkit/browse_thread/thread/8fc34663134032b1/3fce069ac3114f46">hack the toolkit to treat it like IE6</a>, but that&#8217;s the extent of what you can do to support new browsers.</p></li><li><strong>The bundled GWT widgets make extensive use of tables for layout.</strong><p>If you want you application to generate a standards-compliant document structure, you&#8217;ll need to write your own widgets, which isn&#8217;t a happy prospect.</p></li><li><strong>GWT was written to work with Java 1.4 or later.</strong><p>As such, it does not take advantage of Java 5 features like annotations and generics. This adds some redundancy and bulk to the code you must write, especially when working with the AJAX features of the library. For example, each server-side access point in your application requires you to write an interface to describe the servce, another interface to describe the asynchronous version of the service, and finally a class to implement the service. Using annotations, you could do it all by writing just one class.</p></li><li><strong>The development shell does not support Mac OS X.</strong><p>Google is saying that Mac support is planned, but for now GWT development is limited to Windows and Linux. Compiled GWT applications run just fine in Mac browsers, of course.</p></li><li><strong>Unclear best practices for security and performance.</strong><p>By masking the client-server division, GWT could lead unwary developers to make some serious security and performance blunders. You really need to know what you&#8217;re doing to use GWT effectively.</p></li></ul><p>But the biggest thing lacking in GWT is an example of a finished, real-world application running in the wild. No doubt Google is hard at work on its next big project using GWT, but for now at least GWT is unproven technology.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/first-look-google-web-toolkit/feed/</wfw:commentRss> <slash:comments>24</slash:comments> </item> <item><title>Write Java Web Apps in Visual Basic (or JavaScript!)</title><link>http://www.sitepoint.com/write-java-web-apps-in-visual-basic-or-javascript/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=write-java-web-apps-in-visual-basic-or-javascript</link> <comments>http://www.sitepoint.com/write-java-web-apps-in-visual-basic-or-javascript/#comments</comments> <pubDate>Fri, 19 May 2006 05:35:48 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/05/19/write-java-web-apps-in-visual-basic-or-javascript/</guid> <description><![CDATA[More from the JavaOne 2006 keynotes&#8230; One of the new key features in Java 6 (Mustang), available now in beta and weekly snapshots and slated for release in October, is support for alternative languages running on the JVM. In particular, Java 6 will ship with support for running JavaScript code as a first-class citizen, with [...]]]></description> <content:encoded><![CDATA[<p></p><p>More from the <a
href="http://java.sun.com/javaone/sf/sessions/general/index.jsp" class="broken_link">JavaOne 2006 keynotes</a>&#8230;</p><p>One of the new key features in Java 6 (Mustang), available now in beta and weekly snapshots and slated for release in October, is support for alternative languages running on the JVM. In particular, Java 6 will ship with support for running JavaScript code as a first-class citizen, with complete access to the Java class libraries and the ability to call back and forth between Java and JavaScript code within a single application.</p><p>At JavaOne on Tuesday, Sun took the wraps off of two new projects that are taking advantage of this capability in a way that will be of interest to web developers. The first, Project Semplice, brings the Visual Basic language to the Java platform. Not meant for porting existing VB apps over to Java, but rather for allowing Visual Basic developers to transition to the Java platform while leveraging their existing skills, Semplice lets you write code using VB syntax (including all the automatic type conversion, support for properties implemented by methods, and other niceties that VB developers love so much) that compiles to Java classes that will run on the Java 6 VM. As J# is to Java, Semplice is to Visual Basic.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>In the demo during the keynote, Semplice developer <a
href="http://blogs.sun.com/tor">Tor Norbye</a> (regular on the <a
href="http://javaposse.com/">Java Posse podcast</a>) demonstrated building a simple web application in VB using a pre-release version <a
href="http://developers.sun.com/prodtech/javatools/jscreator/">Java Studio Creator</a>. Starting from a blank page, he dragged a number of JavaServer Faces (JSF) components onto the page, then double-clicked one to add an event handler to it. The editor that popped open contained a new event handler written in Visual Basic, to which he quickly added some simple implementation code, then compiled and ran the application.</p><p>The application, he pointed out, made use of JSF components written in Java, and he accessed properties of these directly from his Visual Basic code. Additionally, the JSF components call the Visual Basic event handling code from within Java. Semplice allows these two languages to work together transparently.</p><p>Thanks to features of the VB language, instead of having to call <code>farenheit.getText()</code> to obtain the value of the <code>farenheit</code> form field, he could refer to it as <code>farenheit.Text</code>, or even just as <code>farenheit</code>, thanks to Visual Basic&#8217;s flexibility. He was also able to use the resulting <code>String</code> value in an arithmetic calculation (i.e. <code>celsius = (farenheit - 32) * 5 / 9</code>) without having to convert it to an integer.</p><p>For developers that want the power of Java when writing server-side business logic, but want a more flexible and loosely-typed language when writing web presentation logic, Visual Basic running on the Java VM could well be a very attractive option!</p><p>Even <em>more</em> flexible than Visual Basic, however, and likely much more familiar to them as well is JavaScript. So why not write the server-side code of web applications in JavaScript? That&#8217;s exactly what <a
href="https://phobos.dev.java.net/" class="broken_link">Project Phobos</a> will do. With Project Phobos, you can either write server-side application logic with JavaScript directly within your HTML templates (much like you can in PHP or JSP), or in separate &#8220;helper&#8221; scripts to keep your code separate from your markup.</p><p>Along with the many other projects working to bring other languages to the Java VM, these two projects give developers even more choices when considering Java as a web development platform.</p><p>The video of both demos may be found in Segment Three of the <a
href="http://java.sun.com/javaone/sf/sessions/general/index.jsp" class="broken_link">Sun Technical General Session: Java Platform Roadmaps: The Big Stuff, Today &#038; Tomorrow</a> from Day 1 of the JavaOne 2006 conference.</p><p><ins
datetime="2006-05-19T23:40:06+00:00"><a
href="http://blogs.sun.com/roller/page/herbertc?entry=project_semplice_visual_basic_for">Full details and screenshots of Semplice in action</a> on project developer &#8220;HerbertC&#8221;&#8216;s blog.</ins></p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/write-java-web-apps-in-visual-basic-or-javascript/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item><div><div
class="post_box two_ads" style="float:left;padding-left:2px;"><div
id='div-gpt-ad-1328645237920-0' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328645237920-0'); });</script> </div></div></div><div
class="clear">&nbsp;</div> <item><title>Sun: Open source Java not whether but how</title><link>http://www.sitepoint.com/sun-open-source-java-not-whether-but-how/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sun-open-source-java-not-whether-but-how</link> <comments>http://www.sitepoint.com/sun-open-source-java-not-whether-but-how/#comments</comments> <pubDate>Thu, 18 May 2006 08:28:41 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/05/18/sun-open-source-java-not-whether-but-how/</guid> <description><![CDATA[Sun has conceded: Java will be open sourced. During his opening keynote at JavaOne 2006, newly annointed Sun CEO Jonathan Schwartz welcomed to the stage Rich Green, Executive VP of Software, with the hard question: &#8220;Are you going to open source Java?&#8221; After a little mock evasiveness, Green explained Sun&#8217;s latest thinking on the matter, [...]]]></description> <content:encoded><![CDATA[<p></p><p>Sun has conceded: Java will be open sourced.</p><p>During his <a
href="http://java.sun.com/javaone/sf/sessions/general/" class="broken_link">opening keynote</a> at <a
href="http://java.sun.com/javaone/sf/">JavaOne 2006</a>, newly annointed Sun CEO <a
href="http://blogs.sun.com/jonathan">Jonathan Schwartz</a> welcomed to the stage Rich Green, Executive VP of Software, with the hard question: &#8220;Are you going to open source Java?&#8221;</p><p>After a little mock evasiveness, Green explained Sun&#8217;s latest thinking on the matter, ending with the bottom line: &#8220;It isn&#8217;t a question of whether, but a question of how. And so we&#8217;ll go do this.&#8221;</p><p>Green did take the time to point out that, from the perspective of <a
href="http://jcp.org/">community involvement</a> and <a
href="https://www.dev.java.net/" class="broken_link">contribution</a> to the development of the Java platform, Java is <em>already</em> effectively open source:</p><blockquote><p>There&#8217;s two battling forces here. There&#8217;s the desire to completely open this up&#8211;complete access&#8211;I mean, so many changes of the licenses have been made that it&#8217;s virtually all there. But there is the sense of wanting to complete the program. The flip side is compatibility really matters. I don&#8217;t think anybody wants to see a diverging Java platform. One of the great values of Java has been that we&#8217;ve been able to keep it together&#8211;something you can all rely on in terms of its consistency and value and evolution. And the challenge, going forward, is how to solve for both of those things.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p></blockquote><p>C|Net has <a
href="http://news.com.com/1606-2_3-6072875.html">video of the conversation</a>, and of course the <a
href="http://java.sun.com/javaone/sf/sessions/general/" class="broken_link">full webcast of the session</a> is available on the JavaOne web site.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/sun-open-source-java-not-whether-but-how/feed/</wfw:commentRss> <slash:comments>6</slash:comments> </item> <item><title>Follow JavaOne 2006 online</title><link>http://www.sitepoint.com/follow-javaone-2006-online/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=follow-javaone-2006-online</link> <comments>http://www.sitepoint.com/follow-javaone-2006-online/#comments</comments> <pubDate>Thu, 18 May 2006 07:51:29 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/05/18/follow-javaone-2006-online/</guid> <description><![CDATA[If you enjoy working in Java like I do, there are probably few places you would rather be right now than at JavaOne 2006. Particularly hot web development topics at JavaOne this year include the newly-released JavaEE 5 platform for building enterprise Java applications more easily, and the associated updates coming in NetBeans 5.5. But [...]]]></description> <content:encoded><![CDATA[<p></p><p>If you enjoy working in Java like I do, there are probably few places you would rather be right now than at <a
href="http://java.sun.com/javaone/sf/">JavaOne 2006</a>. Particularly hot web development topics at JavaOne this year include the newly-released <a
href="http://java.sun.com/javaee/">JavaEE 5</a> platform for building enterprise Java applications more easily, and the associated updates coming in <a
href="http://www.netbeans.org/">NetBeans 5.5</a>.</p><p>But whether due to time, money or geography, not everyone can make it to San Francisco to bask in the Java love for a week.</p><p>Thankfully, you can follow the big picture from wherever you happen to be. All of the general sessions (i.e. keynote  speakers and demos) are available for viewing via <a
href="http://java.sun.com/javaone/sf/sessions/general/" class="broken_link">live and on-demand webcasts</a> that are almost as good as being there (plus you get to skip the boring bits!).</p><p>As for the more focused technical sessions, most of them have published downloadable PDFs containing the slides for free download from the <a
href="http://www.cplan.com/javaone2006/contentcatalog" class="broken_link">session catalog</a>. You can also wait until the dust settles and the slides will be freely available with synchronized audio from <a
href="http://developers.sun.com/learning/javaoneonline/">JavaOne Online</a>.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>And if podcasts are your thing, PodTech.net is hosting a <a
href="http://www.podtech.net/?cat=68">series of podcasts</a> from JavaOne, including the full audio of all the general sessions. Unfortunately, there is no dedicated feeed for just the JavaOne programs, so you might find yourself downloading some programs from other tech conferences going on at the same time.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/follow-javaone-2006-online/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>JRun 5 hits beta</title><link>http://www.sitepoint.com/jrun-5-hits-beta/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jrun-5-hits-beta</link> <comments>http://www.sitepoint.com/jrun-5-hits-beta/#comments</comments> <pubDate>Mon, 01 May 2006 23:22:42 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/05/02/jrun-5-hits-beta/</guid> <description><![CDATA[Adobe (formerly Macromedia) JRun 4 was released in 2002. Since then, Java web development has moved on somewhat. JRun 4 supports Servlet 2.3 and JSP 1.2, while most servers are now on Servlet 2.4 and JSP 2.0. At four years since the last release, many developers assumed development of the server had ceased. But now [...]]]></description> <content:encoded><![CDATA[<p></p><p>Adobe (formerly Macromedia) JRun 4 was released in 2002. Since then, Java web development has moved on somewhat. JRun 4 supports Servlet 2.3 and JSP 1.2, while most servers are now on Servlet 2.4 and JSP 2.0. At four years since the last release, many developers assumed development of the server had ceased.</p><p>But now it looks like JRun might be set to rise from the ashes, with Adobe <a
href="http://www.bpurcell.org/blog/index.cfm?mode=entry&#038;entry=1084">looking for beta testers</a> of a major new release. At this stage, Adobe is tight-lipped on what new features will come with this version&#8211;EJB 3.0? <a
href="http://www.sitepoint.com/jetty-60-to-provide-new-architecture-for-ajax-apps/">Jetty-like continuations?</a> More affordable pricing?</p><p>I&#8217;ve asked for a look at the beta, and will report what I can when I can.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jrun-5-hits-beta/feed/</wfw:commentRss> <slash:comments>3</slash:comments> </item> <item><title>Tomcat sucks&#8230; Is Apache flawed?</title><link>http://www.sitepoint.com/tomcat-sucks-apache-flawed/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tomcat-sucks-apache-flawed</link> <comments>http://www.sitepoint.com/tomcat-sucks-apache-flawed/#comments</comments> <pubDate>Fri, 21 Apr 2006 05:26:21 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/04/21/tomcat-sucks-but-what-doesnt/</guid> <description><![CDATA[High on my list of Java blogs is Hani Suleiman&#8217;s The BileBlog, in which he gives unapologetically abrasive reviews of popular Java projects and the people behind them. In the past, he has had been less than complimentary of the Apache Project&#8216;s various open source (&#8220;opensores&#8221;) Java offerings like Maven and Struts. Today, he took [...]]]></description> <content:encoded><![CDATA[<p></p><p>High on my list of Java blogs is Hani Suleiman&#8217;s <a
href="http://jroller.com/page/fate">The BileBlog</a>, in which he gives unapologetically abrasive reviews of popular Java projects and the people behind them. In the past, he has had been <a
href="http://jroller.com/search/fate?q=Apache">less than complimentary</a> of the <a
href="http://www.apache.org/">Apache Project</a>&#8216;s various open source (&#8220;opensores&#8221;) Java offerings like <a
href="http://maven.apache.org/">Maven</a> and <a
href="http://struts.apache.org/">Struts</a>. Today, he <a
href="http://jroller.com/page/fate?entry=why_i_hate_tomcat">took Tomcat to task</a>.</p><p><a
href="http://tomcat.apache.org/">Tomcat</a>, of course, provides the reference implementations for the Servlet and JSP specifications, but by virtue of the fact that it is free, it&#8217;s also the server of choice for many small-to-medium businesses. I <a
href="http://www.sitepoint.com/in-search-of-a-beginner-friendly-server/">took a critical look at Tomcat</a> myself awhile back, while looking for a beginner-friendly Java web application server (I&#8217;m still looking).</p><p>Suleiman&#8217;s critique of Tomcat is based, somewhat refreshingly (he often resorts to unpersuasive, if entertaining, personal attacks on the developers), on the quality of the project&#8217;s code&#8211;or rather its lack thereof. Choosing a pivotal but relatively uncomplicated class (<a
href="http://svn.apache.org/repos/asf/tomcat/container/tc5.5.x/catalina/src/share/org/apache/catalina/servlets/DefaultServlet.java" class="broken_link"><code>DefaultServlet</code></a>, which is responsible for serving static resources like HTML/CSS/JavaScript files and images), he points out many examples of terrible coding practice, of which these are only a sampling:<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><dl><dt>Initialization code that lazily catches <code>Throwable</code></dt><dd><pre><code class="java">        // Set our properties from the initialization parameters
        String value = null;
        try {
            value = getServletConfig().getInitParameter("debug");
            debug = Integer.parseInt(value);
        } catch (Throwable t) {
            ;
        }
        try {
            value = getServletConfig().getInitParameter("input");
            input = Integer.parseInt(value);
        } catch (Throwable t) {
            ;
        }</code></pre><pre><code>Throwable</code> is the base interface for all Java exceptions an errors, many of which have no business being caught by this sort of code, let alone being ignored as this code will do. If the server happens to run out of memory while initializing a <code>DefaultServlet</code>, for example, this code will ignore the resulting error and attempt to continue running.
</dd>
<dt>Attempts to identify particular exceptions by portions of their message strings</dt>
<dd>
<pre><code class="java">        try {
            serveResource(request, response, true);
        } catch( IOException ex ) {
            // we probably have this check somewhere else too.
            if( ex.getMessage() != null
                &amp;&amp; ex.getMessage().indexOf("Broken pipe") &gt;= 0 ) {
                // ignore it.
            }
            throw ex;
        }</code></pre><p>Fortunately, the <code>if</code> statement in question (which, from the comment, it seems the developer was rather uncertain about) doesn't actually cause the exceptions it identifies to be ignored (as the second comment says it should do), so this confusing twist of poor programming is actually useless anyway.</p></dd><dt>A method that returns an exception instead of throwing it</dt><dd><pre><code class="java">    protected IOException copyRange(InputStream istream,
                                  ServletOutputStream ostream) {
        // Copy the input stream to the output stream
        IOException exception = null;
        ...
            try {
                ...
            } catch (IOException e) {
                exception = e;
                ...
            }
        ...
        return exception;
    }</code></pre></dd></dl><p>As a believer in open source development, I looked at every issue he pointed out to give it the benefit of the doubt. "Okay, it looks silly, but there must be a good reason that they did that." There wasn't, of course, unless you consider laziness or ignorance a good reason.</p><p>For a project produced under the public scrutiny of the open source development, these are disturbingly fundamental issues indeed. For me, the most important question becomes not whether or not Tomcat sucks, but whether this level of code quality is the exception or the norm in the Apache camp.</p><p>I know for a fact that there is plenty of good quality open source Java code in the wild. I've probed into the code of <a
href="http://www.sitepoint.com/jetty-really-is-lightweight/">Jetty</a> a number of times, for instance, and have been pleasantly surprised by what I found there. I also know that poor open source code <a
href="http://www.sitepoint.com/evaluating-php-applications/">isn't just a problem that faced by Java</a>. But Apache is supposed to be a leader in the field.</p><p>If the repeated condemnations of The BileBlog are any indication, the majority of the web could be running software like this--code that looks like it was written in a desperate push to meet a deadline with something that works... most of the time... just barely.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/tomcat-sucks-apache-flawed/feed/</wfw:commentRss> <slash:comments>22</slash:comments> </item><div><div
class="post_box two_ads" style="float:left;padding-left:2px;"><div
id='div-gpt-ad-1328645237920-1' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328645237920-1'); });</script> </div></div></div><div
class="clear">&nbsp;</div> <item><title>Sun Developer Days 2006: Day Two</title><link>http://www.sitepoint.com/sun-developer-days-2006-day-two/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sun-developer-days-2006-day-two</link> <comments>http://www.sitepoint.com/sun-developer-days-2006-day-two/#comments</comments> <pubDate>Sun, 09 Apr 2006 21:14:12 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/?p=1508</guid> <description><![CDATA[The second day of Sun&#8217;s Developer Days 2006 conference in Melbourne last week was a similar mixed bag to the first. Be sure to read my coverage of day one if you missed it. Before the day&#8217;s sessions began in earnest, Sun organiser David Coldrick got up to plug two useful resources for Java developers [...]]]></description> <content:encoded><![CDATA[<p></p><p>The second day of Sun&#8217;s <a
href="http://au.sun.com/events/developer/index.jsp?cid=104303">Developer Days 2006 conference</a> in Melbourne last week was a similar mixed bag to the first. Be sure to read <a
href="http://www.sitepoint.com/sun-developer-days-2006-day-one/">my coverage of day one</a> if you missed it.</p><p>Before the day&#8217;s sessions began in earnest, Sun organiser <a
href="http://blogs.sun.com/coldrick">David Coldrick</a> got up to plug two useful resources for Java developers to keep up with the latest developments between Developer Days conferences: <a
href="http://javaposse.com/">The Java Posse podcast</a> (which I highly recommend as well!), and <a
href="http://www.javapassion.com/">javapassion.com</a>, which I have <a
href="http://www.sitepoint.com/learn-j2ee-programming-with-passion/">covered in this blog</a> before.</p><h2 id="session-lee"><cite>Building Great Games for the Mobile World</cite>, Chuk Munn Lee (Sun)</h2><p>Having <a
href="http://j2mebomber.sourceforge.net/">done some work on mobile games</a> already, I was hoping for some insight into the technical issues that face game developers on this platform: device-specific API fragmentation, application size and processing speed limits, inconsistent control methods, and more. What we got instead was a non-technical overview about the pros and cons of developing games for mobile handsets as compared to the PC- and console-based game platforms.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>In brief, <a
href="http://java.sun.com/javame/">Java Micro Edition (ME)</a> is a lightweight platform that can let you produce a fully-realized game for millions of potential users with as little as one man-month of development time. Successful games for this platform should take into account the fact that gamers will be playing on-the-go, for brief periods, and may stop playing at any time. Given this, the popular practice of adapting old games from other platforms to handsets is not a great approach.</p><h2 id="session-ritter"><cite>Optimizing Performance for Java SE &amp; Java EE Applications</cite>, Simon Ritter (Sun)</h2><p>Again, my expectations were a bit off the mark for this session (I really wish the conference programme had included session abstracts). Rather than a grab bag of useful techniques for writing speedier code, or an overview of certain common performance anti-patterns, what we got was a tutorial on tuning the garbage collection algorithms in the Sun Java Virtual Machine (VM) using a variety of undocumented (or poorly documented) <a
href="http://java.sun.com/performance/reference/whitepapers/tuning.html">command-line switches</a>.</p><p>I quite enjoyed the explanation of the VM&#8217;s heap management techniques, and how they allow for the tendency of Java applications to make extensive use of short-lived objects that must be garbage collected quickly and efficiently for Java to work, as well as the look at the <a
href="http://java.sun.com/performance/reference/whitepapers/tuning.html#section4.2.5">biased locking</a> algorithm that was introduced to further improve performance in version 1.5.0_06 of the Java 5 runtime. But the vast majority of the performance tweaks discussed would apply really only to high-load, multi-processor servers, so were little more than technical curiosities for me.</p><h2 id="session-patel"><cite>SOA, JBI, BPEL: Strategy, Design &amp; Best Practices</cite>, Rima Patel (Sun)</h2><p>In <a
href="http://www.sitepoint.com/sun-developer-days-2006-day-one/#session-rao2">his day one session</a>, Ashwin Rao showed off some of the tools Sun is cooking up for developers to tackle the unique challenges of building applications based on discrete, specialized services &#8212; a practice known as Service Oriented Architecture (SOA). Ms. Patel took a step back with this session and looked at the motivations and technical challenges of SOA, which must be considered long before development tools come into the picture.</p><p>While developers are used to facing new accronyms and buzzwords that, once grasped, bring technical benefits including performance, usability, and ease of development, SOA is very different, in that the motivations that drive it are largely business-centric.</p><p>Many big businesses today are straining under the weight of overlapping legacy systems that have been developed and connected on an ad hoc basis, on conflicting, often vendor-specific platforms. The SOA approach to this problem is to identify key <em>services</em> that exist within these systems and to either reimplement them or wrap the existing systems in interfaces such that applications can discover and access them openly, asychronously, statefully and securely through the exchange of XML documents that mirror the business documents that would change hands in the paper-based equivalents to the relevant business processes.</p><p>Ms. Patel went on to briefly outline the <a
href="http://java.sun.com/integration/">Java Business Integration (JBI)</a> specification, which provides the plumbing for SOA applications in the form of an open framework that is both vendor and platform neutral. Not a bad option if you&#8217;re rearchitecting the IT systems for a major bank, which I&#8217;m not. For me, this session was mainly about confirming that my vision of what SOA means roughly matches with Sun&#8217;s. I make no guarantees as to whether or not it matches yours.</p><h2 id="session-ritter2"><cite>Java SE: Tiger, Mustang and Dolphin</cite>, Simon Ritter (Sun)</h2><p>A relatively straightforward session, this talk rattled through an overview of the most high-profile features coming in <a
href="https://mustang.dev.java.net/" class="broken_link">Java 6 (codenamed Mustang)</a> later this year. There&#8217;s plenty of <a
href="http://blogs.sun.com/roller/page/dannycoward?entry=the_10_things_you_need">good coverage</a> of this going around, especially because Sun has been very open about Mustang&#8217;s development, with weekly builds available for download and testing.</p><p>Changes most likely to affect web developers in Java 6 are: <a
href="http://blogs.sun.com/roller/page/dannycoward/20060227">full support for XML web services</a> built in, the inclusion of the Rhino scripting engine, which will permit JavaScript code to run on the Java VM and make full use of Java class libraries; JDBC 4.0, which will <a
href="http://weblogs.java.net/blog/lancea/" class="broken_link">simplify and enhance</a> the primary API for Java applications connecting to databases; and <a
href="http://blogs.sun.com/roller/page/dannycoward/20060310">better debugging support</a>, making it easier to detect and diagnose deadlocks, memory leaks, and other runtime issues.</p><p>Personally, I&#8217;m most excited about the <a
href="http://weblogs.java.net/blog/chet/archive/2006/02/these_are_some.html">enhancements for desktop-based Java applications</a>, but Mr. Ritter skipped over most of these in favour of more core changes to the platform.</p><p>Mr. Ritter did take a few minutes to give some hand-wavy examples of the sorts of things planned for Java 7 (codenamed Dolphin), including support for XML code appearing natively within Java code, and bytecode changes to support dynamic languages (such as scripting languages) running on the Java VM, but with almost nothing set in stone for Dolphin, every scrap of information was accompanied by the disclaimer: &#8220;On the other hand, we might not do this at all.&#8221;</p><h2 id="session-chen"><cite>Making AJAX more effective with servlets, JavaServer Pages Technology, &amp; JavaServer Faces Technology</cite>, Doris Chen (Sun)</h2><p>The confused title should have scared me off, but I went along to this session hoping at least to see some elegant examples of supporting AJAX applications within server-side Java code. I gave up and left after watching roughly 45 minutes of the speaker&#8217;s confused and confusing attempts to simply define what AJAX <em>was</em>. I wasn&#8217;t the only one to walk out.</p><p>I hate to pan the presenter further, but it&#8217;s a sad day indeed when you can&#8217;t keep a room full of developers interested in a presentation about AJAX.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/sun-developer-days-2006-day-two/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> <item><title>Sun Developer Days 2006: Day One</title><link>http://www.sitepoint.com/sun-developer-days-2006-day-one/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=sun-developer-days-2006-day-one</link> <comments>http://www.sitepoint.com/sun-developer-days-2006-day-one/#comments</comments> <pubDate>Wed, 05 Apr 2006 11:08:20 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/04/05/sun-developer-days-2006-day-one/</guid> <description><![CDATA[Sun Microsystems is winding up a tour of Australia and New Zealand with the final stop of its Sun Developer Days 2006 conference today and tomorrow in Melbourne. Fellow SitePointer Lachlan Donald and I were there today to take in the Java vibes, and as with most free conferences there was a great deal of [...]]]></description> <content:encoded><![CDATA[<p></p><p>Sun Microsystems is winding up a tour of Australia and New Zealand with the final stop of its <a
href="http://au.sun.com/events/developer/index.jsp?cid=104303">Sun Developer Days 2006</a> conference today and tomorrow in Melbourne. Fellow SitePointer Lachlan Donald and I were there today to take in the Java vibes, and as with most free conferences there was a great deal of variation in the quality of the sessions we attended.</p><h2 id="session-brewin"><cite>Sun Developer Tools</cite>, Bob Brewin (Sun)</h2><p>In his keynote, Mr. Brewin spoke chiefly about the push Sun is making towards Ease of Development (EoD) across the entire Java platform and the set of Sun developer tools. Key examples of this included the <a
href="http://java.sun.com/developer/technicalArticles/releases/j2se15/">new language features in Java SE 5.0</a>, the release as a free download of <a
href="http://developers.sun.com/prodtech/javatools/jscreator/">Java Studio Creator</a>, and the <a
href="http://java.sun.com/j2ee/persistence/faq.html">Java Persistence API</a>, which is set to replace entity beans in EJB 3.0. This is all old news, however, and Brewin looked like he&#8217;d delivered this keynote fifty times before. Though some of the improvements being made to the Java landscape may be inspiring, this session was not.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><h2 id="session-ritter"><cite>Changing the Landscape of Software Development</cite>, Simon Ritter (Sun)</h2><p>Mr. Ritter&#8217;s keynote essentially covered all of the ways Sun is fostering open source development with Java. Again, there was very little in this talk that would have been news to the people in the room, and Ritter seemed vaguely embarassed by this fact (even wondering aloud at some of the choices of imagery &#8220;his boss&#8221; had made in assembling his slides for him). The end of the session, which described all the ways in which Java was <em>as good as</em>, if not actually open source, seemed downright defensive&#8230; which was  especially odd because a quick poll of the audience indicated only a small minority thought that it should be.</p><h2 id="session-rao1"><cite>Rapid Web Application Development Using Sun Java Studio Creator</cite>, Ashwin Rao (Sun)</h2><p>Very much a quick introduction, this session took a quick spin through <a
href="http://developers.sun.com/prodtech/javatools/jscreator/">Java Studio Creator</a>, a tool for drag-and-drop web application development using <a
href="http://java.sun.com/javaee/javaserverfaces/">JavaServer Faces (JSF)</a>. I&#8217;ve seen a couple of introductions like this in the past, and while I applaud what Sun has achieved with Creator in terms of making it possible to throw together Java web applications in a hurry, I&#8217;m still not sold on its merit for producing best practice code (at least, not out of the box).</p><p>Much like Microsoft&#8217;s <a
href="http://msdn.microsoft.com/vstudio/express/vwd/">Visual Web Developer</a> edition of Visual Studio (with which Creator was obviously designed to compete), Creator lets you quickly produce web user interfaces by dragging ready-made components onto a design view. I shudder every time I consider the accessibility repercussions of using this development mechanism naively (particularly in the default &#8220;grid&#8221; layout mode, which makes use of absolute pixel coordinates to position all page elements).</p><p>That said, the JSF technology that Creator is based on is certainly capable of producing standards compliant, accessible web sites. What I want to know is whether the quick-and-dirty results that Creator seems so ready to produce are the fault of the tool (in which case I humbly suggest Sun should go back to the drawing board), the bundled components (in which case a dedicated group of developers could produce a more &#8220;responsible&#8221; set of components to use in Creator), or just the way the developer chooses to use them (in which case SitePoint should probably write a book similar to <a
href="http://www.sitepoint.com/books/dreamweaver1/">its recent Dreamweaver title</a>).</p><h2 id="session-lokman"><cite>SAP Technical Session: Running Open Source based Java EE Applications on the SAP Web AS</cite>, Taib Lokman (SAP)</h2><p>While I&#8217;ve certainly seen the name <a
href="http://www.sap.com/">SAP</a> bandied about, I didn&#8217;t really understand how it fit into the Java space. It turns out that SAP has been in the <a
href="https://www.sdn.sap.com/">Java enterprise development business</a> for awhile, and today it offers its own suite of Java EE servers and Eclipse-based development tools. SAP sponsored the conference, so I was expecting a sales pitch in this session. What I got instead was unexpected, and very confusing.</p><p>In his talk, Mr. Lokman introduced and even demonstrated a number of popular open source Java enterprise technologies (Struts, Axis, Ant, etc.), seemingly held them up as great things that we should all be using, and then explained that SAP had its own more or less proprietary alternative that you would have to deal with if you were ever called upon to work on a project that relied on SAP&#8217;s platform. And that was it. Seriously, it was like &#8220;Who uses Struts? Great! Isn&#8217;t it cool? But if you use SAP, you&#8217;ll need to learn NetWeaver, which is quite different, instead.&#8221; Rinse and repeat.</p><h2 id="session-patel"><cite>Persistence for Java SE &amp; Java EE</cite>, Rima Patel (Sun)</h2><p>As the co-author of the book<cite>Mastering EJB, 3rd Ed.</cite> (<a
href="http://www.theserverside.com/books/wiley/masteringEJB/index.tss">free PDF download</a>), which apparently has a 4th edition coming out soon that will also be freely available for download, Ms. Patel really knows her stuff when it comes to Enterprise JavaBeans (EJB). That translated to a dynamic and illuminating talk about what we can expect from the soon-to-be-released EJB 3.0.</p><p>The single biggest change to EJB 3.0 is the radical rethinking and simplification of entity beans. Used to represent database records (and other persistent data items) as Java objects that can participate in transactions and have their state synchronized with the database, entity beans have been a serious pain point in EJB for a long time. They require developers to write a lot of repetitive boilerplate code, and were limited in many ways that Java objects normally aren&#8217;t. In EJB 3.0, entity beans have been scrapped in favour of the <a
href="http://java.sun.com/j2ee/persistence/faq.html">Java Persistence API</a>, which lets you use label plain old Java objects (POJOs) as entities, which can do all the things entity beans could do, but without all the tedious coding overhead and without all the limitations of entity beans.</p><p>For awhile now, Java developers have had the benefits of a lot of the Java Persistence API in the form of <a
href="http://www.hibernate.org/">Hibernate</a>, an open source library that maps relational database records to Java objects. With the Java Persistence API, however, those powerful capabilities will not only become a standard part of the Java EE platform, but they will be able work within EJB architectures, with all the resource and transaction management that EJBs were designed to provide.</p><h2 id="session-rao2"><cite>Tackling Complexity &amp; Improving Productivity in Developing to SOA</cite>, Ashwin Rao (Sun)</h2><p>I haven&#8217;t had much to do with Service Oriented Architecture (SOA), an emerging vision of enterprise development where discrete, specialized services can be assembled and orchestrated together to produce useful applications with high degrees of scalability and flexibility. It&#8217;s certainly the direction that large enterprises are moving in, but at ground level where most of the developers in our audience reside, it&#8217;s not much of a factor. This session was an opportunity to check in with the state of SOA.</p><p>Mr. Rao briefly outlined the realities of SOA today, and then concluded that managing the resulting complexity means coming up with tools that address the unique challenges of orchestrating disparate services in a useful way. This offered a convenient lead-in to a demo of <a
href="http://developers.sun.com/prodtech/javatools/jsenterprise/">Java Studio Enterprise 8</a>&#8216;s UML modeling features, and the visual designer for Business Process Execution Language (BPEL) that Sun recently debuted in <a
href="http://www.netbeans.org/community/releases/55/">a preview of the Netbeans 5.5 Enterprise Pack</a>.</p><p>The BPEL designer lets you assemble multiple web services together to produce composite services, essentially by drawing a flowchart to generate an XML description of the required process behind the scenes. Although the flowcharts produced by the tool were undeniably slick, whenever we glanced that the generated XML code it seemed to me that we could have written that code in much less time than it took to step through the wizards required to produce it graphically. Assuming SOA takes off and composite services will begin to involve more complex interactions than the simple demo we saw, I could see the value in being able to visualize those interactions rather than slogging through XML code; nevertheless, I was left with the impression that the problems of SOA that need to be solved are still being discovered, and as a result the tools are at least a generation away from becoming truly useful in the wild.</p><h2 id="session-caicedo"><cite>NetBeans Extreme: Matisse, Collaboration, Profiling and Plug-ins</cite>, Angela Caicedo (Sun)</h2><p>In this marathon 90-minute session, Ms. Caicedo demonstrated just about every aspect of <a
href="http://www.netbeans.org/">NetBeans 5.0</a>, the latest version of Sun&#8217;s free Java IDE, that has been enhanced in this latest release.</p><p>NetBeans 5.0 caused a splash in the desktop application space by introducing <a
href="http://form.netbeans.org/" class="broken_link">Matisse</a>, a remarkable new GUI layout tool that removes a lot of the complexity that Java developers have come to accept from the Java&#8217;s Swing GUI API without sacrificing much (if any) flexibility or quality in the finished product. Instead of relying upon Swing&#8217;s existing <code>LayoutManager</code> classes (such as the infamous <code>GridBagLayout</code>), Matisse uses its own <code>GroupLayout</code> class, which has since been slated for inclusion in the upcoming <a
href="http://java.sun.com/javase/6/">Java SE 6.0</a>. The demo of Matisse in this session was enticing, if not entirely convincing to a veteran <code>GridBagLayout</code> user like me. It may be miles and miles ahead of any visual GUI layout tool Java has had in the past, but the demo suffered from a couple of minor layout issues that I could have avoided with <code>GridBagLayout</code>, and I&#8217;m curious if Matisse offers a solution to these.</p><p>The collaboration features were certainly a surprise &#8212; I&#8217;m not sure how I missed their mentions in the excitement surrounding NetBeans 5.0&#8242;s release. Similar features formed the major enhancements in JBuilder 2006 last year, but with the future of that IDE in serious jeopardy, it&#8217;s nice to see these features a healthy IDE like NetBeans. Essentially, the IDE includes an instant messaging client that allows you not only to chat to your fellow developers, but also to share your local project code, browse and edit that code collaboratively through shared views, and even run shared debugging sessions to locate problems together. I had assumed that, for this to work, both developers would need to have their own copy of the project in question on their system, but the demo showcased the fact that shared coding sessions are actually centered around one developer&#8217;s copy of the project, and all the other developers need is a copy of NetBeans to participate.</p><p>Next up, Caicedo took the profiling features in NetBeans for a spin, pinpointing the thread responsible for hanging the interface of a simple Swing application, and then identifying a slow method in a web application. The new profiler is one of NetBeans&#8217;s biggest advantages over the other, more popular free Java IDE, Eclipse, which lacks built-in profiling. While not quite as powerful as a dedicated profiling product like <a
href="http://www.yourkit.com/">YourKit Java Profiler</a>, the tools in NetBeans 5.0 are certainly respectable, and will assist in resolving all but the twistiest of performance issues.</p><p>Last, but not least, we got to watch a complete plug-in for the NetBeans IDE come to life before our eyes. With Java development spanning so many different application domains, it&#8217;s impossible for a single IDE to bundle every tool that a given developer might need. That&#8217;s why all the big IDEs these days place a great deal of emphasis on extensability through plug-in architectures. NetBeans is no exception, and with the integrated wizards and packaging tools Caicedo was able to add a Google search field to the NetBeans toolbar in mere minutes. IDE plug-in development, at least for NetBeans, is certainly a far less intimidating discipline than I had previously imagined.</p><p>So will I be switching to NetBeans tomorrow? I&#8217;m afraid not. Although NetBeans 5.0 has made some impressive strides, and the new pieces in the tool are certainly impressive, many of the basic facilities still have a &#8220;toy IDE&#8221; feel that I just can&#8217;t get past. Lack of fundamental facilities like multiple run configurations and project groups just don&#8217;t quite cut it for me. Still, there&#8217;s a lot to like in new features and old (I especially appreciate the use of Ant for all build tasks), so I&#8217;ll certainly be keeping an eye on NetBeans.</p><p>All up, after a weak start, the day got a great deal more interesting as talk turned from general spin to down-and-dirty coding. Hopefully tomorrow will hold more of the same!</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/sun-developer-days-2006-day-one/feed/</wfw:commentRss> <slash:comments>7</slash:comments> </item> <item><title>JBuilder Seeks Good Home</title><link>http://www.sitepoint.com/jbuilder-seeks-good-home/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jbuilder-seeks-good-home</link> <comments>http://www.sitepoint.com/jbuilder-seeks-good-home/#comments</comments> <pubDate>Fri, 10 Feb 2006 02:57:36 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/?p=1408</guid> <description><![CDATA[Across the web, headlines are proclaiming the demise of JBuilder, the venerable Java IDE from Borland. The truth of the matter, as always, is not so clear cut. Borland has announced that it&#8217;s looking to sell off its IDE business, including all the developers and staff responsible for producing and selling JBuilder, as well as [...]]]></description> <content:encoded><![CDATA[<p></p><p>Across the web, headlines are <a
href="http://www.javalobby.org/forums/thread.jspa?threadID=63512">proclaiming the demise of JBuilder</a>, the venerable Java IDE from Borland.</p><p>The truth of the matter, as always, is not so clear cut. <a
href="http://blogs.borland.com/davidi/archive/2006/02/08/23013.aspx" class="broken_link">Borland has announced</a> that it&#8217;s looking to sell off its IDE business, including all the developers and staff responsible for producing and selling JBuilder, as well as Delphi, C++Builder, C#Builder and others. The announcement has a number of encouraging quotes by the company&#8217;s chief product evangelist about the products&#8217; bright future in the &#8220;new company.&#8221;</p><p>When such a company will eventuate, and whether or not it will have the budget and drive to keep JBuilder in the competitive Java IDE game (currently dominated by Eclipse and NetBeans, with IDEA a trendy contender), remains to be seen.</p><p>As a longtime JBuilder user, I always enjoyed the product&#8217;s rich feature set. It always seemed like if it was worth doing, JBuilder could do it. It wouldn&#8217;t always be <em>easy</em> or <em>attractive</em>, but you could do it. Borland recently released JBuilder 2006, the twelfth major release of the IDE, where the major changes (aside from supporting new standards and technologies) were in the area of team development: with the new version, two developers can work together on a piece of code, each from his or her own desktop. The IDE provides tools for the developers to chat and give/take control over a shared code view.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>But as JBuilder has evolved over the past few years, I&#8217;ve observed more and more focus on producing new &#8220;peripheral&#8221; features like these, while the core experience of day-to-day coding has remained relatively unchanged. As its innovative competitors have deployed rich coding assistance tools (such as static analysis of source code in IDEA and continuous integration in Eclipse), JBuilder&#8217;s efforts in these areas have seemed unpolished in some cases.</p><p>Several months ago, I took the plunge and switched to IntelliJ IDEA, which offers free licenses to developers who work on open source products like I do. Although there were a few features I missed from JBuilder (such as support for JAR archive signing in the build process), the overall environment and workflow just felt more polished, and more carefully thought out, while JBuilder always felt like just a dazzling collection of features.</p><p>Up until this announcement, the next step in JBuilder&#8217;s evolution was to be its <a
href="http://www.sitepoint.com/some-ide-news/">reincarnation on the Eclipse platform</a>, codenamed Peloton, with some of the base components to be open sourced. The rights to this in-development product will go to whichever company buys Borland&#8217;s IDE business, but until that happens, and the new company announces its intentions, it&#8217;s safe to say that JBuilder&#8217;s future &#8212; in <em>any</em> form &#8212; is in definite jeopardy.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jbuilder-seeks-good-home/feed/</wfw:commentRss> <slash:comments>1</slash:comments> </item> <item><title>Step-by-Step Jakarta Tapestry</title><link>http://www.sitepoint.com/jakarta-tapestry/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=jakarta-tapestry</link> <comments>http://www.sitepoint.com/jakarta-tapestry/#comments</comments> <pubDate>Wed, 01 Feb 2006 14:00:00 +0000</pubDate> <dc:creator>Alexander Kolesnikov</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://blogs.sitepoint.com/?p=34632</guid> <description><![CDATA[The Jakarta Tapestry framework is a hidden treasure of Java web development. So says Alexander, as he steps us through the process of setting up the development environment and building a basic web app with this easy-to-use Java-based technology.]]></description> <content:encoded><![CDATA[<p></p><p><strong>The Jakarta Tapestry framework is a hidden treasure of Java web development. It greatly simplifies the work of both web designers and developers. It offers significant convenience by transparently handling much of the boring &quot;plumbing&quot;. It even changes the paradigm of web development (at least in terms of the presentation tier) to one that is more natural. </strong></p><p>Yet Tapestry remains more or less unknown to a great majority of web developers, for numerous reasons. The most obvious is Tapestry&#8217;s legendary &quot;steep learning curve&quot; which, in my opinion, is more myth than reality: Tapestry is in fact easier to learn and use than are many other frameworks. Yes, internally Tapestry is more complex than its predecessors, in the same way that a contemporary camcorder is much more complex than those mechanical devices that our grandfathers used to produce their amateur movies. But is a camcorder more difficult to use? No, it is much, much easier (believe me &#8212; I&#8217;ve tried both types of devices).</p><p>All right, enough brainwashing, let&#8217;s jump straight in! By the end of this tutorial, you&#8217;ll be able to decide for yourself just how easy Tapestry is to use. We won&#8217;t be creating the traditional &#8216;Hello World&#8217; web application here &#8212; that really would be too trivial with Tapestry. We&#8217;ll start with something more realistic: a login form.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>On our way to unraveling the wonders of Tapestry, we need to pass through a kind of purgatory &#8212; the process of creating of a working, Tapestry-ready configuration on our computers. This is more or less standard practice for Java web development, so we&#8217;ll make it as simple as possible.</p><p>If you&#8217;ve ever tried any kind of Java Web development &#8212; using servlets, JSP or Struts &#8212; chances are that you&#8217;ll already have most of the necessary components on your machine. But if not, don&#8217;t worry: we&#8217;ll install everything very quickly and easily. In fact, the installation is mostly about downloading and unpacking ready-to-use pieces of software.</p><h5>Requirements</h5><div
id="adz" class="vertical"><script type="text/javascript">GA_googleFillSlot("Articles_6_300x250");</script></div><p>We&#8217;ll need the following:</p><ul><li>Java Development Kit (JDK)</li><li>Tomcat Web server</li><li>Eclipse Integrated Development Environment (IDE)</li><li>Spindle plugin for Eclipse IDE</li><li>Tapestry-specific libraries</li></ul><p>If you already have some of these components installed on your computer, just skip the appropriate part of the instructions that follow.</p><p>Although Tapestry 4 has just been released, we&#8217;ll start from the third version of the framework. Many concepts of Tapestry development are more or less the same in both versions &#8212; especially from a beginner&#8217;s viewpoint. Additionally, Spindle, a very convenient and helpful tool for Tapestry development, is currently only available for Tapestry 3.</p><p>What we are going to do now may not seem very exciting, but we need to do this just once. Some of the following instructions are platform-specific &#8212; choose whichever are appropriate for you.</p><h5>Installing the JDK</h5><p>If you&#8217;ve ever tried your hand at Java development, you&#8217;ll already have a JDK installed on your computer. It comes pre-installed with the latest versions of Mac OS X. To verify whether you have it or not, try the following.</p><p>In Windows, choose Start &gt; Run&#8230;, then type <code>cmd</code> and press the OK button. In Linux or Mac OS X, simply open a terminal window.</p><p>Enter the following command at the prompt:</p><pre><code>javac</code></pre><p>Press Enter. If your computer has a JDK installed and configured, you will see more than a dozen lines of output, beginning with the following:</p><pre><code>Usage: javac &lt;options&gt; &lt;source files&gt; <br />
where possible options include: <br />
 &nbsp;-g &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Generate all debugging info <br />
... more lines of output ...</code></pre><p>If your computer didn&#8217;t recognize the command, you&#8217;ll need to install a JDK. You could install either the latest version, JDK 5.0, or the previous one, JDK 1.4.2. Both are fine for the purposes of this tutorial. Let&#8217;s assume that you&#8217;re going to install the most recent version.</p><p><strong><em>1. Download the JDK</em></strong></p><p>For Windows and Linux: <a
class="sublink" href="http://java.sun.com/j2se/1.5.0/download.jsp">download the recent version of JDK 5.0</a> (at the time of writing, it&#8217;s JDK 5.0 Update 6). Please note: you will need the JDK, not the JRE!</p><p>Some advice for Linux users: whichever distribution you use, you might wish to download the Linux self-extracting file (<code>jdk-1_5_0_06-linux-i586.bin</code>), not the Linux RPM self-extracting file (<code>jdk-1_5_0_06-linux-i586-rpm.bin</code>). In some cases, the former is easier to install and configure.</p><p>For Mac OS X: You may not need to download anything, as you probably already have something like the JDK 1.4.2_09 installed on your computer. If you want the new version of the JDK, <a
class="sublink" href="http://www.apple.com/support/downloads/java2se50release3.html">download it here</a>. However, be warned that changing the default version of the JDK in Mac OS X is not a trivial task, so for the purposes of this tutorial, you might want to stick to the pre-installed JDK 1.4.2.</p><p>To better understand the problems running Java 5 on Mac OS X, refer to <a
class="sublink" href="http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=next_topic&#038;f=73&#038;t=000209">this discussion at the Javaranch.com forum</a>.</p><p><strong><em>2. Install the JDK</em></strong></p><p>With Windows and Mac OS X versions, you aren&#8217;t given many choices; just launch the executable file you&#8217;ve downloaded, and follow the instructions.</p><p>In Linux, you&#8217;ll need to change permissions for the downloaded file in order to be able to execute it:</p><pre><code>chmod +x jdk-1_5_0_06-linux-i586-rpm.bin</code></pre><p>Then, execute it:</p><pre><code>./jdk-1_5_0_06-linux-i586-rpm.bin</code></pre><p>Once you agree to the terms and conditions that are shown to you, the file will unpack itself. Move the resulting directory, <code>jdk1.5.0_06</code>, to the location where you want it to live (e.g. to <code>/usr/java</code>).</p><p>Now, you need to add the bin subdirectory (say, <code>/usr/java/jdk1.5.0_06/bin</code>) to the PATH of your machine. One way you can accomplish this under Linux is to add the following two lines to your <code>.bashrc</code> file (if you use bash, of course):</p><pre><code>PATH=/usr/java/jdk1.5.0_06/bin:$PATH <br />
export PATH</code></pre><p>That&#8217;s it! If you followed these instructions correctly, you should have the JDK installed.</p><h5>Installing Tomcat</h5><p>Strictly speaking, Tomcat is much more than a web server &#8212; it&#8217;s what&#8217;s referred to as a servlet container, which works as a gateway between the world of Web and the world of Java. But it has a decent web server in it too, at least for development purposes. Installing Tomcat is very easy, but we do need to configure an environment variable afterwards.</p><p><strong><em>1. Download Tomcat</em></strong></p><p>This step is common for all the platforms, as Tomcat is a Java program! Go to <a
class="sublink" href="http://tomcat.apache.org">http://tomcat.apache.org</a>. If you&#8217;ve got JDK 5, choose the latest stable version of Tomcat (at the time of writing, this is 5.5.12), otherwise download Tomcat 5.0.28 &#8212; for our purposes it will work exactly the same.</p><p><strong><em>2. Unpack Tomcat</em></strong></p><p>Unpack the downloaded package into a directory of your choice. This might be <code>c:\apache-tomcat-5.5.12</code> on a Windows computer, something like <code>/home/alex/apache-tomcat-5.5.12</code> under Linux, or <code>/Users/alex/jakarta-tomcat-5.5.12</code> under Mac OS X. The installer wizard for Windows makes this process even easier.</p><p><strong><em>3. Set the JAVA_HOME Environment Variable</em></strong></p><p>This environment variable should point to the directory into which you&#8217;ve placed your JDK. Since we&#8217;re dealing with the computer&#8217;s operating system at this point, the following instructions are platform-specific.</p><p><strong>Windows XP</strong></p><p>Your JDK may have been installed automatically, but it&#8217;s not difficult to find out where it was installed. It most probably lives in the <code>C:\Program Files\Java</code> directory, so your environment variable should point to something like this:</p><pre><code>C:\Program Files\Java\jdk1.5.0_06</code></pre><p>To set the variable, right-click on My Computer and select Properties. In the dialog that opens, choose the Advanced tab, then click the Environment Variables button at the bottom.</p><p>The System Variables are listed in the lower portion of the window (see Fig. 1). If you don&#8217;t see <code>JAVA_HOME</code> there, create it by pressing the New button, otherwise edit it as needed by pressing the Edit button.</p><p><img
src="http://sitepointstatic.com/graphics/afig1.gif"  height="528" width="447" alt="1508_figure1" /><br
/> <em>Fig.1. Setting JAVA_HOME in Windows XP</em></p><p><strong>Linux</strong></p><p>If you installed the JDK as described above, you&#8217;ll know where it is. Otherwise, you might need to find it using the following command:</p><pre><code>which java</code></pre><p>This will display something similar to this:</p><pre><code>/usr/java/jdk1.5.0_06/bin/java</code></pre><p>Your <code>JAVA_HOME</code> should therefore point to <code>/usr/java/jdk1.5.0_06</code>.</p><p>There are several places where you can set an environment variable in Linux. My preferred option is to edit the .bashrc file, adding the following line:</p><pre><code>export JAVA_HOME=/usr/java/jdk1.5.0_06</code></pre><p><strong>Mac OS X</strong></p><p>The Mac OSX process is mostly the same as the one we used for Linux, the difference being that finding the location at which your JDK is installed is more difficult on Mac. To find out, type:</p><pre><code>which java</code></pre><p>This will give you something like:</p><pre><code>/usr/bin/java</code></pre><p>In this case, your <code>JAVA_HOME</code> should point to <code>/usr</code>.</p><p>To set the variable, edit your <code>.bash_profile</code> file and add to it the following line:</p><pre><code>export JAVA_HOME=/usr</code></pre><p><strong><em>4. Test it!</em></strong></p><p>To test whether or not your installation of Tomcat really works, go to the bin subdirectory of the directory where you installed Tomcat. In other words, if you&#8217;ve installed Tomcat into <strong>c:\apache-tomcat-5.5.12</strong>, go to <strong>c:\apache-tomcat-5.5.12\bin</strong>.</p><p>There, you&#8217;ll find the following scripts: <code>startup.sh</code> and <code>shutdown.sh</code> (for Linux and MacOS X usage) and <code>startup.bat</code> and <code>shutdown.bat</code> (for Windows).</p><p>Note that on a Linux or Mac OS X machine you may need to change the permissions of all the <code>.sh</code> scripts in this directory in order to be able to execute them, but that&#8217;s easy:</p><pre><code>chmod +x *.sh</code></pre><p>To start Tomcat, launch <code>startup.sh</code> or <code>startup.bat</code> (depending on your platform), wait a few seconds, then navigate your web browser to <code>http://localhost:8080</code>. If everything&#8217;s functioning correctly, you&#8217;ll see a page similar to Fig.2.</p><p><img
src="http://sitepointstatic.com/graphics/afig2.gif"  height="429" width="500" alt="1508_figure2" /><br
/> <em>Fig.2. If you see this page, your Tomcat was installed successfully.</em></p><p>In the world of networking, localhost refers to your own computer, when it&#8217;s referred to as a server. When you navigate to <code>localhost:8080</code>, you are actually asking your computer if anybody is listening on port 8080 (ports on your computer are like telephone extensions inside your office). And this is where Tomcat is listening, by default, so it shows its face.</p><p>To stop Tomcat when you don&#8217;t need it any more, use the <code>shutdown.sh</code> or <code>shutdown.bat</code> scripts. If you used the Windows Tomcat installer, you&#8217;ll also have a handy little monitoring tool that sits in your task bar. You can use this to start and stop the server.</p><h5>Installing Eclipse</h5><p>An efficient and convenient IDE greatly enhances a developer&#8217;s productivity, and when it comes to Tapestry development, the natural choice of IDE is Eclipse, primarily because the Spindle plug-in we&#8217;re going to use only exists for Eclipse, but also, of course, because the Eclipse is a superb IDE!<br
/> Installing Eclipse is very simple. Go to <a
class="sublink" href="http://eclipse.org/downloads">the Eclipse downloads page</a> and download the version that suits you, for example <code>eclipse-SDK-3.1.1-win32.zip</code> for Windows, <code>eclipse-SDK-3.1.1-macosx-carbon.tar.gz</code> for Mac OS X, or <code>eclipse-SDK-3.1.1-linux-gtk.tar.gz</code> for Linux. Unpack the download to the directory of your choice, e.g. <code>c:\eclipse</code> or <code>/Users/alex/eclipse</code>.</p><p>You can start the IDE by launching Eclipse.app in Mac OS X, eclipse.exe in Windows, or by typing eclipse in Linux. When you start Eclipse for the first time, you&#8217;ll be asked to choose your workspace &#8212; the directory in which all your Eclipse projects will be stored. You can choose either the default directory, or a different one.</p><p>That&#8217;s it! Now we&#8217;ve got the JDK, Tomcat and Eclipse, all of which are prerequisites for general Java Web development. Now, we&#8217;re going to enrich our work environment with a few Tapestry-specific components.</p><h5>Installing Spindle</h5><p>This Eclipse plug-in greatly simplifies Tapestry development, and it&#8217;s quite easy to install.</p><p>Open your Eclipse IDE. Choose Help &gt; Software Updates &gt; Find and Install&#8230;</p><p><img
src="http://sitepointstatic.com/graphics/afig3.gif"  height="417" width="500" alt="1508_figure3" /><br
/> <em>Figure 3. Selecting to install Spindle</em></p><p>In the dialog that appears, select Search for new features to install and press Next. In the next window, press the New Remote Site&#8230; button. Enter Spindle for the Name and <code>http://spindle.sf.net/updates</code> for the URL, then press OK and Finish. You will be prompted to select a mirror; select the closest location to you and press OK.</p><p>Eclipse will search for the plug-in and show you the result, as shown in Figure 3 above. Select Spindle and press Next.</p><p>In the next dialog, accept the terms in the license agreement and press Next. Finally, press Finish. Eclipse will download everything it needs to install Spindle (this could take half an hour or more, depending on your connection). It will then ask you to verify that you really want to install &#8216;an unsigned feature&#8217; (see Fig.4).</p><p>Choose Install All and, when the installation completes, agree to restart your workbench.</p><p>Great! Now your IDE is ready for Tapestry development. The very last step we need to take is to download all the libraries that Tomcat needs to run a Tapestry Web application, and place them in an appropriate location.</p><p><img
src="http://sitepointstatic.com/graphics/afig4.gif"  height="417" width="500" alt="1508_figure4" /><br
/> <em>Figure 4. Installing Spindle: Verification Stage.</em></p><h5>Downloading Tapestry and Other Libraries</h5><p>Tapestry 3 itself comes in two .jar files: <code>tapestry-3.0.3.jar</code> and <code>tapestry-contrib-3.0.3.jar</code>. But it also relies on other libraries, some of which are included in its distribution, while others need to be downloaded separately. The easiest way to get all the necessary libraries is to <a
class="sublink" href="http://www.sitepoint.com/examples/tapestry/tapestrylibs.zip">download the <code>tapestry_libs.zip</code> archive that I have created for you</a>. <br
/> Unpack all the contents of this archive into the <code>shared/lib</code> directory under your Tomcat installation. It can be, say, <code>c:\apache-tomcat-5.5.12\shared\lib</code> on a Windows machine or <code>/Users/alex/jakarta-tomcat-5.5.12/shared/lib</code> on Mac OS X.</p><p>Whew, we&#8217;ve done it! We&#8217;re now ready to unleash the magic of Tapestry.</p><p><div
class="article-cms-pagebreak"></div></p><h5>Our First Tapestry Web Application</h5><p>First, let&#8217;s visualize what we&#8217;re going to create. Our first Tapestry application will be quite simple &#8212; though still useful &#8212; and will have two pages. The first page will display a login form: just a standard form that ask for a username and a password. The second page will greet visitors using their login names &#8212; that is, if they successfully pass authentication. If the login/password combination is wrong, the login page will be redisplayed again.</p><p>Figure 5 shows what both pages should look like when completed. For simplicity, I haven&#8217;t used any styles here, but you can apply your creativity to create a design of your own.</p><p><img
src="http://sitepointstatic.com/graphics/afig5a.gif"  height="253" width="392" alt="1508_figure5a" /></p><p><img
src="http://sitepointstatic.com/graphics/afig5b.gif"  height="253" width="405" alt="1508_figure5b" /><br
/> <em>Figure 5. This is how the completed pages of our application will look.</em></p><p>In fact, it makes sense to begin the development of your Tapestry application by first creating the HTML &#8216;mockups&#8217; &#8212; prototypes of your future pages that show exactly how they&#8217;ll look in a working application.</p><p>You can exercise all your creative skills to the full when creating mockups or, if you&#8217;re the manager or client of a good design team, tell your designers not to limit their imagination. You&#8217;re not going to spoil their efforts by inserting ugly tags or mixing carefully crafted design with an unintelligible mix of HTML and code. As you&#8217;ll soon see, Tapestry treats page design with great care.</p><p>Here&#8217;s the HTML code for my page mockups:</p><p>Page 1:<br
/> <code>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &nbsp;<br
/> &nbsp; &nbsp;&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; &nbsp;<br
/> &lt;html&gt; &nbsp;<br
/> &lt;head&gt; &nbsp;<br
/> &nbsp;&lt;title&gt;Welcome to Tapestry!&lt;/title&gt; &nbsp;<br
/> &lt;/head&gt; &nbsp;<br
/> &lt;body&gt; &nbsp;<br
/> &nbsp;&lt;h2&gt;Welcome to Tapestry!&lt;/h2&gt; &nbsp;<br
/> &nbsp;&lt;form action=&quot;&quot;&gt; &nbsp;<br
/> &nbsp; &nbsp;&lt;p&gt;User Name: &lt;input type=&quot;text&quot;/&gt;&lt;br/&gt; &nbsp;<br
/> &nbsp; &nbsp; &nbsp; &nbsp;Password: &lt;input type=&quot;password&quot;/&gt;&lt;br/&gt; &nbsp;<br
/> &nbsp; &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Let me in!&quot;/&gt;&lt;/p&gt; &nbsp;<br
/> &nbsp;&lt;/form&gt; &nbsp;<br
/> &lt;/body&gt; &nbsp;<br
/> &lt;/html&gt;</code></pre><div
id="adz" class="vertical"><script type="text/javascript">GA_googleFillSlot("Articles_6_300x250");</script></div><p>Page 2:<br
/> <code>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &nbsp;<br
/> &nbsp; &nbsp;&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; &nbsp;<br
/> &lt;head&gt; &nbsp;<br
/> &nbsp;&lt;title&gt;You've got it!&lt;/title&gt; &nbsp;<br
/> &lt;/head&gt; &nbsp;<br
/> &lt;body&gt; &nbsp;<br
/> &nbsp;&lt;h2&gt;Precious User!&lt;/h2&gt; &nbsp;<br
/> &nbsp;&lt;h3&gt;Welcome to the wonderful World of Tapestry!&lt;/h3&gt; &nbsp;<br
/> &lt;/body&gt; &nbsp;<br
/> &lt;/html&gt;</code></pre><p>Now that we have our mockups ready, let's create our first Tapestry project.</p><h5>Creating a Tapestry Project</h5><p>Fire up Eclipse (but not Tomcat yet). To create a new Tapestry project, choose File &gt; New &gt; Other... and, under the Tapestry node, choose Tapestry Web project, as shown in Fig. 6. Then press Next.</p><p><img
src="http://sitepointstatic.com/graphics/afig6.gif"  height="476" width="500" alt="1508_figure6" /><br
/> <em>Figure 6. Choosing a Tapestry Web Project</em></p><p>Name the project, say, 'Login', and check the box Include the Tapestry redirect filter in web.xml (see Fig.7).</p><p><img
src="http://sitepointstatic.com/graphics/afig7.gif"  height="581" width="500" alt="1508_figure7" /><br
/> <em>Fig. 7. Naming the project</em></p><p>Press Next, and in the next window click Finish. You'll see the structure of your new application, as shown in Fig.8.</p><h5>General Structure of a Java Web Application</h5><p><img
src="http://sitepointstatic.com/graphics/afig8.gif"  height="250" width="252" alt="1508_figure8" /><br
/> <em>Fig. 8. The Structure of a New Tapestry Project</em></p><p>If you don't have any experience with Java web development, you might benefit from a brief overview of the standard structure of Java web application. This structure is common to all frameworks based on servlets, including JSP, Struts, Tapestry and virtually everything that exists in the Java web world.</p><p>A simplified version of this structure is shown in Fig. 9. The whole application is contained within one directory, which is given the name of the application. We've labeled this top-level directory <code>AppName</code> in the diagram.</p><p><img
src="http://sitepointstatic.com/graphics/afig9.gif"  height="581" width="247" alt="1508_figure9" /><br
/> <em>Fig. 9. The Generic Structure of a Java Web Application </em></p><p>Directly under <code>AppName</code> live those resources that are directly accessible by the outside world, via the Web. This includes HTML pages, JSP pages, CSS files, images and any other resources that might be needed for the external part of the application. I use the term &quot;external&quot;  because if you have, say, a page named <code>MyPage.html</code> that's stored directly under the <code>AppName</code> directory on your <code>www.myserver.com</code> server, web users can see that page by pointing their browsers to <code>http://www.myserver.com/AppName/MyPage.html</code>.</p><p>Images and style sheets are often put into a subdirectory -- in this case, one named assets. Grouping content like this helps to keep things neat; this subdirectory will be also accessible to everyone.</p><p>You'll notice a (particularly important) subdirectory named <code>WEB-INF</code>. It should be named exactly like this -- not <code>web-inf</code> or <code>Web-Inf</code> -- otherwise your Web application won't work. This is the inner sanctum of a Java Web application: nothing that goes inside this directory will be exposed directly to the outer world (i.e. to the Web).</p><p>There's an important file inside <code>WEB-INF</code> named <code>web.xml</code>. It has the same name in all Java web applications, and is the deployment descriptor. The purpose of this file is to tell Tomcat some general, important information about the application.</p><p>There are also two subdirectories under <code>WEB-INF</code>, named classes and lib. All the compiled Java classes that make up the application go into the classes subdirectory, and all the libraries that are used by the application go into the lib directory -- simple! Many other files serving different purposes can be kept under <code>WEB-INF</code> and in its subdirectories, but this is the standard structure.</p><p>Now, let's see how this arrangement maps to the structure of our first Tapestry application, created for us by Eclipse (together with Spindle).</p><h5>The Structure of our Web Application</h5><p>You can see that the top level directory of our application is named Login -- the name that we gave to the application.</p><p>The <code>src</code> subdirectory was created for our convenience. This is where the source code of all our Java classes will be stored. Below it, you'll see two library references: Tapestry Framework and JRE System Library. Eclipse displays them here to indicate that we have them at our disposal for this project. There's also a context subdirectory. All of our application's files -- everything that was listed directly under <code>AppName</code> in Figure 9 -- are stored in the context subdirectory. We don't have any static HTML pages here right now, but we might do later. We would also keep any images or style sheets here if we had them. Right now, we see just the sacred <code>WEB-INF</code> file.</p><p>In <code>WEB-INF</code> you'll see the deployment descriptor, <code>web.xml</code>. We won't explore it just yet, though.</p><p>We haven't created any Java classes, nor have we used any libraries, so no classes or <code>lib</code> subdirectories are displayed just yet.</p><p>There is also a <code>Login.application</code> file that contains application-wide configuration. Right now, we'll just leave it as it is, but later, when we make some changes to it, we'll discuss the contents of this file.</p><p>Now we come to the most interesting part of the process: creating Tapestry pages.</p><h5>Creating the Home Page</h5><p>You'll notice that Spindle has created two more files for us: <code>Home.html</code> and <code>Home.page</code>. A page named Home is the default page for a Tapestry application, very much like <code>index.html</code> is the default page for a Website's directory. If no page is specified in a request from the client, Tapestry will show the Home page.</p><p>We'll put our login form on this page. Let's see what sort of HTML Spindle has created for us. Double-click the <code>Home.html</code> file to open it in the editor:</p><pre><code>&lt;html&gt; &nbsp;<br />
&lt;head&gt; &nbsp;<br />
 &nbsp;<br />
&lt;/head&gt; &nbsp;<br />
 &nbsp;<br />
&lt;body&gt; &nbsp;<br />
 &nbsp; &nbsp; <br />
&lt;/body&gt; &nbsp;<br />
&lt;/html&gt;</code></pre><p>This is just an empty stub for a HTML page. Let's replace it with our mockup for the first page. We'll add a doctype, a title and a simple form to the body.</p><pre><code>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &nbsp;<br />
 &nbsp; &nbsp;&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; &nbsp;<br />
&lt;html&gt; &nbsp;<br />
&lt;head&gt; &nbsp;<br />
 &nbsp;&lt;title&gt;Welcome to Tapestry!&lt;/title&gt; &nbsp;<br />
&lt;/head&gt; &nbsp;<br />
&lt;body&gt; &nbsp;<br />
 &nbsp;&lt;h2&gt;Welcome to Tapestry!&lt;/h2&gt; &nbsp;<br />
 &nbsp;&lt;form action=&quot;&quot;&gt; &nbsp;<br />
 &nbsp; &nbsp;&lt;p&gt;User Name: &lt;input type=&quot;text&quot;/&gt;&lt;br/&gt; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;Password: &lt;input type=&quot;password&quot;/&gt;&lt;br/&gt; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Let me in!&quot;/&gt;&lt;/p&gt; &nbsp;<br />
 &nbsp;&lt;/form&gt; &nbsp;<br />
&lt;/body&gt; &nbsp;<br />
&lt;/html&gt;</code></pre><p>Let's say we've just received this carefully crafted HTML page from our design team. It's time to apply our knowledge of Tapestry and convert the mockup into the real thing -- an HTML template for a Tapestry page! Here's the end result of such a conversion:</p><pre><code>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &nbsp;<br />
 &nbsp; &nbsp;&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; &nbsp;<br />
&lt;html&gt; &nbsp;<br />
&lt;head&gt; &nbsp;<br />
 &nbsp;&lt;title&gt;Welcome to Tapestry!&lt;/title&gt; &nbsp;<br />
&lt;/head&gt; &nbsp;<br />
&lt;body&gt; &nbsp;<br />
 &nbsp;&lt;h2&gt;Welcome to Tapestry!&lt;/h2&gt; &nbsp;<br />
 &nbsp;&lt;form action=&quot;&quot; jwcid=&quot;loginForm&quot;&gt; &nbsp;<br />
 &nbsp; &nbsp;&lt;p&gt;User Name: &lt;input type=&quot;text&quot; jwcid=&quot;uname&quot; /&gt;&lt;br/&gt; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;Password: &lt;input type=&quot;password&quot; jwcid=&quot;password&quot; /&gt;&lt;br/&gt; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Let me in!&quot;/&gt;&lt;/p&gt; &nbsp;<br />
 &nbsp;&lt;/form&gt; &nbsp;<br />
&lt;/body&gt; &nbsp;<br />
&lt;/html&gt;</code></pre><p>Of course, your eagle eye has spotted the changes we've made, but will your web browser notice them? Open the original mockup in a browser of your choice, then open the converted version and check if there are any differences. There aren't. Because those strange <code>jwcid</code> attributes mean nothing to a web browser from a rendering perspective, it just ignores them.</p><p>You might be interested to know that jwcid means &quot;Java Web Component ID&quot;, and these jwcid attributes are our way of telling Tapestry, &quot;We want to apply some magic here. Please turn these standard HTML elements into dynamic Tapestry components.&quot; As a result, the standard HTML element <code>&lt;form&gt;</code> will become a Tapestry component, as will the two standard <code>&lt;input&gt;</code> elements.</p><p>By the way, the names that you assign to jwcid attributes are, more or less, arbitrary. If you like, you can give them name them like <code>jwcid=&quot;bilbo&quot;</code> or <code>jwcid=&quot;FrodoBaggins&quot;</code>. But don't try something like <code>jwcid=&quot;%@^&amp;*&quot;</code>, the language of Mordor won't work here. I recommend you use something indicative of the type of data the file represents.</p><p><img
src="http://sitepointstatic.com/graphics/afig10.gif"  height="199" width="500" alt="1508_figure10" /><br
/> <em>Fig. 10. Spindle Has Found an Error</em></p><p>All right, so if the component IDs are arbitrary, how will Tapestry know exactly which of its standard or custom components you want to use in place of the static HTML? You might notice that Spindle isn't quite happy with our new attributes -- it underlines the first of them with a red line and draws a red, crossed circle in the left margin of the editor window (see Figure 10). If you hover your cursor over the underlined word or the red circle, you'll see this error message:</p><pre><code>Tag &lt;form&gt; on line 7 references unknown component id 'loginForm'.</code></pre><p>Logically, there should be a place where we can specify for Tapestry the details of our design, and there is! This place is called the page specification and for our Home page it is represented by the <code>Home.page</code> file, which was already created for us by Spindle.</p><p>Now is the time to discuss the following revelation: Tapestry pages actually consist of three parts:</p><ol><li>an HTML template (Home.html for our first page, for example)</li><p></p><li>a page specification (such as <code>Home.page</code>)</li><p></p><li>a page class (we'll call ours <code>Home.class</code> -- see later)</li></ol><p>The HTML template defines what our users will see. The page class contains the page's functionality. And the page specification links the components in the template with the corresponding functionality in the page class. It specifies all the necessary details for these components, and may also contain some other page-specific information.</p><p>We'll return to the three-part nature of Tapestry pages later -- and more than once, too -- because it's very important. But right now, let's create the page specification for our Home page. Double-click the <code>Home.page</code> file in your Package Explorer in Eclipse. This is what you should see:</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &nbsp;<br />
&lt;!DOCTYPE page-specification PUBLIC &nbsp;<br />
 &nbsp;&quot;-//Apache Software Foundation//Tapestry Specification 3.0//EN&quot; &nbsp;<br />
 &nbsp;&quot;http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd&quot;&gt; &nbsp;<br />
&lt;!-- generated by Spindle, http://spindle.sourceforge.net --&gt; &nbsp;<br />
 &nbsp;<br />
&lt;page-specification class=&quot;org.apache.tapestry.html.BasePage&quot;&gt; &nbsp;<br />
 &nbsp;&lt;description&gt;add a description&lt;/description&gt; &nbsp;<br />
&lt;/page-specification&gt;</code></pre><p>If you don't have much experience with XML documents and doctypes, don't pay too much attention to the first five lines. The first line just states that this is an XML document. The cryptic-looking <code>&lt;!DOCTYPE&gt;</code> tag tells an XML parser how to understand the document that follows.</p><p>We're interested in the information inside the page-specification element, beginning with the attribute <code>class=&quot;org.apache.tapestry.html.BasePage&quot;</code>.</p><p>Remember how I told you that every Tapestry page consists of three parts, one of which is a Java class that contains the page's functionality? Even if you don't create a class, a default class exists anyway -- the <code>BasePage</code> class referred to by this attribute. Of course, it doesn't contain any custom functionality, but it still has many default methods that give us access to the infrastructure of Tapestry.</p><p>When we decide to create our custom page class, it will always extend this default <code>BasePage</code> class.</p><p>Next comes the description element. You can either leave this as it is, or if you are like me and prefer to keep your stuff well organized, go ahead and add a description of the page -- something like 'Login page'.</p><p>Inside of the page-specification element, we have to explain to Tapestry what we really meant when we wrote <code>jwcid=&quot;uname&quot;</code> etc.</p><p>Here, I'll show you what we're going to write for our page specification, and explain what it means before we type it into Eclipse. In a moment you'll see how we can use some handy features of Spindle and Eclipse to write all these specifications in no time at all.</p><p>First, we're going to describe our <code>loginForm</code> component. Its specification will look like this:</p><pre><code>&lt;component id=&quot;loginForm&quot; type=&quot;Form&quot;&gt; &nbsp;<br />
 &nbsp;&lt;binding name=&quot;listener&quot; expression=&quot;listeners.onFormSubmit&quot; /&gt; &nbsp;<br />
&lt;/component&gt;</code></pre><p>You may already have deduced that this piece of XML tells Tapestry: &quot;The <code>jwcid=&quot;loginForm&quot;</code> that I inserted into the HTML template will be a standard Tapestry Form component.&quot;</p><p>The binding element actually creates a link between the HTML template and the page class. When the name of the binding is listener (there are a few other names available), we're describing the name of the method on the page class that will be invoked when the form is submitted.</p><p>A Tapestry Form's listener is specified like this:</p><pre><code>&lt;binding name=&quot;listener&quot; expression=&quot;listeners.onFormSubmit&quot;/&gt;</code></pre><p>The only part of this element that you can change is the actual listener method name, in this case <code>onFormSubmit</code>. You have control over the name of this method, so you could call it <code>onSubmit</code>, or something that was more meaningful to you, if you liked. Let's stick with <code>onFormSubmit</code> for now; Tapestry will therefore be looking in the page class for a method with the following signature:</p><pre><code>public void onFormSubmit(IRequestCycle cycle) {}</code></pre><p>It will be your responsibility to provide the implementation of such a method. And if you decide to name the listener <code>myGloriousMethod</code>, make sure that you provide a method to Tapestry with the signature:</p><pre><code>public void myGloriousMethod(IRequestCycle cycle) {}.</code></pre><p>Where can you provide such a custom listener method? In a custom page class (we'll come to that later). Don't bother for now about that <code>IRequestCycle</code> thing, either -- we'll come to that in a moment. Right now, let's tell Tapestry how to handle the other two components that we're yet to specify.</p><p>The first is <code>uname</code>, for storing the user name. This is how it should be specified:</p><pre><code>&lt;component id=&quot;uname&quot; type=&quot;TextField&quot;&gt; &nbsp;<br />
 &nbsp;&lt;binding name=&quot;value&quot; expression=&quot;uname&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;/component&gt;</code></pre><p>Here, we're telling Tapestry that what we marked in the HTML template as <code>jwcid=&quot;uname&quot;</code> is actually a standard Tapestry TextField component, and the value obtained from it should be stored in a property uname. Again, this will be a property of our custom page class, but we'll cover that later. You can actually name this property whatever you like, though it is convenient (and good practice) to give the property the same name as the component's ID.</p><p>The last component on our Home page is password. This is how it should be specified:</p><pre><code>&lt;component id=&quot;password&quot; type=&quot;TextField&quot;&gt; &nbsp;<br />
 &nbsp;&lt;binding name=&quot;value&quot; expression=&quot;password&quot;/&gt; &nbsp;<br />
 &nbsp;&lt;static-binding name=&quot;hidden&quot; value=&quot;true&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;/component&gt;</code></pre><p>This tells Tapestry that the component we marked as password is also a TextField, that its value should be stored in a property named password, and that its hidden parameter should be set to true.</p><p>Because Tapestry doesn't have a special Password component, the effect of replacing keystrokes with asterisks is achieved by setting the hidden property of a normal TextField component to true, so that the characters are not echoed to the screen.</p><p>The difference between <code>&lt;binding&gt;</code> and <code>&lt;static-binding&gt;</code> is that <code>&lt;binding&gt;</code> is evaluated by Tapestry every time the form is rendered or submitted, which is good for unpredictable or variable values (who knows what password a user will enter?). On the other hand, <code>&lt;static-binding&gt;</code> is good for constant values: we want the hidden parameter always to be true; this will be remembered by Tapestry, which won't evaluate hidden every time, saving precious resources.</p><p><div
class="article-cms-pagebreak"></div></p><p>Now let's edit our <code>Home.page</code> file and add to it the component specifications we've just discussed. But writing XML by hand is boring and error-prone, so we're going to rely on Spindle's help here.</p><p>Place your cursor in the line below the <code>&lt;description&gt;</code> tag and press Ctrl + Space. In the Code Assist window that opens, select component (see Fig. 11).</p><p><img
src="http://sitepointstatic.com/graphics/afig11.gif"  height="285" width="500" alt="1508_figure11" /><br
/> <em>Fig. 11. Writing component specification with the help of Code Assist</em></p><p>Press Enter and you'll get a stub of a component specification:</p><pre><code>&lt;component id=&quot;value&quot;&gt;&lt;/component&gt;</code></pre><p>Notice that value is already selected for you, so you can enter something to replace it immediately. Enter <code>loginForm</code>. Press Tab, and the cursor will jump to the next place of entry. This feature may not work if you're constantly switching between your browser and your Eclipse window, so you might want to print this tutorial or arrange your workspace (or, if possible, memorize these few steps) so you can perform this procedure in one go. Press Ctrl + Space again, select type from the list and press Enter. This is how your new specification should look:</p><pre><code>&lt;component id=&quot;loginForm&quot; type=&quot;value&quot;&gt;&lt;/component&gt;</code></pre><p>The word value is selected again. Once again, press Ctrl + Space and type the letter 'f'. You'll see the names of the components that start with F. Choose Form and press Enter. This is what you'll see now:</p><pre><code>&lt;component id=&quot;loginForm&quot; type=&quot;Form&quot;&gt;&lt;/component&gt;</code></pre><p>Press Tab again to jump to the next entry point, right between the <code>&lt;component ...&gt;</code> and <code>&lt;/component&gt;</code> tags, and -- you guessed it -- press Ctrl + Space. Choose binding (empty) from the list and press Enter. At this stage, your specification will look like this (I pressed Enter another couple of times to format the code nicely; you might want to do the same):</p><pre><code>&lt;component id=&quot;loginForm&quot; type=&quot;Form&quot;&gt; &nbsp; <br />
 &nbsp;&lt;binding name=&quot;value&quot;/&gt; &nbsp; <br />
&lt;/component&gt;</code></pre><p>With the word value selected, press Ctrl + Space. Choose listener, press Enter, then Tab and  Ctrl + Space again. The only choice in the list will be expression, so choose it by pressing Enter. Finally, enter <code>listeners.onFormSubmit</code> instead of value. That's it! We've completed the specification for our first component.</p><p>After you become accustomed to using Code Assist, you'll see how easy it is to write component specifications.</p><p>Now go on and have some practice. Create specifications for the other two components, and check back here when you're done. The final result of your numerous Ctrl + Space keystrokes should look like this:</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &nbsp; <br />
&lt;!DOCTYPE page-specification PUBLIC &nbsp; <br />
 &nbsp;&quot;-//Apache Software Foundation//Tapestry Specification 3.0//EN&quot; &nbsp; <br />
 &nbsp;&quot;http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd&quot;&gt; &nbsp; <br />
&lt;!-- generated by Spindle, http://spindle.sourceforge.net --&gt; &nbsp; <br />
 &nbsp; <br />
&lt;page-specification class=&quot;org.apache.tapestry.html.BasePage&quot;&gt; &nbsp; <br />
 &nbsp; <br />
 &nbsp;&lt;description&gt;Login page&lt;/description&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; <br />
 &nbsp;&lt;component id=&quot;loginForm&quot; type=&quot;Form&quot;&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;binding name=&quot;listener&quot; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;expression=&quot;listeners.onFormSubmit&quot;/&gt; &nbsp; &nbsp; &nbsp; <br />
 &nbsp;&lt;/component&gt; &nbsp; <br />
 &nbsp;&lt;component id=&quot;uname&quot; type=&quot;TextField&quot;&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;binding name=&quot;value&quot; expression=&quot;uname&quot;/&gt; &nbsp; &nbsp; &nbsp; <br />
 &nbsp;&lt;/component&gt; &nbsp; <br />
 &nbsp;&lt;component id=&quot;password&quot; type=&quot;TextField&quot;&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;binding name=&quot;value&quot; expression=&quot;password&quot;/&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;static-binding name=&quot;hidden&quot; value=&quot;true&quot;/&gt; &nbsp; &nbsp; &nbsp; <br />
 &nbsp;&lt;/component&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; <br />
&lt;/page-specification&gt;</code></pre><div
id="adz" class="vertical"><script type="text/javascript">GA_googleFillSlot("Articles_6_300x250");</script></div><p>We've completed the page specification for our Home page, and the Spindle syntax checker should be completely happy with what we have written (i.e. there should be no wavy red lines either in <code>Home.html</code>, nor in <code>Home.page</code>).  However, the page won't work yet. Remember, we promised Tapestry that there would be an <code>onFormSubmit</code> listener and two properties named uname and password in the page class.</p><p>Right now, this page uses the default <code>BasePage</code> class, and it doesn't have any custom methods or properties. To implement our custom logic, we should create our own Java class that will inherit from <code>BasePage</code>.</p><h5>Creating the Page Class</h5><p>Right-click (or Ctrl-click on a Mac) in your Package Explorer and choose New &gt; Other..., then, in the Select a wizard dialog, choose Class (see Fig. 12). Press Next.</p><p><img
src="http://sitepointstatic.com/graphics/afig12.gif"  height="476" width="500" alt="1508_figure12" /><br
/> <em>Figure 12. Selecting a Class wizard</em></p><p>In the Java Class dialog enter a package name, for example <code>com.sitepoint.tapestry.login</code>. Enter <code>Home</code> for the name of the new class, and <code>org.apache.tapestry.html.BasePage</code> for the Superclass. Make sure the public static void main(String[] args) checkbox is deselected -- we're not going to run this class as a standalone program. You might find it useful to add automatically generated comments, so select the Generate Comments checkbox. The final result should look like Fig. 13.</p><p><img
src="http://sitepointstatic.com/graphics/afig13.gif"  height="634" width="500" alt="1508_figure13" /><br
/> <em>Figure 13. A new class is ready to be created</em></p><p>Press Finish, and a brand new page class will be generated for you in a few seconds. It will be named <code>Home.java</code> and its code will look like this:</p><pre><code>/** &nbsp; <br />
 * &nbsp; &nbsp;<br />
 */ &nbsp; <br />
package com.sitepoint.tapestry.login; &nbsp; <br />
 &nbsp; <br />
import org.apache.tapestry.html.BasePage; &nbsp; <br />
 &nbsp; <br />
/** &nbsp; <br />
 * @author alex &nbsp; <br />
 * &nbsp; <br />
 */ &nbsp; <br />
public class Home extends BasePage { &nbsp; <br />
 &nbsp; <br />
}</code></pre><p>This is where we define our listener method. Specify it like this:</p><pre><code>public class Home extends BasePage { &nbsp; <br />
 &nbsp; <br />
 &nbsp;public void onFormSubmit(IRequestCycle cycle) { &nbsp; <br />
 &nbsp; &nbsp;// Some code will go here &nbsp; <br />
 &nbsp;} &nbsp; <br />
}</code></pre><p>At this stage, we'll create only the skeleton of the method -- the rest of the code will be added later. The mysterious <code>IRequestCycle</code> parameter can be thought of as Tapestry's representative in our code. Whenever we need something from the framework, we'll ask this cycle to get it for us. We'll see an example of this soon.</p><p>However, at the moment Eclipse tells us that it doesn't know what an <code>IRequestCycle</code> is. To make it happy, we'll need to add the following import statement:</p><pre><code>import org.apache.tapestry.IRequestCycle;</code></pre><p>Now that we have a custom page class, we need to specify it in our page specification. Change the opening <code>&lt;page-specification&gt;</code> tag in <code>Home.page</code> to look like this:</p><pre><code>&lt;page-specification class=&quot;com.sitepoint.tapestry.login.Home&quot;&gt;</code></pre><h5>Specifying Properties the Tapestry Way</h5><p>Now is the time to deal with the two properties uname and password. There are two ways to specify a property in Tapestry: the standard Java way (a private class member, public getter and setter, and perhaps some other maintenance code), and the Tapestry way. The latter, although it looks slightly unusual, is used much more often, so we'll use the Tapestry approach here.</p><p>We don't want to write all that property-related code by hand, so we'll just ask Tapestry to generate it for us automatically at run time. All we need to do is to describe how the properties should be named, and what type they should be (any Java class available to Tapestry can suffice as the type).</p><p>You've probably already guessed that we'll describe the properties we want in our page specification. In <code>Home.page</code> class, just below the <code>&lt;description&gt;</code> tag, add the following two lines (of course, you don't have to write them all out by hand -- use your Code Assist Ctrl + Space skills):</p><pre><code>&lt;property-specification name=&quot;uname&quot; type=&quot;java.lang.String&quot;/&gt; &nbsp; <br />
&lt;property-specification name=&quot;password&quot; type=&quot;java.lang.String&quot;/&gt;</code></pre><p>That's it! Now you can just assume that at run time these properties will be ready for you, and they'll be managed by Tapestry properly without any efforts from your side and without any code written by you.</p><p>Previously, before we even specified these properties, we had already connected them to two of our components: a TextField component with the ID <code>uname</code> is bound to the property uname, and a TextField component with the ID <code>password</code> is bound to the password property. Let me describe all the activities that Tapestry will perform based on our page specification:</p><ol><li>When the Home page is requested, Tapestry will create the page class for it (an instance of <code>com.sitepoint.tapestry.login.Home</code>, created by us). It will then notice that we asked to add two properties to this page, so Tapestry will create an 'enhanced' version of our class (i.e. another class that inherits from Home), and will add to it the two requested properties along with all the code that might be needed to handle them.</li><p><li>Tapestry then asks the enhanced page class instance to render itself to the user. To do that, the page class instance will use our Home.html template. When rendering the uname and password components, the class instance will check whether these components have any default values. We didn't specify any, so the components will just be shown as blank text fields.</li></p><p><li>When the login form is submitted, Tapestry (using the same kind of page class instance, either created anew or taken from the pool) will take the values entered by the user into the two text fields, and put them into their corresponding properties, so that we can use them in our code.</li></ol><p>It took three paragraphs for me to describe what Tapestry will do automatically for us as a result of just a few lines in the page specification. You don't really need to know all those procedures when you're taking your first steps with Tapestry. All you need to know is that you can specify the properties you need, connect them to the components you use on your page and, as a result, whatever is submitted by a user will be available in your code via these properties.</p><p>The only nuance is that to use or edit a value of this kind of property in your code, you should create a getter or a setter (or both, if necessary) in your page class. Admittedly, this is a tad unusual: you didn't create any properties in your Java code, and you certainly didn't write anything like this:</p><pre><code>private String uname; &nbsp; <br />
private String password;</code></pre><p>Yet we're asking Tapestry to provide them at run time, so we'll just believe that the properties will be there. All this is a little bit... abstract. And yes, we are going to create abstract getters for these shadowy properties. Here they are:</p><pre><code>public abstract String getUname(); &nbsp; <br />
public abstract String getPassword();</code></pre><p>We'll add these getters to our page class and, since it will have abstract methods, this class will also become abstract! This is how it will look (with comments removed for the sake of brevity):</p><pre><code>package com.sitepoint.tapestry.login; &nbsp; <br />
 &nbsp; <br />
import org.apache.tapestry.html.BasePage; &nbsp; <br />
import org.apache.tapestry.IRequestCycle; &nbsp; <br />
 &nbsp; <br />
public abstract class Home extends BasePage { &nbsp; <br />
 &nbsp;public void onFormSubmit(IRequestCycle cycle) { &nbsp; <br />
 &nbsp; &nbsp;// Some code using getUname() and getPassword will go here &nbsp; <br />
 &nbsp;} &nbsp; <br />
 &nbsp; &nbsp; <br />
 &nbsp;public abstract String getUname(); &nbsp; <br />
 &nbsp;public abstract String getPassword(); &nbsp; <br />
}</code></pre><p>Using abstract classes as a &quot;final product&quot; in your application looks somewhat strange, but as soon as you get used to it, you'll realize that this is actually very handy: you write exactly what you need, and Tapestry takes over and cleverly creates all the &quot;plumbing&quot; for you.</p><p>By the way, you can see this approach not only in Tapestry, but also in EJBs with container-managed persistence.</p><p>Right, we've written enough to test our first Tapestry page. It won't do anything visible at this point, but at least we can check whether Tapestry understands our code properly. If everything goes as planned, we'll see a web page that looks identical to our mockup for the Home page.</p><h5>Informing Tomcat about our Web Application</h5><p>Before running our Tapestry Web application for the first time, we need to inform Tomcat that we've created this application and where to find it. To do this, we'll create a very simple XML file, a kind of note for Tomcat. We'll call it <code>Login.xml</code>. You can use any text editor to create this file; it won't be a part of our Web application.</p><p>This is all we need to write:</p><pre><code>&lt;Context docBase=&quot;/Users/alex/Documents/workspace/Login/context&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;path=&quot;/Login&quot;/&gt;</code></pre><p>In the <code>docBase</code> attribute, you must specify the path to the context subdirectory of your Web application. It will depend on where you've chosen to place your workspace directory when installing Eclipse. In this example, you can see the location of this directory on my Mac. It will be something similar on a Linux machine.</p><p>For Windows, note that when specifying the path to your context, you should use forward slashes, not the backward ones normally used in Windows paths. In other words, you should write <code>docBase=&quot;c:/workspace/Login/context&quot;</code>, instead of <code>docBase=&quot;c:\workspace\Login\context&quot;</code>.</p><p>Put this <code>Login.xml</code> file into the <code>conf/Catalina/localhost</code> subdirectory in your Tomcat directory (examples: <code>c:\apache-tomcat-5.5.12\conf\Catalina\localhost</code> or <code>/Users/alex/jakarta-tomcat-5.0.28/conf/Catalina/localhost</code>).</p><p>We're now ready to run our Tapestry Web application.</p><h5>Running the Application</h5><p>Start your Tomcat server as explained in the &quot;Installing Tomcat&quot; section. If Tomcat was already running, shut it down and start up again -- this will give Tomcat the opportunity to read the new configuration file that we just created when it starts up.</p><p>Point your browser to <code>http://localhost:8080/Login/app</code>. If everything was done properly, you should see the login page as shown in Figure 5 -- exactly as expected. If instead you get an error, go back and double-check that every step has been followed, then restart your Tomcat server and try again.</p><p>You already know that a request for <code>http://localhost:8080</code> will invoke Tomcat running on your computer. <code>/Login</code> tells Tomcat which Web application we want our request sent to. Remember, when configuring Tomcat in the previous section, we told it the path to our application using <code>path=&quot;/Login&quot;</code>.</p><p>The <code>/app</code> part of our request tells our application that this is a request for its Tapestry part. By default, it's configured in such a way that all requests addressed to Tapestry must end with <code>/app</code>. This is for the case that our application contains other, non-Tapestry resources -- static HTML pages, for example. In the next part of this tutorial, I'll show you how to change the configuration so that all requests to <code>/Login</code> are passed to Tapestry.</p><p>Congratulations! You've got your first Tapestry Web application running. Admittedly, it's not much more impressive than 'Hello World' right now, but behind the scenes this page is already using three Tapestry components, and it's just waiting for us to add more functionality.</p><p>Let's add the following ground-breaking behaviour: when a user presses the &quot;Let me in!&quot; button, the second page will be displayed. For now, we won't perform any validation of the username or password. We'll just react to the pressing of the button by displaying the second page.</p><p>Which second page? The one we are going to create right now!</p><p><div
class="article-cms-pagebreak"></div></p><h5>Creating the Second Page</h5><p>Let's name the second page Content, as though it contained something valuable requiring user authentication.</p><p>Right-click the Package Explorer, choose New &gt; Other... , and locate and select the Tapestry Page option. Press Next.</p><p>In the New Tapestry Page Component dialog which opens, enter Content for the Page Name. Make sure that the Generate an associated HTML file? checkbox is checked.  Leave all other values to their default settings and press Next.</p><p>Here you can choose which class to use as a page class. We're going to create some custom functionality, so let's make our own class. Select the Create a new class radio button. Specify the package to be <code>com.sitepoint.tapestry.login</code>, and make the class public and abstract (yes, we are going to use those shadowy Tapestry properties again). Your dialog should look like Figure 14.</p><p><img
src="http://sitepointstatic.com/graphics/afig14.gif"  height="613" width="500" alt="1508_figure14" /><br
/> <em>Figure 14. Creating a New Page with a Custom Page Class</em></p><p>Press Finish and Spindle will create three new files for you: <code>Content.html</code>, <code>Content.page</code> and <code>Content.java</code>.</p><p>The default HTML template for the second page doesn't contain anything useful, so we'll replace its contents with the mockup code from Page 2 in the previous section (titled &quot;Our First Tapestry Web Application&quot;). Modify this mockup into the real HTML template, which looks like this:</p><pre><code>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01//EN&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; &nbsp; &nbsp;<br />
&lt;html&gt; &nbsp; &nbsp;<br />
&lt;head&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;title&gt;You've got it!&lt;/title&gt; &nbsp; &nbsp;<br />
&lt;/head&gt; &nbsp; &nbsp;<br />
&lt;body&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;h2&gt;Precious &lt;span jwcid=&quot;uname&quot;&gt;User&lt;/span&gt;!&lt;/h2&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;h3&gt;Welcome to the wonderful World of Tapestry!&lt;/h3&gt; &nbsp; &nbsp;<br />
&lt;/body&gt; &nbsp; &nbsp;<br />
&lt;/html&gt;</code></pre><p>You can see that, on the second page, we'll be using just one Tapestry component, which is named uname and disguised as a standard HTML span element. You're probably aware that the span element is often used to apply a special style to text. We won't be specifying any styles here, just our magical <code>jwcid</code>, which is incomprehensible and invisible to a web browser.</p><h5>A Specification for the Second Page</h5><p>We're going to need both the username and password in the code for the second page, so let's create the same two properties in the page specification (you can just copy them from <code>Home.page</code>):</p><pre><code>&lt;property-specification name=&quot;uname&quot; type=&quot;java.lang.String&quot;/&gt; &nbsp; &nbsp;<br />
&lt;property-specification name=&quot;password&quot; type=&quot;java.lang.String&quot;/&gt;</code></pre><p>Let's also specify the uname component mentioned in the HTML template. This time, it will be a standard Tapestry Insert component, which simply inserts a string into the outputted HTML. This is how the specification will look:</p><pre><code>&lt;component id=&quot;uname&quot; type=&quot;Insert&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;binding name=&quot;value&quot; expression=&quot;uname&quot;/&gt; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&lt;/component&gt;</code></pre><p>And here's the completed page specification, which goes into the <code>Content.page</code> file:</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &nbsp; &nbsp;<br />
&lt;!DOCTYPE page-specification PUBLIC &nbsp; &nbsp;<br />
 &nbsp;&quot;-//Apache Software Foundation//Tapestry Specification 3.0//EN&quot; &nbsp; &nbsp;<br />
 &nbsp;&quot;http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd&quot;&gt; &nbsp; &nbsp;<br />
&lt;!-- generated by Spindle, http://spindle.sourceforge.net --&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
&lt;page-specification class=&quot;com.sitepoint.tapestry.login.Content&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
 &nbsp;&lt;description&gt;Content page&lt;/description&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;property-specification name=&quot;uname&quot; type=&quot;java.lang.String&quot;/&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;property-specification name=&quot;password&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;type=&quot;java.lang.String&quot;/&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;component id=&quot;uname&quot; type=&quot;Insert&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;binding name=&quot;value&quot; expression=&quot;uname&quot;/&gt; &nbsp; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;/component&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;<br />
&lt;/page-specification&gt;</code></pre><p>All that's left is to fill in our custom page class with some functionality.</p><h5>Adding Functionality to the Page Class</h5><p>We want to be able not only to read the uname and password properties of the page, but to set them as well. That's why we'll create two pairs of abstract getters/setters for the page class. Remember from the first page that these methods will be abstract, because we didn't create the properties ourselves, but asked Tapestry to make them for us at run time.</p><p>With the addition of getters and setters, our <code>Content.java</code> will look like this:</p><pre><code>package com.sitepoint.tapestry.login; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
import org.apache.tapestry.html.BasePage; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
public abstract class Content extends BasePage { &nbsp; &nbsp;<br />
 &nbsp;public abstract String getUname(); &nbsp; &nbsp;<br />
 &nbsp;public abstract String getPassword(); &nbsp; &nbsp;<br />
 &nbsp;public abstract void setUname(String uname); &nbsp; &nbsp;<br />
 &nbsp;public abstract void setPassword(String password); &nbsp; &nbsp;<br />
}</code></pre><div
id="adz" class="vertical"><script type="text/javascript">GA_googleFillSlot("Articles_6_300x250");</script></div><p>It's now time to return to the first page, Login, and add functionality to its page class so that when the form is submitted, the second page (that we named Content) is shown.</p><h5>Navigating From Page to Page</h5><p>Our listener method <code>onFormSubmit()</code> is still empty. Let's add some code to it to display the second page. This can be done quite simply: we'll just ask Tapestry to show another page.</p><p>How do we ask Tapestry to do something for us from our code? We've got its representative, cycle (of type <code>IRequestCycle</code>), which is passed as a parameter to our listener method. So let's just ask this cycle object to do the job for us. This is what our listener method in <code>Home.java</code> looks like:</p><pre><code>public void onFormSubmit(IRequestCycle cycle) { &nbsp; &nbsp;<br />
 &nbsp;cycle.activate(&quot;Content&quot;); &nbsp; &nbsp;<br />
}</code></pre><p>Let's see if it works. At the moment, we need to keep restarting Tomcat every time we make a change, in order to see the most recent version of our application. This is definitely not the most convenient thing to do, and there are easier ways to achieve the same result. However, we've had enough distractions already, so I'll leave you to research the alternatives. For the moment, let's press on.</p><p>Shut down Tomcat if it was running, then start it up again. Point your browser to <code>http://localhost:8080/Login/app</code> and you'll see our login form. Push the Let me in! button and you should see the second page as shown on Fig. 15.</p><p><img
src="http://sitepointstatic.com/graphics/afig15.gif"  height="253" width="405" alt="1508_figure15" /><br
/> <em>Figure 15. The Second Page is Displayed Without a User Name</em></p><p>Notice that no username is output. Well, I didn't ask you to enter a login or password into the login form! But even if I had done so, we didn't tell the second page in our listener method what information we were receiving from the user. Let's correct this.</p><h5>Passing Parameters to the Second Page</h5><p>I'll now show you a design pattern that's used often in Tapestry development to pass variables to another page: the &quot;bucket brigade&quot; pattern.</p><p>We'll do the following:</p><ol><li>Ask Tapestry to give us a reference to the next page that we want to display.</li><p></p><li>Use setters on that page to assign values that we want to pass to the page's properties.</li><p></p><li>Ask Tapestry to display the next page.</li></ol><p>At this point you should understand one important thing: although the users of our web application think of the pages they're viewing as HTML that's being sent to their browsers, in reality (and as far as Tapestry is concerned), each page is a Java class -- a page class -- such as Home or Content. This class has many talents; the ability to send an HTML response is just one of them.</p><p>Our next page is called Content. So, if we wanted to declare a reference to the next page, it would look like this:</p><pre><code>Content nextPage;</code></pre><p>We can tell Tapestry: &quot;Please give us a reference to an instance of a page class for the page named Conten&#038;nt&quot;. Translated into Java, it would look like this:</p><pre><code>Content nextPage = (Content) cycle.getPage(&quot;Content&quot;);</code></pre><p>After receiving the reference, we can use it to invoke any setters that we have prepared in that next page. For example, if we had a username and password received from a user stored in uname and password variables, we could write this:</p><pre><code>nextPage.setUname(uname); &nbsp; &nbsp;<br />
nextPage.setPassword(password);</code></pre><p>We'll then ask Tapestry to show the next page:</p><pre><code>cycle.activate(nextPage);</code></pre><p>Our completed listener method looks like this:</p><pre><code>public void onFormSubmit(IRequestCycle cycle) { &nbsp; &nbsp;<br />
 &nbsp;Content nextPage = (Content) cycle.getPage(&quot;Content&quot;); &nbsp; &nbsp;<br />
 &nbsp;nextPage.setUname(getUname()); &nbsp; &nbsp;<br />
 &nbsp;nextPage.setPassword(getPassword()); &nbsp; &nbsp;<br />
 &nbsp;cycle.activate(nextPage); &nbsp; &nbsp;<br />
}</code></pre><p>Note that in <code>nextPage.setUname(getUname());</code> we're calling the abstract getter of our Home class and passing the returned value to the abstract setter of Content class. It looks strange: how can we use a method that has yet to be implemented? But it works perfectly well at run time, because Tapestry creates implementations of all the abstract methods for us.</p><p>Let's test the new version of our application. Shut down and start up your Tomcat server, and point your browser to <code>http://localhost:8080/Login/app</code>. When the login form appears, enter a user name and any password into it and press the Let me in! button. Depending on which user name you used, the result might look like Figure 16.</p><p><img
src="http://sitepointstatic.com/graphics/afig16.gif"  height="253" width="405" alt="1508_figure16" /><br
/> <em>Figure 16. The Second Page Displays as Expected</em></p><h5>Limiting Access to a Page</h5><p>Since we're requesting a user name and password, it would be natural to limit access to our valuable Content page, so that only authorised users can access it. For now, let's hard-code one password for all users.</p><p>Normally, we'd check the password in the Login page and, if it was correct, we'd send the visitor the hidden Content. But what if some unwanted visitor managed to request the Content page directly, without logging in? Technically, this is possible.</p><p>One of the solutions to this problem is to check the password in the Content page. If the password is correct, we display the contents of the page, otherwise we redirect the user to the Login page.</p><p>To be able to do this, our Content page needs to make an agreement with Tapestry. It should ask, &quot;Please notify me when you are going to show me, so that I can check a few things.&quot; This kind of agreement can be achieved if the page implements the <code>PageValidateListener</code> interface. To implement this interface, we need to declare it and add a <code>pageValidate()</code> method to our page class. With these additions, our <code>Content.java</code> looks like this:</p><pre><code>package com.sitepoint.tapestry.login; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
import org.apache.tapestry.html.BasePage; &nbsp; &nbsp;<br />
import org.apache.tapestry.event.PageValidateListener; &nbsp; &nbsp;<br />
import org.apache.tapestry.event.PageEvent; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
public abstract class Content extends BasePage &nbsp; &nbsp; <br />
 &nbsp; &nbsp;implements PageValidateListener { &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;<br />
 &nbsp;public void pageValidate(PageEvent event) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp;// Some code will go here &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;<br />
 &nbsp;public abstract String getUname(); &nbsp; &nbsp;<br />
 &nbsp;public abstract String getPassword(); &nbsp; &nbsp;<br />
 &nbsp;public abstract void setUname(String uname); &nbsp; &nbsp;<br />
 &nbsp;public abstract void setPassword(String password); &nbsp; &nbsp;<br />
}</code></pre><p>Notice the two new import statements. You don't have to know where to find the classes or interfaces that you need, and you don't need to write these statements by hand. Eclipse will do all that for you. For example, when you type <code>PageEvent</code>, Eclipse will underline it with red, because it doesn't know what you mean. Place your cursor somewhere on this word and choose Source &gt; Add Import, and this smart IDE will create the necessary import statement for you!</p><p>Tapestry will check that the page implements the <code>PageValidateListener</code> interface, so it should have a <code>pageValidate()</code> method. Tapestry calls this method just before showing the page to a user, and it is up to us to define which checks should be done in the method.</p><p>We're going to check if the password specified by the user is the same as the one we've hard-coded. If not, we'll tell Tapestry: &quot;Stop! Don't show this page! Redirect the user to the Home page instead.&quot; This is what it looks like in Java:</p><pre><code>if (!&quot;mellon&quot;.equals(getPassword())) { &nbsp; &nbsp;<br />
 &nbsp;throw new PageRedirectException(&quot;Home&quot;); &nbsp; &nbsp;<br />
}</code></pre><p>If the password entered by the user is &quot;mellon&quot; (the Elvish word for &quot;friend&quot;), everything is fine: they'll see the Content page. If not, we switch on an alarm and tell Tapestry: &quot;Forget whatever you were doing, just show our login form to this user.&quot;</p><p>This is how the completed <code>Content.java</code> should look:</p><pre><code>package com.sitepoint.tapestry.login; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
import org.apache.tapestry.PageRedirectException; &nbsp; &nbsp;<br />
import org.apache.tapestry.html.BasePage; &nbsp; &nbsp;<br />
import org.apache.tapestry.event.PageValidateListener; &nbsp; &nbsp;<br />
import org.apache.tapestry.event.PageEvent; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
public abstract class Content extends BasePage implements PageValidateListener { &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;<br />
 &nbsp;public void pageValidate(PageEvent event) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp;if (!&quot;mellon&quot;.equals(getPassword())) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;throw new PageRedirectException(&quot;Home&quot;); &nbsp; &nbsp;<br />
 &nbsp; &nbsp;} &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;<br />
 &nbsp;public abstract String getUname(); &nbsp; &nbsp;<br />
 &nbsp;public abstract String getPassword(); &nbsp; &nbsp;<br />
 &nbsp;public abstract void setUname(String uname); &nbsp; &nbsp;<br />
 &nbsp;public abstract void setPassword(String password); &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
}</code></pre><p>Now let's test our completed login web application.</p><p>Start or restart Tomcat and navigate, as usual, to <code>http://localhost:8080/Login/app</code>. Enter any user name and a wrong password, and press the Let me in! button. Nothing should happen -- you'll just see the same login form. Now type the secret word for the password that we hard-coded above. You should be able to view the Content page!</p><h5>What Have we Learnt?</h5><p>First, we saw that Tapestry HTML templates can be displayed perfectly in any web browser, because Tapestry's server-side hooks are limited to the attributes of standard HTML tags, so they remain virtually invisible.</p><p>This is very important because the presentation (HTML) remains absolutely independent of the logic (Java code), and either of them can be edited without any changes to the other. This is the cleanest possible separation between presentation and logic -- something that other frameworks struggle with and often fail to achieve.</p><p>We also saw how convenient and useful the Eclipse IDE (with the Spindle plug-in) is when it comes to Tapestry development.</p><p>We got our hands dirty and created a couple of pages, and saw that every page has three parts to it: an HTML template, a page specification and a page class.</p><p>We learned that Tapestry components are declared in the page specification, and saw how the binding is established between a component's jwcid attribute in the HTML template and either an event listener or a property.</p><p>We also saw one of the trickier but more powerful aspects of Tapestry: how page properties can be declared in the page specification, and how we can work with them as if they really existed, even though they're only created by Tapestry at run time.</p><p>We learned how to write code to navigate from one page to another, and how to pass parameters between pages (the &quot;bucket brigade&quot; pattern).</p><p>Finally, we saw how a Tapestry page can protect itself from being accessed by unauthorised visitors, and how little needs to be done to implement this functionality.</p><p>Whew! We've mastered quite a lot for this introduction, but there is still much more to the world of Tapestry!</p><p><strong><em>Further Reading</em></strong></p><p>Currently there are only two books on Jakarta Tapestry available in English:</p><ol><li><a
class="sublink" href="http://www.amazon.com/gp/product/1932394117/102-4971099-2798520">&quot;Tapestry in Action&quot; by Howard Lewis Ship</a>, the creator of Tapestry. This book is useful for gaining a deeper understanding of the ideas behind Tapestry, and details of the inner workings of Tapestry 3. However, it's not very useful as a tutorial for beginners.</li><p><li><a
class="sublink" href="http://www.amazon.com/gp/product/1411649133/qid=1138182732/">&quot;Enjoying Web Development with Tapestry&quot; by Ka lok 'Kent' Tong</a>. I would call this book an advanced tutorial, and it is a must-have title for every Tapestry developer. It's packed with examples and advice starting from the basics and going on to some advanced topics. I found it invaluable when working on my own commercial Tapestry application. The book is available in two editions: for Tapestry 3 and for Tapestry 4.</li></ol> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/jakarta-tapestry/feed/</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>Java Studio Creator 2 Released and Still Free</title><link>http://www.sitepoint.com/java-studio-creator-2-released-and-still-free/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=java-studio-creator-2-released-and-still-free</link> <comments>http://www.sitepoint.com/java-studio-creator-2-released-and-still-free/#comments</comments> <pubDate>Thu, 02 Feb 2006 01:45:27 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://www.sitepoint.com/blogs/2006/02/01/java-studio-creator-2-released-and-still-free/</guid> <description><![CDATA[When I first announced that Sun was making its Java Studio Creator product available as a free download, some skeptics labelled this as a mere publicity stunt ahead of the release of Creator 2. Well, Java Studio Creator 2 is now here, and it&#8217;s still free. Java Studio Creator is based on JavaServer Faces (JSF) [...]]]></description> <content:encoded><![CDATA[<p></p><p>When <a
href="http://www.sitepoint.com/suns-java-studio-creator-is-also-a-free-download/">I first announced</a> that Sun was making its Java Studio Creator product available as a free download, some skeptics labelled this as a mere publicity stunt ahead of the release of Creator 2.</p><p>Well, <a
href="http://developers.sun.com/prodtech/javatools/jscreator/">Java Studio Creator 2 is now here</a>, and it&#8217;s still free.</p><p>Java Studio Creator is based on <a
href="http://java.sun.com/j2ee/javaserverfaces/">JavaServer Faces</a> (JSF) technology, a component-based approach to web development that is similar in style to ASP.NET. This positions Java Studio Creator as a direct competitor to Microsoft&#8217;s <a
href="http://www.sitepoint.com/visual-studio-2005-express-editions-are-free-downloads/">Visual Studio 2005 Express Editions</a>. Both bring drag-and-drop rapid application development to the web and both are free downloads, but Creator is free of many of the restrictions placed on Microsoft&#8217;s Express Editions (e.g. it offers a full visual database query builder).</p><p>And of course, being written in Java, Creator will run on Mac OS X and Linux systems.</p><p>A brief overview of some of the new features:</p><ul><li>improved code completion in code editors (Java, HTML, CSS)</li><li>a new graphical CSS editor</li><li>EJB Support (was beta in Creator 1)</li><li>many new JSF components</li><li>a new database support layer</li><li>HTTP monitoring</li><li>AJAX components (including a Google Maps component)</li><li>runs on Java 5 with associated speed and UI benefits</li></ul><p>If you&#8217;ve considered Java web development in the past and were put off by code-heaviness and cryptic XML configuration files, you should definitely check out the <a
href="http://developers.sun.com/prodtech/javatools/jscreator/overview/tours/">video product tours</a> for Creator 2 to see just how easy it can be.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/java-studio-creator-2-released-and-still-free/feed/</wfw:commentRss> <slash:comments>5</slash:comments> </item> <item><title>All Java, No Froth: 6 Easy Steps to MVC Web Apps</title><link>http://www.sitepoint.com/java-6-steps-mvc-web-apps/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=java-6-steps-mvc-web-apps</link> <comments>http://www.sitepoint.com/java-6-steps-mvc-web-apps/#comments</comments> <pubDate>Tue, 24 Jan 2006 14:00:00 +0000</pubDate> <dc:creator>Kevin Yank</dc:creator> <category><![CDATA[Java EE]]></category> <guid
isPermaLink="false">http://blogs.sitepoint.com/?p=34631</guid> <description><![CDATA[Tired of the Java hype? Cut to the chase with this easy, 6-step tutorial designed to introduce budding Java developers to the power of this fantastic technology. Kevin introduces JDBC, servlets, JSP, and JSTL, and combines them using MVC architecture to help you gain the knowledge you'll need to concoct practical Java web apps.]]></description> <content:encoded><![CDATA[<p></p><p><strong>It&#8217;s an exciting time to be a Java web developer. Gaining popularity amongst hosting providers, <a
class="sublink" href="http://java.sun.com/j2se/1.5.0/">Java 5</a> (Java 2 Standard Edition 5.0) contains a pile of <a
class="sublink" href="http://java.sun.com/developer/technicalArticles/releases/j2se15/">new language features</a> to bamboozle complacent developers who had grown used to knowing the language inside and out. Hosts have also largely deployed the latest releases of major Java web application servers, which support the current standards in Java web development (<a
class="sublink" href="http://java.sun.com/j2ee/">J2EE 1.4</a>). And the major development tools have been updated to support the powerful features of these standards, such as <a
class="sublink" href="http://java.sun.com/j2ee/javaserverfaces/">JavaServer Faces</a>. It&#8217;s all right there, waiting for you to use it.</strong></p><p>At the same time, Java is getting a bad reputation among everyday web developers. There&#8217;s a growing sense that Java isn&#8217;t <em>easy</em> anymore, that you have to work for a company with the budget equal to the GDP of a small country for web development on this platform to make sense. Competing platforms like Microsoft&#8217;s .NET are winning loads of cool points for doing things that Java has done for years; nimble scripting languages like Ruby are making amazing things possible with very little code, while Java is perceived as a stagnant monolith by many.<div
id='div-gpt-ad-1328644474660-10' style='width:728px; height:90px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1328644474660-10'); });</script> </div></p><p>A lot of this sentiment comes from the fact that Java web development was invented in layers. First there was this great, easy-to-learn programming language: Java. Someone wanted to generate web pages with it on the fly, so servlets were invented, and they ran on Java. Someone <em>else</em> wanted to build dynamic web pages without losing the HTML code among all the Java code, so JavaServer Pages (JSP) were invented, and they ran on servlets, which ran on Java.</p><p>Years later, the cutting edge of Java web development sits on top of at least a half dozen layers of technology, and as a newcomer you can quickly feel lost in the forest of buzzwords! So now we get hobbyists asking how to build a web-based photo gallery with Enterprise JavaBeans (EJB) &#8211; the equivalent of buying a tractor trailer to carry your bread and milk home from the corner store.</p><p>In this article, I&#8217;ll chart a map through that forest of buzzwords, so that as you take your first steps in Java web development you can work out what you really need to know, what you can really use, and what you can safely leave to the multinationals. Most importantly, I&#8217;m here to express the joy I find in working with Java. I hope I can help you find it, too.</p><h5>Let&#8217;s Start at the Bottom&#8230;</h5><p>As I have <a
class="sublink broken_link" href="http://www.sitepoint.com/blog-post-view.php?id=203951">mentioned</a>, Java web technology has been built up in layers over many years. Today, there are at least a dozen practical and proven approaches to building web sites with Java. By and large, however, they are all built on the same foundation: <a
class="sublink" href="http://java.sun.com/j2ee/">Java Enterprise Edition</a> (JavaEE) &#8212; previously Java 2 Enterprise Edition (J2EE) &#8212; a constellation of related specifications that describe the aforementioned layers of server-side Java technology.</p><p>Picking our way through J2EE, we&#8217;ll start by looking at <a
class="sublink" href="http://java.sun.com/products/servlet/">Servlets</a>, then we&#8217;ll move on to <a
class="sublink" href="http://java.sun.com/products/jsp">JSP</a>, combine the two as we examine <a
class="sublink" href="http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html">Model 2</a>, extend this to a discussion of MVC frameworks like <a
class="sublink" href="http://struts.apache.org/">Struts</a> and <a
class="sublink" href="http://www.springframework.org/">Spring</a>, and evenutally explore the various View technologies like <a
class="sublink" href="http://jakarta.apache.org/velocity/">Velocity</a>, <a
class="sublink" href="http://java.sun.com/j2ee/javaserverfaces/">JavaServer Faces</a>, and <a
class="sublink" href="http://xmlc.objectweb.org/">XMLC</a>. This is by no means an exhaustive list &#8212; there&#8217;s lots to explore!</p><div
class="vertical">GA_googleFillSlot(&#8220;Articles_6_300x250&#8243;);</div><p>As we do this, I predict you&#8217;ll notice an interesting trend. Most web development platforms start out being reasonably easy to learn and use, but they tend to get more and more complicated as you try to shoehorn larger, more practical and complex projects into them. PHP comes to mind: much as I love that language&#8217;s ease of use, you can spend months reading people&#8217;s thoughts on how best to structure sizeable projects and still not come up with a clean solution.</p><p>The trend with Java is different: there is a lot to learn up front, and at first simple tasks can seem stupidly labour-intensive. But as you become comfortable with the layers of complexity, they begin to work <em>for</em> you, and projects that you used to find intimidating will start to seem easy.</p><p>To begin our tour, we&#8217;ll start with a dead simple web application: a database driven to-do list. We&#8217;ll be building this same application with each of the technologies we explore, and I&#8217;ll provide downloadable code for each version. Because this is a simple project, it&#8217;ll allow you to focus on the differences between the techniques, their strenghts and weaknesses, which features are easy to implement, and which are hard.</p><p>Each incarnation of this application will rely on the same <a
class="sublink" href="http://www.mysql.com/">MySQL</a> database, so let&#8217;s start with that. If you plan to follow along, now&#8217;s a good time to make sure you have a healthy MySQL installation on your development machine. If you&#8217;re <em>really</em> new to databases or server-side web development in general, you can find a solid introduction to MySQL with full installation instructions in the first two chapters of my book, <a
class="sublink" href="http://www.sitepoint.com/books/phpmysql1/"><em>Build Your Own Database Driven Website Using PHP &amp; MySQL</em></a>. These chapters are available as free articles on sitepoint.com: <a
class="sublink" href="http://www.sitepoint.com/article/525">chapter one</a> and <a
class="sublink" href="http://www.sitepoint.com/article/527">chapter two</a>.</p><p>With MySQL in place, create a new database (I&#8217;ll call it <code>todo</code>) with the following single table in it:</p><pre><code>CREATE TABLE todo ( <br />
 &nbsp;todoid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, <br />
 &nbsp;todo VARCHAR(255) NOT NULL <br />
)</code></pre><p>That&#8217;s it! We&#8217;re all set to look at the Java classes that will interface with this simple database.</p><h5>Talking to MySQL: Your First Look at JDBC</h5><p>To build the to-do list application we will use to explore the myriad Java web development technologies that are available, we&#8217;ll begin with the backbone of the application: a set of classes that connect to a MySQL database to retrieve, model, and update a to-do list.</p><p>Before we go any further, you&#8217;ll need a working knowledge of Java as a programming language. At the very least, you should understand the basic concepts of object oriented programming: classes, objects, methods, properties, and constructors. For an overview of these concepts and the necessary basics of Java programming, see my articles: <a
class="sublink" href="http://www.sitepoint.com/article/getting-started-java">Getting Started with Java</a>, <a
class="sublink" href="http://www.sitepoint.com/article/java-language-basics">Java Language Basics</a>, and <a
class="sublink" href="http://www.sitepoint.com/article/oriented-concepts-java-1">Object Oriented Concepts in Java (part one</a> and <a
class="sublink" href="http://www.sitepoint.com/article/oriented-concepts-java-2">two</a>).</p><p>In the following discussion, I&#8217;ll also make use of many of the built-in utility classes that Java offers in its core APIs. If you&#8217;re curious about these (and you should be!), you can browse the reference in the <a
class="sublink" href="http://java.sun.com/j2se/1.5.0/docs/api/">Java 5 API documentation</a>, or grab a copy for yourself from <a
class="sublink" href="http://java.sun.com/j2se/1.5.0/download.jsp">the same page where you downloaded JDK</a>.</p><p>Since we&#8217;re connecting to a database, we will be using the <a
class="sublink" href="http://java.sun.com/products/jdbc/">Java Database Connectivity (JDBC)</a> classes, which are part of the Java Enterprise Edition (JavaEE) platform, supported by all Java-enabled web servers. JDBC provides a common set of classes for connecting to any database server (you can <a
class="sublink" href="http://java.sun.com/products/jdbc/reference/api/">browse the API reference</a> for these classes if you like).</p><p>In order to connect to MySQL with JDBC, we need to grab a copy of <a
class="sublink" href="http://www.mysql.com/products/connector/j/">MySQL Connector/J</a>, the JDBC driver for MySQL. After telling Java to load the driver, we can ask it to connect to a MySQL database, and all of the standard JDBC classes will know how to work with that connection.</p><p>Download and extract the MySQL Connector/J archive. Inside you&#8217;ll find a <code>mysql-connector-java-<em>version</em>-bin.jar</code> file (version 3.1.12 as of this writing), which is the driver library. Ignore the rest of the fluff and copy the JAR file to the working directory in which you plan to build your to-do list Java application.</p><p>We&#8217;re ready to start coding! In this article, I&#8217;ll present all the code line-by-line, so that you can type it straight into your favourite text editor. If you&#8217;re used to some of the more terse scripting languages out there, Java code may seem a bit verbose to you. Indeed, that&#8217;s one of the main things people who don&#8217;t like Java tend to complain about. For real world development, I would highly suggest you get yourself a solid Integrated Development Environment (IDE), such as <a
class="sublink" href="http://www.netbeans.org/">NetBeans</a> or <a
class="sublink" href="http://www.eclipse.org/">Eclipse</a> (both are free). A good IDE will write much of the code for you, so that Java&#8217;s verbosity becomes an aid to code readability, not a hindrance to productivity. In these initial learning stages, however, typing all the code by hand will definitely help you absorb exactly what&#8217;s going on, so I&#8217;ll leave further exploration of IDEs for a later article.</p><p>First of all, let&#8217;s build a class called <code>ToDoList</code>, which will represent the to-do list stored in the database and will allow us to access and modify its entries. We&#8217;ll put this class in a Java package (or namespace) called <code>com.sitepoint</code> so, in your working directory, create a directory called <code>com</code> with a subdirectory called <code>sitepoint</code>, and in it create a file named <code>ToDoList.java</code>. Start the file out with the required package declaration:</p><pre><code>package com.sitepoint;</code></pre><p>In this class, we&#8217;ll use the JDBC classes from the <code>java.sql</code> and the collection classes from <code>java.util</code>, so let&#8217;s import those:</p><pre><code>import java.util.*; <br />
import java.sql.*;</code></pre><p>Finally, we&#8217;ll declare our class:</p><pre><code>public class ToDoList {</code></pre><p>To keep the class as database-independent as possible, we&#8217;ll design its constructor to accept the name of a JDBC driver and a JDBC connection string, which together give it everything it needs to connect to a database through JDBC. The constructor will load the driver class immediately, then store the JDBC connection string in a private property, so that the object can use it to connect to the database when it needs to.</p><pre><code> &nbsp;private String jdbcConnectionString; <br />
 <br />
 &nbsp;public ToDoList(String jdbcDriver, String jdbcConnectionString) { <br />
 &nbsp; &nbsp;this.jdbcConnectionString = jdbcConnectionString; <br />
 <br />
 &nbsp; &nbsp;// Load the driver <br />
 &nbsp; &nbsp;try { <br />
 &nbsp; &nbsp; &nbsp;Class.forName(jdbcDriver).newInstance(); <br />
 &nbsp; &nbsp;} <br />
 &nbsp; &nbsp;catch (Exception ex) { <br />
 &nbsp; &nbsp; &nbsp;System.err.println(&quot;Error loading database driver &quot; + jdbcDriver + <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;:\n&quot; + ex.getMessage()); <br />
 &nbsp; &nbsp;} <br />
 &nbsp;}</code></pre><p><code>Class.forName()</code> obtains a reference to the JDBC driver class, and calling its <code>newInstance()</code> method makes sure it is loaded. We catch any exceptions that may be thrown in case the driver class is not available (if you forget to do this, the compiler will remind you about it).</p><p>Now, our first version of this class will allow Java programs (and web pages) to:</p><ul><li>Get a list of the items on the to-do list.</li><li>Get the number of items on the list.</li><li>Add new items to the list.</li><li>Delete items from the list.</li></ul><p>Because fetching the list from the database can be a time consuming operation, we&#8217;ll make our class keep a copy of the list once it has been fetched, and only update it from the database when necessary.</p><pre><code> &nbsp;private List list = new ArrayList(); <br />
 &nbsp;private boolean staleList = true;</code></pre><p>The <code>list</code> variable will store the list retrieved from the database, and the second will keep track of when that list needs updating (i.e. when it is &quot;stale&quot;). We start off with an empty <code>ArrayList</code> (Java&#8217;s stock-standard list class, from the <code>java.util</code> package), which is assumed to be in need of updating.</p><p>Now, whether the program wants the actual list of to-do items or it simply wants to know how many items there are, we will need to fetch the list from the database. So let&#8217;s write a single private method that checks if the stored list (in the <code>list</code> property) is stale, and loads the list from the database if necessary:</p><pre><code> &nbsp;private void refreshList() { <br />
 &nbsp; &nbsp;if (staleList) { <br />
 &nbsp; &nbsp; &nbsp;// Load list from the database... <br />
 <br />
 &nbsp; &nbsp; &nbsp;staleList = false; <br />
 &nbsp; &nbsp;} <br />
 &nbsp;}</code></pre><p>Loading the list from the database is where JDBC comes in. First, we use the JDBC connection string (stored by the constructor in <code>jdbcConnectionString</code>) to connect to the database. Since this is a time consuming operation, we&#8217;ll store the connection in another private property called <code>conn</code>, and only create a new connection when it is empty:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;if (conn == null) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;conn = DriverManager.getConnection(jdbcConnectionString); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;}</code></pre><p>Next, we create a <code>Statement</code> object from the connection and use it to execute a <code>SELECT</code> query and obtain the resulting <code>ResultSet</code> object:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;Statement stmt = conn.createStatement(); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;ResultSet rs = stmt.executeQuery(&quot;SELECT todoid, todo FROM todo&quot;);</code></pre><p>With the results in hand, we store a new, empty <code>ArrayList</code> in the <code>list</code> property, and fill it with <code>ToDoItem</code> objects created from the contents of the result set:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;list = new ArrayList(); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;while (rs.next()) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list.add(new ToDoItem(rs.getInt(1), rs.getString(2))); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;}</code></pre><p>This may be a confusing bit of code for several reasons. First, we&#8217;re using a <code>while</code> loop to step through the result set. Calling the <code>next()</code> method of the result set advances it to the next record, or returns <code>false</code> if there are no records remaining, thus ending the <code>while</code> loop.</p><p>Within the loop, we&#8217;re using the <code>add()</code> method of the <code>ArrayList</code> class to add items to the list. But what exactly are we adding? New instances of the <code>ToDoItem</code> class.</p><pre><code>ToDoItem</code> is a simple little class that keeps track of an ID (the database ID of a to-do list item) and a string (the text for that item). These two values are &quot;read only&quot;, in that there are no methods provided for altering them. Objects like this that represent records in the database are called <strong>data objects</strong>. Create this class by pasting the following code into a file called <code>ToDoItem.java</code> alongside the <code>ToDoList.java</code> file you're already working on:
</pre><pre><code>package com.sitepoint; <br />
 <br />
public class ToDoItem { <br />
 &nbsp;private int id; <br />
 &nbsp;private String item; <br />
 <br />
 &nbsp;ToDoItem(int id, String item) { <br />
 &nbsp; &nbsp;this.id = id; <br />
 &nbsp; &nbsp;this.item = item; <br />
 &nbsp;} <br />
 <br />
 &nbsp;public int getId() { <br />
 &nbsp; &nbsp;return id; <br />
 &nbsp;} <br />
 <br />
 &nbsp;public String getItem() { <br />
 &nbsp; &nbsp;return item; <br />
 &nbsp;} <br />
 <br />
 &nbsp;public String toString() { <br />
 &nbsp; &nbsp;return getItem(); <br />
 &nbsp;} <br />
}</code></pre><p>The only detail worthy of note in this simple class is that the constructor is not declared public, but is instead left package private, so that only classes within the <code>com.sitepoint</code> package can create <code>ToDoItem</code> objects.</p><p>Returning to <code>ToDoList</code>, the constructor of <code>ToDoItem</code> expects to be given the ID and text values for the item. We can fetch these values from the current row of the result set, using <code>getInt(1)</code> to fetch an integer value from the first column (<code>todoid</code>) and <code>getString(2)</code> to get a string value from the second column (<code>todo</code>).</p><p>That&#8217;s it for filling up the list, except that to handle database errors from all this we much catch any <code>SQLException</code>s that might be thrown (again, the compiler will remind you if you forget). Here&#8217;s the completed <code>refreshList()</code> method, and the delcaration for the <code>conn</code> property:</p><pre><code> &nbsp;private Connection conn; <br />
 <br />
 &nbsp;private void refreshList() { <br />
 &nbsp; &nbsp;if (staleList) { <br />
 &nbsp; &nbsp; &nbsp;try { <br />
 &nbsp; &nbsp; &nbsp; &nbsp;if (conn == null) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;conn = DriverManager.getConnection(jdbcConnectionString); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp; &nbsp; &nbsp;Statement stmt = conn.createStatement(); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;ResultSet rs = stmt.executeQuery(&quot;SELECT todoid, todo FROM todo&quot;); <br />
 <br />
 &nbsp; &nbsp; &nbsp; &nbsp;list = new ArrayList(); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;while (rs.next()) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list.add(new ToDoItem(rs.getInt(1), rs.getString(2))); <br />
 &nbsp; &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp; &nbsp;catch (SQLException ex) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp;System.err.println( <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;Error retrieving to-do list items from the database:\n&quot; + <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ex.getMessage()); <br />
 &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp; &nbsp;staleList = false; <br />
 &nbsp; &nbsp;} <br />
 &nbsp;}</code></pre><p>With the hard work done in <code>refreshList()</code>, implementing <code>getToDoItems()</code> and <code>getItemCount()</code>, to obtain the to-do list items and the number of such items respectively, is a cinch:</p><pre><code> &nbsp;public Iterator getToDoItems() { <br />
 &nbsp; &nbsp;refreshList(); <br />
 &nbsp; &nbsp;return list.iterator(); <br />
 &nbsp;} <br />
 <br />
 &nbsp;public int getItemCount() { <br />
 &nbsp; &nbsp;refreshList(); <br />
 &nbsp; &nbsp;return list.size(); <br />
 &nbsp;}</code></pre><p>The <code>iterator()</code> method of Java&#8217;s list classes returns an <code>Iterator</code>, an object much like the database result set we just worked with, that lets the requesting object step through the list. <code>size()</code>, meanwhile, is self-explanatory.</p><p>The <code>addItem()</code> and <code>deleteItem()</code> methods work much the same way as <code>refreshList()</code>, except they use a <code>PreparedStatement</code> instead of a simple <code>Statement</code>. Consider this code from <code>addItem</code>:</p><pre><code> &nbsp; &nbsp; &nbsp;PreparedStatement stmt = conn.prepareStatement( <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;INSERT INTO todo (todo) VALUES (?)&quot;); <br />
 &nbsp; &nbsp; &nbsp;stmt.setString(1, item); <br />
 &nbsp; &nbsp; &nbsp;stmt.executeUpdate();</code></pre><p>Notice the question mark in the <code>INSERT</code> query. This indicates a spot where some unknown value will be added to the query (the text for the new to-do list item, in this case). The <code>setString(1, item)</code> method call that follows assigns a string value (provided by the <code>item</code> variable in this case) to the first spot in the query. Other methods like <code>setInt()</code> let you enter values of other types. Sticking values into your database queries in this way neatly sidesteps the character escaping issues that often come into play with other languages, and that are often the cause of security vulnerabilities.</p><p>Here&#8217;s the complete code for <code>addItem()</code> and <code>deleteItem()</code>, thus completing our <code>ToDoList</code> class:</p><pre><code> &nbsp;public void addItem(String item) { <br />
 &nbsp; &nbsp;try { <br />
 &nbsp; &nbsp; &nbsp;if (conn == null) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp;conn = DriverManager.getConnection(jdbcConnectionString); <br />
 &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp; &nbsp;PreparedStatement stmt = conn.prepareStatement( <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;INSERT INTO todo (todo) VALUES (?)&quot;); <br />
 &nbsp; &nbsp; &nbsp;stmt.setString(1, item); <br />
 &nbsp; &nbsp; &nbsp;stmt.executeUpdate(); <br />
 &nbsp; &nbsp;} <br />
 &nbsp; &nbsp;catch (SQLException ex) { <br />
 &nbsp; &nbsp; &nbsp;System.err.println( <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;Error adding a to-do list item to the database:\n&quot; + <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ex.getMessage()); <br />
 &nbsp; &nbsp;} <br />
 &nbsp; &nbsp;staleList = true; <br />
 &nbsp;} <br />
 <br />
 &nbsp;public void deleteItem(int id) { <br />
 &nbsp; &nbsp;try { <br />
 &nbsp; &nbsp; &nbsp;if (conn == null) { <br />
 &nbsp; &nbsp; &nbsp; &nbsp;conn = DriverManager.getConnection(jdbcConnectionString); <br />
 &nbsp; &nbsp; &nbsp;} <br />
 &nbsp; &nbsp; &nbsp;PreparedStatement stmt = conn.prepareStatement( <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;DELETE FROM todo WHERE todoid=?&quot;); <br />
 &nbsp; &nbsp; &nbsp;stmt.setInt(1, id); <br />
 &nbsp; &nbsp; &nbsp;stmt.executeUpdate(); <br />
 &nbsp; &nbsp;} <br />
 &nbsp; &nbsp;catch (SQLException ex) { <br />
 &nbsp; &nbsp; &nbsp;System.err.println( <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;Error deleting a to-do list item from the database:\n&quot; + <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ex.getMessage()); <br />
 &nbsp; &nbsp;} <br />
 &nbsp; &nbsp;staleList = true; <br />
 &nbsp;}</code></pre><p>Notice that each of these methods sets <code>staleList</code> to <code>true</code> once it&#8217;s done its job, so that the next attept to read the to-do list will cause <code>refreshList</code> to fetch it from the database again.</p><p>All we need now is a class to test the work we&#8217;ve done so far. Here&#8217;s a class called <code>ToDoTest</code> that&#8217;ll do the trick. Put <code>ToDoTest.java</code> in with your other files:</p><pre><code>package com.sitepoint; <br />
 <br />
import java.util.*; <br />
 <br />
public class ToDoTest { <br />
 &nbsp;public static void main(String[] args) { <br />
 &nbsp; &nbsp;ToDoList list = new ToDoList(&quot;com.mysql.jdbc.Driver&quot;, <br />
 &nbsp; &nbsp; &nbsp; &nbsp;&quot;jdbc:mysql://localhost/<em>todo</em>?user=<em>root</em>&amp;password=<em>password</em>&quot;); <br />
 <br />
 &nbsp; &nbsp;System.out.println(&quot;The to-do list contains &quot; + list.getItemCount() + <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;items:&quot;); <br />
 &nbsp; &nbsp;Iterator it = list.getToDoItems(); <br />
 &nbsp; &nbsp;while (it.hasNext()) { <br />
 &nbsp; &nbsp; &nbsp;System.out.println(&quot; - &quot; + it.next()); <br />
 &nbsp; &nbsp;} <br />
 <br />
 &nbsp; &nbsp;list.addItem(&quot;Another todo item.&quot;); <br />
 &nbsp; &nbsp;list.addItem(&quot;And yet another.&quot;); <br />
 <br />
 &nbsp; &nbsp;System.out.println(&quot;The to-do list contains &quot; + list.getItemCount() + <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot; items:&quot;); <br />
 &nbsp; &nbsp;it = list.getToDoItems(); <br />
 &nbsp; &nbsp;while (it.hasNext()) { <br />
 &nbsp; &nbsp; &nbsp;System.out.println(&quot; - &quot; + it.next()); <br />
 &nbsp; &nbsp;} <br />
 &nbsp;} <br />
}</code></pre><p>You&#8217;ll need to substitute your MySQL database name, user name, and password into the JDBC connection string near the top of this file.</p><p>Compile your three classes from the top-level working directory:</p><pre><code>javac com/sitepoint/ToDoList.java com/sitepoint/ToDoItem.java <br />
 &nbsp; &nbsp;com/sitepoint/ToDoTest.java</code></pre><p>Then run <code>ToDoTest</code>, with the MySQL JDBC driver added to the classpath:</p><pre><code>java -classpath .;mysql-connector-java-3.0.15-ga-bin.jar <br />
 &nbsp; &nbsp;com.sitepoint.ToDoTest</code></pre><p>You should see a list of the to-do list items before and after the two new items are added to the list, something like this:</p><pre><code>The to-do list contains 2 items: <br />
 - Another todo item. <br />
 - And yet another. <br />
The to-do list contains 4 items: <br />
 - Another todo item. <br />
 - And yet another. <br />
 - Another todo item. <br />
 - And yet another.</code></pre><p><a
class="sublink" href="http://www.sitepoint.com/examples/jgrind/todo-backbone.zip">Download the source code</a>. (5KB)</p><p>That&#8217;s it! We&#8217;re ready to build a web application around these classes.</p><p><div
class="article-cms-pagebreak"></div></p><h5>Servlets</h5><p>If you&#8217;ve followed along, you&#8217;ve now got a to-do list database and a couple of classes that view and update it. The next step is to take that functionality to the web by wrapping it in a web application. On the Java platform, there are dozens of ways to do this. The simplest approach is to write a servlet. A servlet is simply a class that has methods that handle requests from web browsers.</p><p>Basic page requests are handled by a <code>doGet()</code> method. Form submissions that use the POST method are handled by a <code>doPost()</code> method. Objects passed to these methods provide access to information about the browser request and allow control over the servlet&#8217;s response.</p><div
class="vertical">GA_googleFillSlot(&#8220;Articles_6_300x250&#8243;);</div><p>An XML configuration file controls the URLs the servlet is responsible for, and provides any configuration information that the servlet may require.</p><p>The Java web application standard (J2EE) even specifies a directory structure, so that the servlet always knows where to find any class files, configuration files, and additional web resources (like images and style sheets) that it needs.</p><p>Let&#8217;s start by putting the stuff we have already into the correct directory structure. Create a new empty directory to work in, then create a subdirectory called <code>WEB-INF</code>. All of the &quot;normal&quot; web resources (HTML pages, images, style sheets and JavaScript files) will go in the main directory, while all the Java stuff (classes, libraries and configuration files) will go in <code>WEB-INF</code>.</p><p>Within <code>WEB-INF</code>, create two more subdirectories: <code>classes</code> and <code>lib</code>. <code>WEB-INF/classes</code> will contain all the Java classes for our web application, and <code>WEB-INF/lib</code> will contain any libraries that those classes may require.</p><p>Speaking of required libraries, remember from the previous section that our <code>ToDoList</code> class requires the JDBC driver for MySQL (MySQL Connector/J) to access the database. For a standalone application, we needed to add the JAR file (<code>mysql-connector-java-<em>version</em>-bin.jar</code>) to the classpath. For a Java web application, simply drop the file into the <code>WEB-INF/lib</code> directory.</p><p>Since we&#8217;ll be using the classes we&#8217;ve already developed (<code>ToDoList</code> and <code>ToDoItem</code>) in our web application, we need to put them in the <code>WEB-INF/classes</code> directory. You might as well drop the source files in there along with the compiled classes, just in case you need to make any changes &#8212; recompiling will then be a breeze.</p><p>Here&#8217;s our file and directory structure so far:</p><pre><code>/WEB-INF/classes/com/sitepoint/ToDoItem.class &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoItem.java &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoList.class &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoList.java &nbsp;<br />
/WEB-INF/lib/mysql-connector-java-<em>version</em>-bin.jar</code></pre><p>Let&#8217;s now turn our attention to building the servlet for our application. Remember, servlets are just Java classes, and this one will be <code>com.sitepoint.ToDoServlet</code>:</p><pre><code>package com.sitepoint; &nbsp;<br />
 &nbsp;<br />
import java.io.*; &nbsp;<br />
import java.util.*; &nbsp;<br />
import javax.servlet.*; &nbsp;<br />
import javax.servlet.http.*; &nbsp;<br />
 &nbsp;<br />
public class ToDoServlet extends HttpServlet {</code></pre><p>As you can see, servlet classes must extend the <code>javax.servlet.HttpServlet</code> class. You can view documentation on this and related classes in the <a
class="sublink" href="http://java.sun.com/j2ee/1.4/docs/api/">J2EE API Specification</a>.</p><p>Our servlet will use an instance of our <code>ToDoList</code> class, which we want to create when the servlet is first loaded. We can perform initialization tasks like this in the <code>init()</code> method, which the server will call when it loads the servlet:</p><pre><code> &nbsp;private ToDoList toDoList; &nbsp;<br />
 &nbsp;<br />
 &nbsp;// Initialize global variables &nbsp;<br />
 &nbsp;public void init() throws ServletException { &nbsp;<br />
 &nbsp; &nbsp;toDoList = new ToDoList(getInitParameter(&quot;jdbcDriver&quot;), &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;getInitParameter(&quot;jdbcConnectionString&quot;)); &nbsp;<br />
 &nbsp;}</code></pre><p>You may recall that the <code>ToDoList</code> constructor takes the name of the JDBC driver you want to use, and a JDBC connection string so that it can connect to your database. Rather than hard-coding these strings into our servlet, we use this code, which uses initialization parameters for these values, so that they can be configured without recompiling the servlet. We&#8217;ll look more at this later.</p><p>You&#8217;ll notice that the <code>init()</code> method, like all standard servlet methods, can throw a <code>ServletException</code>. This exception is used to let the server know that something went wrong in the servlet. We&#8217;ll see how this works a bit later.</p><p>Next up is the <code>doGet()</code> method, which handles normal browser requests. It takes two parameters: an <code>HttpServletRequest</code> that contains detailed information about the browser request, and a <code>HttpServletResponse</code> that the servlet can use to control its response to the browser:</p><pre><code> &nbsp;public void doGet(HttpServletRequest request, HttpServletResponse response) &nbsp;<br />
 &nbsp; &nbsp; &nbsp;throws ServletException, IOException {</code></pre><p>Once again, the method is able to throw a <code>ServletException</code> to signal an error in the servlet. The servlet specification also allows this function to throw an <code>IOException</code>, in case there is a problem reading the request, or writing the response.</p><p>In response to normal browser requests, we want to display the current to-do list and give the user the ability to add items to the list, and also to delete existing items on the list. First, we must let the <code>HttpServletResponse</code> object know what content type we will be sending back to the browser:</p><pre><code> &nbsp; &nbsp;response.setContentType(&quot;text/html&quot;);</code></pre><p>Now we can ask it for a <code>PrintWriter</code> object that we can use to send HTML code to the browser:</p><pre><code> &nbsp; &nbsp;PrintWriter out = response.getWriter();</code></pre><p>The <code>PrintWriter</code> object lets us send HTML code to the browser using its <code>println()</code> method:</p><pre><code> &nbsp; &nbsp;out.println(&quot;&lt;!DOCTYPE html PUBLIC \&quot;-//W3C//DTD XHTML 1.0 Strict//EN\&quot;\n&quot; + &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot; &nbsp;\&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\&quot;&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;html xmlns=\&quot;http://www.w3.org/1999/xhtml\&quot;&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;head&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;title&gt;To-Do List&lt;/title&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;meta http-equiv=\&quot;content-type\&quot; &quot; + &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;content=\&quot;text/html; charset=iso-8859-1\&quot; /&gt;&quot;);</code></pre><p>If this doesn&#8217;t look very pretty to you, then you&#8217;ve spotted the biggest weakness of servlets: the HTML markup is mixed in with the Java logic of your application, which makes it difficult to read and maintain.</p><p>Pressing on, we want to link a CSS style sheet to our page:</p><pre><code> &nbsp; &nbsp;out.println(&quot;&lt;link rel=\&quot;stylesheet\&quot; type=\&quot;text/css\&quot; href=\&quot;&quot; + &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;request.getContextPath() + &quot;/styles.css\&quot; /&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;/head&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;body&gt;&quot;);</code></pre><p>Since we don&#8217;t yet know which directory of the web server our application will be installed in, we don&#8217;t know the path at which resources like style sheets and images will be available. The above code uses the <code>request</code> object&#8217;s <code>getContextPath()</code> method to obtain the path to the root of our application, and from there we can point to the <code>styles.css</code> file, which we&#8217;ll create a little later.</p><p>Next up, we&#8217;ll display our to-do list in an HTML form menu. We can start by grabbing an <code>Iterator</code> from our <code>ToDoList</code> with its <code>getToDoItems()</code> method. Then, we&#8217;ll check to see if it contains any items with its <code>hasNext()</code> method:</p><pre><code> &nbsp; &nbsp;Iterator toDoItems = toDoList.getToDoItems(); &nbsp;<br />
 &nbsp; &nbsp;if (toDoItems.hasNext()) {</code></pre><p>We want the form to submit back to the same URL, so that this servlet can handle that request as well, so we use the <code>getRequestURI()</code> method to get it:</p><pre><code> &nbsp; &nbsp; &nbsp;out.println(&quot;&lt;form action=\&quot;&quot; + request.getRequestURI() + &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;\&quot; method=\&quot;post\&quot;&gt;&quot;);</code></pre><p>Since HTML form menus turn into drop-down lists with a <code>size</code> of 1, we want the <code>&lt;select&gt;</code> tag to have a <code>size</code> of at least 2, but we also want it to stretch to accomodate the number of items in our to-do list. We use the <code>Math.max()</code> method choose between 2 and the total number of items in the list, as given by the <code>getItemCount()</code> method of our <code>ToDoList</code>:</p><pre><code> &nbsp; &nbsp; &nbsp;out.println(&quot;&lt;select name=\&quot;deleteid\&quot; size=\&quot;&quot; + &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Math.max(2, toDoList.getItemCount()) + &quot;\&quot;&gt;&quot;);</code></pre><p>We can then loop through the <code>toDoItems</code> with a <code>while</code> loop. Each time we move through the loop, we pull a <code>ToDoItem</code> out of the <code>Iterator</code> with <code>next()</code>. Since it doesn&#8217;t <em>know</em> it contains <code>ToDoItem</code>s, we need to cast them to the right class before we can use them:</p><pre><code> &nbsp; &nbsp; &nbsp;while (toDoItems.hasNext()) { &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;ToDoItem toDoItem = (ToDoItem) toDoItems.next();</code></pre><p>For each item, we want to create a <code>&lt;option&gt;</code> tag with the item&#8217;s ID as its <code>value</code>. Outputting the ID is no problem, since it&#8217;s just an integer, but the to-do item itself gets tricky. What if the to-do item contains HTML code &#8212;  possibly even malicious script code? We don&#8217;t want to output that stuff and have it interpreted by the browser as part of our site! The solution is to escape any special characters in the value before printing it out.</p><p>This is another area where servlets are weak: there is no built-in HTML escaping functionality in the servlet API or in Java in general (at least none that is accessible to us). Thankfully, this is a longstanding issue, and 3rd party classes have been created to do the job. The one I&#8217;ve chosen is developed and distributed by <a
class="sublink" href="http://www.anyware.co.uk/anyware/java/">AnyWare</a>. The class is called <code>uk.co.anyware.html.HTMLEscaper</code>, and its source code and license are included in the code archive I&#8217;ve provided below.</p><p>To use <code>HTMLEscaper</code>, drop the class (and source code if you want to hold onto it) into the <code>WEB-INF/classes</code> directory and add the required <code>import</code> to the top of the <code>ToDoServlet</code> class:</p><pre><code>import uk.co.anyware.html.*;</code></pre><p>With the class in hand, we can now safely output the to-do item. We&#8217;ll also polish off the rest of the form with a submit button for deleting selected items:</p><pre><code> &nbsp; &nbsp; &nbsp;out.println(&quot;&lt;/select&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp; &nbsp;out.println(&quot;&lt;input type=\&quot;submit\&quot; value=\&quot;Delete Selected Item\&quot; /&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp; &nbsp;out.println(&quot;&lt;/form&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;}</code></pre><p>We&#8217;ll finish off the page with a second form, this time for submitting new to-do items:</p><pre><code> &nbsp; &nbsp;out.println(&quot;&lt;form action=\&quot;&quot; + request.getRequestURI() + &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;\&quot; method=\&quot;post\&quot;&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;input type=\&quot;text\&quot; name=\&quot;newtodo\&quot; /&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;input type=\&quot;submit\&quot; value=\&quot;Add New Item\&quot; /&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;/form&gt;&quot;); &nbsp;<br />
 &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;/body&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.println(&quot;&lt;/html&gt;&quot;); &nbsp;<br />
 &nbsp; &nbsp;out.close(); &nbsp;<br />
 &nbsp;}</code></pre><p>That takes care of displaying the initial page to the user, but we&#8217;ve now got two forms submitting back to this same servlet!</p><p>Both of these forms submit using the POST method (<code>method=&quot;post&quot;</code>), so we could handle them in the servlet&#8217;s <code>doPost()</code> method. But to make the servlet as flexible as possible we&#8217;ll also support submissions for adding new to-do items, and deleting existing ones, via GET requests. To do this, we&#8217;ll simply feed POST requests back into our <code>doGet()</code> method:</p><pre><code> &nbsp;public void doPost(HttpServletRequest request, HttpServletResponse response) &nbsp;<br />
 &nbsp; &nbsp; &nbsp;throws ServletException, IOException { &nbsp;<br />
 &nbsp; &nbsp;doGet(request, response); &nbsp;<br />
 &nbsp;}</code></pre><p>At the top of <code>doGet()</code>, we now need to check for and process our form submissions. Here&#8217;s the code for handling new to-do items:</p><pre><code> &nbsp; &nbsp;String newToDo = request.getParameter(&quot;newtodo&quot;); &nbsp;<br />
 &nbsp; &nbsp;if (newToDo != null) { &nbsp;<br />
 &nbsp; &nbsp; &nbsp;toDoList.addItem(newToDo); &nbsp;<br />
 &nbsp;<br />
 &nbsp; &nbsp; &nbsp;// Redirect to self &nbsp;<br />
 &nbsp; &nbsp; &nbsp;response.sendRedirect(request.getRequestURI()); &nbsp;<br />
 &nbsp; &nbsp; &nbsp;return; &nbsp;<br />
 &nbsp; &nbsp;}</code></pre><p>The <code>getParameter()</code> method lets us retrieve a submitted value with a given name as a string. If the value isn&#8217;t <code>null</code>, we know we have a submission on our hands. We add it to the to-do list using its <code>addItem</code> method, then redirect the browser to the current page with the response&#8217;s <code>sendRedirect()</code> method.</p><p>If we didn&#8217;t redirect the browser, the rest of the <code>doGet()</code> method would indeed display the updated to-do list for the user, but refreshing the page would cause the form submission to be sent again, resulting in a duplicate entry on the to-do list. Redirecting the browser back to the same page forces the browser to think of it as a separate request, and therefore it will not resubmit the form when refreshing the page.</p><p><div
class="article-cms-pagebreak"></div></p><p>The code for processing deleted items is very similar, except that it must convert the submitted string into an integer for the to-do list&#8217;s <code>deleteItem()</code> method:</p><pre><code> &nbsp; &nbsp;String deleteid = request.getParameter(&quot;deleteid&quot;); &nbsp; <br />
 &nbsp; &nbsp;if (deleteid != null) { &nbsp; <br />
 &nbsp; &nbsp; &nbsp;try { &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;toDoList.deleteItem(Integer.parseInt(deleteid)); &nbsp; <br />
 &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;// Redirect to self &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;response.sendRedirect(request.getRequestURI()); &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;return; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;} &nbsp; <br />
 &nbsp; &nbsp; &nbsp;catch (NumberFormatException e) { &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;throw new ServletException(&quot;Bad deleteid value submitted.&quot;, e); &nbsp; <br />
 &nbsp; &nbsp; &nbsp;} &nbsp; <br />
 &nbsp; &nbsp;}</code></pre><p>The conversion is achieved by the <code>Integer.parseInt()</code> method but, if the value submitted cannot be converted into a number, it will throw a <code>NumberFormatException</code>. If this happens, our code catches the exception and throws a <code>ServletException</code> (to which we pass the <code>NumberFormatException</code> as a root cause).</p><div
class="vertical">GA_googleFillSlot(&#8220;Articles_6_300x250&#8243;);</div><p>Remember, all standard servlet methods are allowed to throw <code>ServletException</code>s to let the server know something has gone wrong. That&#8217;s exactly what we&#8217;re doing here. When the code throws the <code>ServletException</code>, the server running the servlet catches it and displays an appropriate error message in the user&#8217;s browser. You can configure most Java servers to control how much technical detail is included in such error pages.</p><p>Believe it or not, that&#8217;s it for the servlet! You still have to compile it, though, and that&#8217;s a little tricky. You see, the <code>HttpServlet</code> class that our servlet extends is included in the libraries distributed with every Java server, and you need that class to be able to compile your subclass.</p><p>In Tomcat 5.x, the servlet library is called <code>servlet-api.jar</code> and it can be found in the <code>common\lib</code> directory of your Tomcat installation. So you can compile your servlet by including that JAR file in the classpath:</p><pre><code>javac -classpath &nbsp; <br />
&quot;.;c:\Program Files\Apache Group\Tomcat 5.5\common\lib\servlet-api.jar&quot; &nbsp; <br />
com/sitepoint/*.java uk/co/anyware/html/*.java</code></pre><p>Here&#8217;s what your file and directory structure should look like now:</p><pre><code>/WEB-INF/classes/com/sitepoint/ToDoItem.class &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoItem.java &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoList.class &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoList.java &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.class &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.java &nbsp; <br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class &nbsp; <br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java &nbsp; <br />
/WEB-INF/lib/mysql-connector-java-<em>version</em>-bin.jar</code></pre><p>We have two things left to add to complete our Java web application. The first is the <code>styles.css</code> style sheet referenced by our servlet:</p><pre><code>body, p, td, th { &nbsp; <br />
 &nbsp;background: #fff; &nbsp; <br />
 &nbsp;color: #000; &nbsp; <br />
 &nbsp;font: medium Verdana, Arial, Helvetica, sans-serif; &nbsp; <br />
} &nbsp; <br />
 &nbsp; <br />
select { &nbsp; <br />
 &nbsp;width: 100%; &nbsp; <br />
}</code></pre><p>Drop this in the main application directory, which also contains the <code>WEB-INF</code> directory.</p><p>The other thing we need is the XML configuration file for the application, <code>web.xml</code>. This file is called the <strong>deployment descriptor</strong>. It must start with a <code>&lt;web-app&gt;</code> tag like this one (again, any decent IDE will write this boilerplate code for you):</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &nbsp; <br />
&lt;web-app xmlns=&quot;http://java.sun.com/xml/ns/j2ee&quot; &nbsp; <br />
 &nbsp; &nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; &nbsp; <br />
 &nbsp; &nbsp;xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd&quot; &nbsp; <br />
 &nbsp; &nbsp;version=&quot;2.4&quot;&gt;</code></pre><p>Next up, we provide a name for our web application:</p><pre><code> &nbsp;&lt;display-name&gt;ToDoServlet&lt;/display-name&gt;</code></pre><p>Now we&#8217;ll configure our servlet. We give it a name and specify its class:</p><pre><code> &nbsp;&lt;servlet&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;toDo&lt;/servlet-name&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-class&gt;com.sitepoint.ToDoServlet&lt;/servlet-class&gt;</code></pre><p>Now, remember the <code>init()</code> method of our servlet used two initialization parameters: one for the JDBC driver class name, and one for the JDBC connection string. We provide values for those parameters here:</p><pre><code> &nbsp; &nbsp;&lt;init-param&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;description&gt;The JDBC driver class.&lt;/description&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;param-name&gt;jdbcDriver&lt;/param-name&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;param-value&gt;com.mysql.jdbc.Driver&lt;/param-value&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;/init-param&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;init-param&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;description&gt;The JDBC connection string.&lt;/description&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;param-name&gt;jdbcConnectionString&lt;/param-name&gt; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;param-value&gt;jdbc:mysql://localhost/todo?user=root&amp;amp;password=password&lt;/param-value&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;/init-param&gt; &nbsp; <br />
 &nbsp;&lt;/servlet&gt;</code></pre><p>Finally, we supply a servlet mapping, which sends requests to a given URL to the servlet. For our example, we&#8217;ll direct requests for <code>index.html</code> in the root of our application to our servlet:</p><pre><code> &nbsp;&lt;servlet-mapping&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;toDo&lt;/servlet-name&gt; &nbsp; <br />
 &nbsp; &nbsp;&lt;url-pattern&gt;/index.html&lt;/url-pattern&gt; &nbsp; <br />
 &nbsp;&lt;/servlet-mapping&gt; &nbsp; <br />
&lt;/web-app&gt;</code></pre><p>That&#8217;s it for our application! Here&#8217;s the complete list of files:</p><pre><code>/styles.css &nbsp; <br />
/WEB-INF/web.xml &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoItem.class &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoItem.java &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoList.class &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoList.java &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.class &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.java &nbsp; <br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class &nbsp; <br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java &nbsp; <br />
/WEB-INF/lib/mysql-connector-java-<em>version</em>-bin.jar</code></pre><p>You&#8217;re now ready to bundle this application up so that it&#8217;s ready to be deployed on a Java-capable server. To do this, you need to use the <code>jar</code> utility included with the JDK. If you&#8217;ve added the <code>bin</code> directory of your JDK to your system path, you should be able to run it from the command prompt just by typing <code>jar</code>.</p><p>Move to your working directory for the application (the one that contains <code>styles.css</code> and <code>WEB-INF</code>), and type this command:</p><pre><code>jar cvf ToDoServlet.war .</code></pre><p>This will produce a file called <code>ToDoServlet.war</code> containing your application. It&#8217;s actually a ZIP file in disguise.</p><p>You now need to deploy this application on your server. Different servers provide different ways of doing this. If you&#8217;re using Tomcat, simply copy the <code>ToDoServlet.war</code> file into the <code>webapps</code> directory of your installation. After a few moments, Tomcat will automatically extract the file into a new directory. You can then go and edit the <code>web.xml</code> file to make sure the JDBC connection string contains the correct details for your database server.</p><p>Once that&#8217;s done, you should be ready to run your application. Load up <code>http://localhost:8080/ToDoServlet/index.html</code> in your browser (assuming Tomcat is running on port 8080 on your local machine). Here&#8217;s what you should see:</p><p><img
src="http://sitepointstatic.com/graphics/48_todoservlet.gif" height="286" width="425" alt="1507_todoservlet" /></p><p>Have a play with the page. It should work just as you&#8217;d expect. Here&#8217;s the WAR file (complete with source code if you unzip it):</p><p><a
class="sublink" href="http://www.sitepoint.com/examples/jgrind/ToDoServlet.war">Download the code</a>. (250KB)</p><p><div
class="article-cms-pagebreak"></div></p><h5>Old School JSP</h5><p>You&#8217;re ready for your next step along the path to understanding the state of the art in Java web application development. So far, we&#8217;ve looked at servlets: Java classes that are designed to respond to web browser requests. Using a servlet, we have assembled a simple web interface to our database driven to-do list. And while it works, it would be a pain in the butt to write practical web applications this way, with the application logic all mixed in with the HTML code for the page.</p><p><strong>JavaServer Pages</strong> (JSP) were created to overcome this weakness of servlets. Instead of writing a Java class with HTML code in it, you write an HTML page with Java code in it. The server then converts this page into a Java servlet on the fly in order to process page requests. As we&#8217;ll see, reversing our approach in this way solves some problems, but creates some new ones.</p><p>Starting with the to-do list web application we built a moment ago, let&#8217;s do away with our pesky servlet and replace it with a JavaServer page that does the same thing: <code>todo.jsp</code>. Here&#8217;s the updated file and directory structure for our application:</p><pre><code>/todo.jsp &nbsp; &nbsp;<br />
/styles.css &nbsp; &nbsp;<br />
/WEB-INF/web.xml &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoItem.class &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoItem.java &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoList.class &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoList.java &nbsp; &nbsp;<br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class &nbsp; &nbsp;<br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java &nbsp; &nbsp;<br />
/WEB-INF/lib/mysql-connector-java-version-bin.jar</code></pre><div
class="vertical">GA_googleFillSlot(&#8220;Articles_6_300x250&#8243;);</div><p>Let&#8217;s get started writing our <code>todo.jsp</code> file. Open up your favourite text editor and we&#8217;ll get cooking!</p><p>JSP files look a lot like HTML files, except that scattered throughout them will be special JSP tags. As a general rule, all JSP tags start with <code>&lt;%</code> and end with <code>%&gt;</code>. As we look at more modern and advanced ways of working with JSP in future, this is a rule that will be broken but, for now, it&#8217;s okay if you take this as gospel.</p><p>The first thing we need to do is provide some information about the page. This is done with a <strong>page directive</strong>. Directives are a type of JSP tag that contain various settings and other types of configuration information. Directives have an <code>@</code> sign following their opening <code>&lt;%</code>. Here&#8217;s our page directive:</p><pre><code>&lt;%@ page import=&quot;java.util.*,com.sitepoint.*,uk.co.anyware.html.*&quot; %&gt;</code></pre><p>The most common use for a page directive is to import Java packages that will be used by the Java code in the JSP file. In this case, we&#8217;ve indicated that we need classes from <code>java.util</code>, <code>com.sitepoint</code>, and <code>uk.co.anyware.html</code>. These same packages were imported by our to-do list servlet (the code for which you might like to have nearby for comparison).</p><p>We can then proceed to write our page much as we would any (X)HTML file:</p><pre><code>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt; &nbsp; &nbsp;<br />
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt; &nbsp; &nbsp;<br />
&lt;head&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;title&gt;To-Do List&lt;/title&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;meta http-equiv=&quot;content-type&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;content=&quot;text/html; charset=iso-8859-1&quot; /&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;href=&quot;&lt;%= request.getContextPath() %&gt;/styles.css&quot; /&gt; &nbsp; &nbsp;<br />
&lt;/head&gt;</code></pre><p>Look closely, and you&#8217;ll see another JSP tag in there: <code>&lt;%= request.getContextPath() %&gt;</code>. This is what we call an <strong>expression</strong>, as indicated by the <code>=</code> sign following the opening <code>&lt;%</code> in the tag. Expressions are used to output the values of Java code; in this case, we&#8217;re outputting the value returned by the <code>getContextPath()</code> method of the <code>request</code> object &#8212; the root directory of our web application, which the browser needs to locate the <code>styles.css</code> file.</p><p>Yes, JSP code, just like servlet code, has access to the browser&#8217;s request through a variable called <code>request</code>. There is also a <code>response</code> variable for the browser&#8217;s response. Both of these variables are called implicit objects &#8212; they&#8217;re created implicitly for you.</p><p>Other implicit objects include <code>out</code>, an object that works just like the <code>PrintWriter</code> that is used in a servlet to send output to the browser, <code>session</code>, an object for storing values over the course of a particular user&#8217;s visit to your site, and <code>application</code>, an object for storing values for use throughout your application.</p><p>Now, just as our servlet relied on a <code>ToDoList</code> object to do a lot of the work of the application, so will our JSP file. We need to declare this object, and for this we need another JSP tag: a <strong>declaration</strong>.</p><pre><code>&lt;%! &nbsp; &nbsp;<br />
private ToDoList toDoList; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
public void jspInit() { &nbsp; &nbsp;<br />
 &nbsp;toDoList = new ToDoList(getInitParameter(&quot;jdbcDriver&quot;), &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;getInitParameter(&quot;jdbcConnectionString&quot;)); &nbsp; &nbsp;<br />
} &nbsp; &nbsp;<br />
%&gt;</code></pre><p>As you can see, declarations are indicated by an exclamation mark (<code>!</code>) following the opening <code>&lt;%</code>, and contain Java property and method declarations just like those you&#8217;d find in a Java class.</p><p>In this case, we&#8217;ve declared a <code>ToDoList</code> object called <code>toDoList</code>, and we&#8217;ve written a method named <code>jspInit()</code> that creates this object from initialization parameters, just as we did in our servlet&#8217;s <code>init()</code> method. While <code>init()</code> is a special method for servlets that is called by the server before a servlet is used for the first time, <code>jspInit()</code> is a special method that is called automatically to initialize JSP files.</p><p>Next up is the code that will process form submissions in this page. You&#8217;ll remember from our servlet that the page will contain two forms: one for adding items to the to-do list, and one for deleting them. The code for processing these submissions will be identical in our JSP, except that it goes inside yet another type of JSP tag: a <strong>scriptlet</strong>.</p><pre><code>&lt;% &nbsp; &nbsp;<br />
String newToDo = request.getParameter(&quot;newtodo&quot;); &nbsp; &nbsp;<br />
if (newToDo != null) { &nbsp; &nbsp;<br />
 &nbsp;toDoList.addItem(newToDo); &nbsp; &nbsp;<br />
 &nbsp;response.sendRedirect(request.getRequestURI()); &nbsp; &nbsp;<br />
 &nbsp;return; &nbsp; &nbsp;<br />
} &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
String deleteid = request.getParameter(&quot;deleteid&quot;); &nbsp; &nbsp;<br />
if (deleteid != null) { &nbsp; &nbsp;<br />
 &nbsp;try { &nbsp; &nbsp;<br />
 &nbsp; &nbsp;toDoList.deleteItem(Integer.parseInt(deleteid)); &nbsp; &nbsp;<br />
 &nbsp; &nbsp;<br />
 &nbsp; &nbsp;response.sendRedirect(request.getRequestURI()); &nbsp; &nbsp;<br />
 &nbsp; &nbsp;return; &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp;<br />
 &nbsp;catch (NumberFormatException e) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp;throw new ServletException(&quot;Bad deleteid value submitted.&quot;, e); &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp;<br />
} &nbsp; &nbsp;<br />
%&gt;</code></pre><p>When JSP was first conceived, scriptlets were expected to be the most common JSP tag type, so they are indicated with simple <code>&lt;%</code> and <code>%&gt;</code> delimiters &#8212; no special character inside the start of the tag. The Java code inside a scriptlet is executed every time the page is requested.</p><p>With the form processing taken care of, all that&#8217;s left is to produce the forms themselves. First up, we have our to-do list, which displays the current to-do items and allows the user to delete them:</p><pre><code>&lt;body&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp;Iterator toDoItems = toDoList.getToDoItems(); &nbsp; &nbsp;<br />
 &nbsp;if (toDoItems.hasNext()) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp;%&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;form action=&quot;&lt;%= request.getRequestURI() %&gt;&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;&lt;%= Math.max(2, toDoList.getItemCount()) %&gt;&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;while (toDoItems.hasNext()) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ToDoItem toDoItem = (ToDoItem) toDoItems.next(); &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;%&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;option value=&quot;&lt;%= toDoItem.getId() %&gt;&quot;&gt;&lt;%= HTMLEscaper.escape(toDoItem.toString()) %&gt;&lt;/option&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;%&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;/select&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Delete Selected Item&quot; /&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;/form&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp;<br />
 &nbsp;%&gt;</code></pre><p>Looks like a bit of a mess, doesn&#8217;t it? What we have here is a mixture of HTML code, JSP scriptlets, and JSP expressions. Let&#8217;s break it down.</p><pre><code> &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp;Iterator toDoItems = toDoList.getToDoItems(); &nbsp; &nbsp;<br />
 &nbsp;if (toDoItems.hasNext()) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp;%&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;... &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp;<br />
 &nbsp;%&gt;</code></pre><p>The first scriptlet gets an <code>Iterator</code> object containing the items in the to-do list. Our servlet did the exact same thing. Since we don&#8217;t need to display the to-do list if it doesn&#8217;t contain any items, we use an <code>if</code> statement to check if it does using the <code>Iterator</code>&#8216;s <code>hasNext()</code> method.</p><p>All of the code for the form then goes inside this <code>if</code> statement. The closing brace of the <code>if</code> statement is in the last scriptlet of the page. As you can see, the Java code inside a scriptlet doesn&#8217;t need to be self-contained; you can think of the HTML code between your JSP tags as instructions to output that HTML code, with the scriptlets providing the logic for when and how that HTML should appear.</p><p>In the form, we use JSP expressions to output required values in our <code>&lt;form&gt;</code> and <code>&lt;select&gt;</code> tags:</p><pre><code> &nbsp; &nbsp;&lt;form action=&quot;&lt;%= request.getRequestURI() %&gt;&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;&lt;%= Math.max(2, toDoList.getItemCount()) %&gt;&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;... &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;/select&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Delete Selected Item&quot; /&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;/form&gt;</code></pre><p>Finally, we need to output an <code>&lt;option&gt;</code> tag for each item in our to-do list. The code is once again remarkably similar to our servlet, as we use a <code>while</code> loop to do the job:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;while (toDoItems.hasNext()) { &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ToDoItem toDoItem = (ToDoItem) toDoItems.next(); &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;%&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;option value=&quot;&lt;%= toDoItem.getId() %&gt;&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;%= HTMLEscaper.escape(toDoItem.toString()) %&gt;&lt;/option&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;%&gt;</code></pre><p>It&#8217;s a mess at first glance, but if you look carefully (or better yet, if you have an editor that highlights JSP tags in a different colour), you can see how the logic is in JSP scriptlets, and the rest of the code is just HTML with JSP expressions to output dynamic values.</p><p>The form for adding new to-do list items is a piece of cake compared to the first one:</p><pre><code> &nbsp;&lt;form action=&quot;&lt;%= request.getRequestURI() %&gt;&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;input type=&quot;text&quot; name=&quot;newtodo&quot; /&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Add New Item&quot; /&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;/form&gt; &nbsp; &nbsp;<br />
&lt;/body&gt; &amp;nbs&amp;np; &nbsp;<br />
&lt;/html&gt;</code></pre><p>That takes care of our JSP file! The only thing left is to update the <code>web.xml</code> configuration file for our application to make the initialization parameters (<code>jdbcDriver</code> and <code>jdbcConnectionString</code>) available to our JSP file:</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &nbsp; &nbsp;<br />
&lt;web-app xmlns=&quot;http://java.sun.com/xml/ns/j2ee&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd&quot; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;version=&quot;2.4&quot;&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;display-name&gt;ToDoJSP&lt;/display-name&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;servlet&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;servlet-name&gt;toDo&lt;/servlet-name&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;jsp-file&gt;/todo.jsp&lt;/jsp-file&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;init-param&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;description&gt;The JDBC driver class.&lt;/description&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;param-name&gt;jdbcDriver&lt;/param-name&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;param-value&gt;com.mysql.jdbc.Driver&lt;/param-value&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;/init-param&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;init-param&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;description&gt;The JDBC connection string.&lt;/description&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;param-name&gt;jdbcConnectionString&lt;/param-name&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;param-value&gt;jdbc:mysql://localhost/todo?user=root&amp;amp;password=password&lt;/param-value&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;/init-param&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;/servlet&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;servlet-mapping&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;servlet-name&gt;toDo&lt;/servlet-name&gt; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;url-pattern&gt;/todo.jsp&lt;/url-pattern&gt; &nbsp; &nbsp;<br />
 &nbsp;&lt;/servlet-mapping&gt; &nbsp; &nbsp;<br />
&lt;/web-app&gt;</code></pre><p>There are two significant changes from the <code>web.xml</code> file we used with our servlet:</p><ul><li>Instead of using a <code>&lt;servlet-class&gt;</code> tag to indicate the servlet for which we are providing parameters, we have a <code>&lt;jsp-file&gt;</code> tag to indicate the JSP file.</li><li>The <code>&lt;url-pattern&gt;</code> tag in the <code>&lt;servlet-mapping&gt;</code> points to the JSP file as well.</li></ul><p>With those changes made, you&#8217;re ready to bundle up the application and deploy it on your server. Unlike servlets, you don&#8217;t need to compile JSP files in advance &#8212; the server will convert them to servlets and compile them for you on the fly. You do, however, still need to compile the classes that your JSP uses (<code>ToDoList</code>, <code>ToDoItem</code>, <code>HTMLEscaper</code>).</p><p>As with the servlet, use the <code>jar</code> command-prompt utility to create a <code>WAR</code> file containing your application:</p><pre><code>jar cvf ToDoJSP.war .</code></pre><p>Drop this file in Tomcat&#8217;s <code>webapps</code> directory to deploy it (or deploy it using whatever Java-compatible server you prefer), and edit the deployed <code>web.xml</code> file to match your database configuration.</p><p>Then load <code>http://localhost:8080/ToDoJSP/todo.jsp</code> to try out your application. You should see your familiar to-do list interface, this time generated by a JSP.</p><p>Here&#8217;s the finished WAR file, including source code, for you to experiment with:</p><p><a
class="sublink" href="http://www.sitepoint.com/examples/jgrind/ToDoJSP.war">Download the code</a>. (250KB)</p><p>Now, you&#8217;ll recall that the whole point of JSP was to overcome the messiness of mixing HTML code into the Java code of a servlet. If you&#8217;ve looked at the code for our new JSP file, I&#8217;d forgive you for being skeptical about whether we&#8217;ve achieved our aim.</p><p>Our to-do list JSP file is written with what I call &quot;old school JSP&quot;. It&#8217;s pure JSP, as it was originally conceived years ago, with none of the modern amenities. In the rest of this article, I&#8217;ll show you how to modify it using current and advanced features of JSP. First of all, we&#8217;ll bring servlets back into the picture (but in a much simpler form!), then we&#8217;ll look at standards like JavaBeans, the Java Standard Tag Library, and JSP Expression Language.</p><p>Generally speaking, our goal will be to get rid of all the Java code in the JSP file, either by replacing it with more designer-friendly tag constructs, or by moving it into external, independent Java classes. By the time we&#8217;re done, you&#8217;ll know how to write a JSP file so that it is barely distinguishable from a standard HTML file.</p><p><div
class="article-cms-pagebreak"></div></p><h5>Kickin&#8217; It MVC-Style</h5><p>Still following along? I&#8217;ve already shown you how to convert a to-do list servlet into a JSP. Unfortunately, what we got wasn&#8217;t much better in terms of readable code &#8212; Java code embedded in an HTML document isn&#8217;t a whole lot more readable than HTML code embedded in a Java class.</p><p>What to do? Well, so far we have two tools at our disposal: servlets and JSPs. Servlets are great for containing Java code, JSPs are great for containing HTML code. The answer is to split our application apart so that the Java code goes into servlets, and the HTML code goes into JSPs.</p><p>A standard approach for this called <a
class="sublink" href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html#1078527">Model 2 Architecture</a> has been around for a long time, but lately it has become known by the more descriptive name: <strong>Model-View-Controller</strong> (MVC).</p><div
class="vertical">GA_googleFillSlot(&#8220;Articles_6_300x250&#8243;);</div><p>The idea is to break the application into three parts:</p><ul><li>The <strong>model</strong>: a collection of Java classes that perform the actual work of the application (often called the <strong>business logic</strong>), independant of the web interface.</li><li>The <strong>view</strong>, a collection of JSPs, or some other technology, that produces the actual web pages that the users see.</li><li>The <strong>controller</strong>, one or more servlets that process browser requests by telling the model what to do and then handing over to the view to respond.</li></ul><p>Now I could go on and on about this all day, but it&#8217;s easier to see through an example, so let&#8217;s get to work on modifying our to-do list application.</p><p>The model is usually the best place to start, as you can usually write it without worrying much about the web interface. In the case of our to-do list application, we already <em>have</em> our model: it&#8217;s made up of the classes <code>ToDoList</code> and <code>ToDoItem</code>. These two classes do all the work of managing the to-do list.</p><p>While we&#8217;re looking at these classes, let&#8217;s make one minor tweak to the <code>getToDoItems</code> method: we&#8217;ll make it return a <code>List</code> rather than an <code>Iterator</code>. This allows for a bit more flexibility in how the to-do list items may be used when they are retrieved through this method.</p><pre><code> &nbsp;public List getToDoItems() { &nbsp; &nbsp; <br />
 &nbsp; &nbsp;refreshList(); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;return (List)list.clone(); &nbsp; &nbsp; <br />
 &nbsp;}</code></pre><p>Next, let&#8217;s work on our controller. We know we&#8217;ll have three different kinds of requests coming from the browser: simple requests to view the to-do list, form posts for adding new items to the list, and form posts for deleting existing items from the list.</p><p>We now have a choice: do we write one servlet that knows how to handle all these different request types, or do we write three simple, specialized servlets each of which knows how to handle one type of request? There&#8217;s no right answer, as there are advantages to each approach, but let&#8217;s try to keep our classes simple and go for multiple servlets.</p><p>We&#8217;ll start with <code>ToDoServlet</code>, which will handle requests to view the to-do list. The first thing this servlet needs to do is set up the model &#8212; an instance of <code>ToDoList</code>. Back when we first looked at servlets, we did this with the <code>init()</code> method of the servlet, which stored the <code>ToDoList</code> in an instance variable of the servlet.</p><p>This time, that won&#8217;t quite do the trick, because we want all three of our servlets to be able to access the model. We can&#8217;t create the <code>ToDoList</code> in one servlet&#8217;s initialization procedure because one of the other servlets might need it first, and we can&#8217;t store it in an instance variable because the other servlets wouldn&#8217;t be able to see it at all. What we need is a way to create the model when the web application first starts up, and a place to store it where any servlet can get at it.</p><p>To perform initialization tasks for the entire application, we must use a <code>ServletContextListener</code>. Rather than a class to extend, this is an interface, which any class can implement. Since our &quot;main&quot; servlet is a good place to do this stuff, we&#8217;ll make it implement that interface:</p><pre><code>public class ToDoServlet extends HttpServlet &nbsp; &nbsp; <br />
 &nbsp; &nbsp;implements ServletContextListener {</code></pre><p>When a class implements <code>ServletContextListener</code>, it must contain two methods: <code>contextInitialized</code>, which performs application initialization tasks, and <code>contextDestroyed</code>, which performs application cleanup:</p><pre><code> &nbsp;public void contextInitialized(ServletContextEvent sce) { &nbsp; &nbsp; <br />
 &nbsp; &nbsp;ServletContext sc = sce.getServletContext(); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;sc.setAttribute(&quot;toDoList&quot;, &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;new ToDoList(sc.getInitParameter(&quot;jdbcDriver&quot;), &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sc.getInitParameter(&quot;jdbcConnectionString&quot;))); &nbsp; &nbsp; <br />
 &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
 &nbsp;public void contextDestroyed(ServletContextEvent sce) { &nbsp; &nbsp; <br />
 &nbsp;}</code></pre><p>All the action here is in <code>contextInitialized</code>, since we don&#8217;t need to do anything special when the application shuts down. As you can see, when they&#8217;re called, both of these methods receive a <code>ServletContextEvent</code> from which we can get a reference to the <code>ServletContext</code>. The <code>ServletContext</code> is an object that represents the web application as a whole &#8212; it&#8217;s the <em>context</em> in which the <em>servlet</em> is running. All servlets and JSPs have access to the <code>ServletContext</code>; therefore, it provides the perfect place to store our model!</p><p>The <code>ServletContext</code> lets you set and get attributes, which are simply application-wide values associated with string labels. We&#8217;ll store our model, a new <code>ToDoList</code> object, in an attribute labelled <code>&quot;toDoList&quot;</code>.</p><p>Before we move on, have a close look at the code that creates the <code>ToDoList</code>:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;new ToDoList(sc.getInitParameter(&quot;jdbcDriver&quot;), &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sc.getInitParameter(&quot;jdbcConnectionString&quot;)));</code></pre><p>As we&#8217;ve done previously, we&#8217;re getting the JDBC driver and connection string values required by this class from initialization parameters, but because we&#8217;re performing initialization for our entire application, the initialization parameters for the <code>ToDoServlet</code> are not yet available! That&#8217;s why we&#8217;re calling the <code>getInitParameter</code> method of the <code>ServletContext</code> object, not the servlet itself, as we&#8217;re used to doing. These are known as <strong>context initialization parameters</strong>, as opposed to servlet initialization parameters.</p><p>Now we&#8217;ve got a <code>ServletContextListener</code> that&#8217;s ready to initialize our application, as long as it gets the context initialization parameters it needs. As you may have guessed, we need to add some things into our <code>web.xml</code> file to make this work:</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; &nbsp; &nbsp; <br />
&lt;web-app xmlns=&quot;http://java.sun.com/xml/ns/j2ee&quot; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd&quot; version=&quot;2.4&quot;&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;display-name&gt;ToDoMVC&lt;/display-name&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;listener&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;listener-class&gt;com.sitepoint.ToDoServlet&lt;/listener-class&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/listener&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;context-param&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;description&gt;The JDBC driver class.&lt;/description&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;param-name&gt;jdbcDriver&lt;/param-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;param-value&gt;com.mysql.jdbc.Driver&lt;/param-value&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/context-param&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;context-param&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;description&gt;The JDBC connection string.&lt;/description&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;param-name&gt;jdbcConnectionString&lt;/param-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;param-value&gt;jdbc:mysql://localhost/todo?user=root&amp;amp;password=password&lt;/param-value&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/context-param&gt; &nbsp; &nbsp; <br />
&lt;/web-app&gt;</code></pre><p>The <code>&lt;listener&gt;</code> tag lets the application know about the context listener we&#8217;ve provided, while the <code>&lt;context-param&gt;</code> tags set up our application-wide context initialization parameters.</p><p>Now, before we got caught up in all this application initialization stuff, I seem to remember that we were writing a servlet. So let&#8217;s take a look at the <code>doGet</code> and <code>doPost</code> methods:</p><pre><code> &nbsp;public void doGet(HttpServletRequest request, HttpServletResponse response) &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;throws ServletException, IOException { &nbsp; &nbsp; <br />
 &nbsp; &nbsp;ToDoList toDoList = (ToDoList)getServletContext().getAttribute(&quot;toDoList&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;List toDoItems = toDoList.getToDoItems(); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;request.setAttribute(&quot;toDoItems&quot;, toDoItems); &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
 &nbsp; &nbsp;RequestDispatcher view = request.getRequestDispatcher(&quot;/todo.jsp&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;view.forward(request, response); &nbsp; &nbsp; <br />
 &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
 &nbsp;public void doPost(HttpServletRequest request, HttpServletResponse response) &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;throws ServletException, IOException { &nbsp; &nbsp; <br />
 &nbsp; &nbsp;doGet(request, response); &nbsp; &nbsp; <br />
 &nbsp;}</code></pre><p>Look at that! A servlet with no embedded HTML code! How is such a thing possible? Well remember, this servlet is merely the controller in our MVC design: after getting things done with the model, it hands the request to the view to display the actual web page. Looking closely at the <code>doGet</code> method, you&#8217;ll see that this is exactly what it does:</p><pre><code> &nbsp; &nbsp;ToDoList toDoList = (ToDoList)getServletContext().getAttribute(&quot;toDoList&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;List toDoItems = toDoList.getToDoItems(); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;request.setAttribute(&quot;toDoItems&quot;, toDoItems);</code></pre><p>Here, it fetches the model (the <code>ToDoList</code> stored in a servlet context attribute), uses it to get a <code>List</code> of the to-do list items, and then stores that <code>List</code> someplace where the view will be able to find it &#8212; namely, in the <code>request</code> object. It turns out that the <code>request</code> object supports attributes too, and this is the perfect way to pass values to the view that it will need to build the page.</p><p>With the heavy lifting done, we&#8217;re ready to pass the request to the view (in this case, a JSP called <code>todo.jsp</code> in the root of our application):</p><pre><code> &nbsp; &nbsp;RequestDispatcher view = request.getRequestDispatcher(&quot;/todo.jsp&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;view.forward(request, response);</code></pre><p>At a glance, this may seem a bit confusing, but this is the formula we will always use to forward requests from a servlet to a JSP. We get a <code>RequestDispatcher</code> object for the location we want to forward to (in this case, <code>&quot;/todo.jsp&quot;</code> specifies the <code>todo.jsp</code> file in the root of the application), then we call its <code>forward</code> method, passing it the <code>request</code> and <code>response</code> objects it will need to do the job.</p><p>Okay, so I&#8217;ve had to yammer on a bit to explain all the new stuff that&#8217;s going on in this servlet, but if you step back and look at the code, you&#8217;ll find it&#8217;s actually pretty neat and tidy. And since they aren&#8217;t burdened with all the application setup stuff, our other two servlets are even neater and tidier!</p><pre><code>package com.sitepoint; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
import javax.servlet.*; &nbsp; &nbsp; <br />
import javax.servlet.http.*; &nbsp; &nbsp; <br />
import java.io.*; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
public class AddToDoServlet extends HttpServlet { &nbsp; &nbsp; <br />
 &nbsp;public void doPost(HttpServletRequest request, HttpServletResponse response) &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;throws ServletException, IOException { &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
 &nbsp; &nbsp;String newToDo = request.getParameter(&quot;newtodo&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;if (newToDo != null) { &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;ToDoList toDoList = (ToDoList)getServletContext().getAttribute(&quot;toDoList&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;toDoList.addItem(newToDo); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp;response.sendRedirect(&quot;index.html&quot;); &nbsp; &nbsp; <br />
 &nbsp;} &nbsp; &nbsp; <br />
}</code></pre><pre><code>package com.sitepoint; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
import javax.servlet.*; &nbsp; &nbsp; <br />
import javax.servlet.http.*; &nbsp; &nbsp; <br />
import java.io.*; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; <br />
public class DeleteToDoServlet extends HttpServlet { &nbsp; &nbsp; <br />
 &nbsp;public void doPost(HttpServletRequest request, HttpServletResponse response) &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;throws ServletException, IOException { &nbsp; &nbsp; <br />
 &nbsp; &nbsp;String deleteid = request.getParameter(&quot;deleteid&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp;if (deleteid != null) { &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;try { &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;ToDoList toDoList = (ToDoList)getServletContext().getAttribute(&quot;toDoList&quot;); &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;toDoList.deleteItem(Integer.parseInt(deleteid)); &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;catch (NumberFormatException e) { &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;throw new ServletException(&quot;Bad deleteid value submitted.&quot;, e); &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp;response.sendRedirect(&quot;index.html&quot;); &nbsp; &nbsp; <br />
 &nbsp;} &nbsp; &nbsp; <br />
}</code></pre><p>You might be surprised to note that these servlets don&#8217;t actually forward to a JSP after they&#8217;ve done their work. Instead, they redirect the browser to <code>&quot;index.html&quot;</code>, which we&#8217;ll shortly configure to point to our main <code>ToDoServlet</code>.</p><p>Because we want to show the user the updated to-do list after adding or deleting an item, we <em>could</em> forward the request to <code>/todo.jsp</code>, but, as I explained previously, this would lead to problems if the user were to refresh the browser afterward. The browser would re-submit the item addition/deletion request, causing errors or duplicate list entries. Redirecting instead of forwarding gets around this by having the browser make a new request, which is safe to repeat, after it has submitted the form.</p><p>To polish off our servlets, we need to assign URLs to each of them in our <code>web.xml</code> file. We&#8217;ll use <code>/index.html</code> for the <code>ToDoServlet</code>, since we want it to come up by default when a user loads our application directory. <code>AddToDoServlet</code> and <code>DeleteToDoServlet</code> will get <code>/AddItem.do</code> and <code>/DeleteItem.do</code> respectively, following the convention of giving &quot;action&quot; URLs <code>.do</code> extensions in Java web apps.</p><pre><code> &nbsp;&lt;servlet&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;todoservlet&lt;/servlet-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-class&gt;com.sitepoint.ToDoServlet&lt;/servlet-class&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/servlet&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;servlet-mapping&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;todoservlet&lt;/servlet-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;url-pattern&gt;/index.html&lt;/url-pattern&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/servlet-mapping&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;servlet&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;addtodoservlet&lt;/servlet-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-class&gt;com.sitepoint.AddToDoServlet&lt;/servlet-class&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/servlet&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;servlet-mapping&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;addtodoservlet&lt;/servlet-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;url-pattern&gt;/AddItem.do&lt;/url-pattern&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/servlet-mapping&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;servlet&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;deletetodoservlet&lt;/servlet-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-class&gt;com.sitepoint.DeleteToDoServlet&lt;/servlet-class&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/servlet&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;servlet-mapping&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;servlet-name&gt;deletetodoservlet&lt;/servlet-name&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;url-pattern&gt;/DeleteItem.do&lt;/url-pattern&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/servlet-mapping&gt;</code></pre><p>With our servlets done, all that&#8217;s left is to build the view for our application. For this example, all we need is a single JSP file: <code>todo.jsp</code>.</p><p>Now that we&#8217;ve pulled all our initialization and request processing code out into servlets, our JSP file looks a lot more reasonable:</p><pre><code>&lt;%@ page import=&quot;java.util.*,com.sitepoint.*,uk.co.anyware.html.*&quot; %&gt; &nbsp; &nbsp; <br />
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt; &nbsp; &nbsp; <br />
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt; &nbsp; &nbsp; <br />
&lt;head&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;title&gt;To-Do List&lt;/title&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=iso-8859-1&quot; /&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&lt;%= request.getContextPath() %&gt;/styles.css&quot; /&gt; &nbsp; &nbsp; <br />
&lt;/head&gt; &nbsp; &nbsp; <br />
&lt;body&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;% &nbsp; &nbsp; <br />
 &nbsp;List toDoItems = (List)request.getAttribute(&quot;toDoItems&quot;); &nbsp; &nbsp; <br />
 &nbsp;Iterator it = toDoItems.iterator(); &nbsp; &nbsp; <br />
 &nbsp;if (it.hasNext()) { &nbsp; &nbsp; <br />
 &nbsp; &nbsp;%&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;form action=&quot;DeleteItem.do&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;&lt;%= Math.max(2, toDoItems.size()) %&gt;&quot;&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;while (it.hasNext()) { &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ToDoItem toDoItem = (ToDoItem) it.next(); &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;%&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;option value=&quot;&lt;%= toDoItem.getId() %&gt;&quot;&gt;&lt;%= HTMLEscaper.escape(toDoItem.toString()) %&gt;&lt;/option&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp; &nbsp;%&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;/select&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Delete Selected Item&quot; /&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;/form&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;% &nbsp; &nbsp; <br />
 &nbsp;} &nbsp; &nbsp; <br />
 &nbsp;%&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;form action=&quot;AddItem.do&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;input type=&quot;text&quot; name=&quot;newtodo&quot; /&gt; &nbsp; &nbsp; <br />
 &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Add New Item&quot; /&gt; &nbsp; &nbsp; <br />
 &nbsp;&lt;/form&gt; &nbsp; &nbsp; <br />
&lt;/body&gt; &nbsp; &nbsp; <br />
&lt;/html&gt;</code></pre><p>If you understood the original JSP we built, this one should be a piece of cake! The scriptlet code simply pulls the <code>List</code> out of the <code>request</code>&#8216;s <code>&quot;toDoItems&quot;</code> attribute to produce the list of to-do items, and our two forms now submit to the <code>.do</code> URLs we assigned to the corresponding servlets. Beyond those changes, it&#8217;s the same old JSP with a lot less Java code.</p><p>And there we have it: an MVC Java web application! Here&#8217;s the directory structure:</p><pre><code>/todo.jsp &nbsp; &nbsp; <br />
/styles.css &nbsp; &nbsp; <br />
/WEB-INF/web.xml &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/AddToDoServlet.class &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/AddToDoServlet.java &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.class &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.java &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoItem.class &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoItem.java &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoList.class &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoList.java &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.class &nbsp; &nbsp; <br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.java &nbsp; &nbsp; <br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.class &nbsp; &nbsp; <br />
/WEB-INF/classes/uk/co/anyware/html/HTMLEscaper.java &nbsp; &nbsp; <br />
/WEB-INF/lib/mysql-connector-java-version-bin.jar</code></pre><p><a
class="sublink" href="http://www.sitepoint.com/examples/jgrind/ToDoMVC.war">Download the code</a>. (250KB)</p><p>This application is starting to look pretty darned good, even if I do say so myself. Its major weakness continues to be the Java scriptlet code in the JSP. We&#8217;ve gotten rid of most of the Java code from this file, but what&#8217;s in there would still be pretty confusing for a web designer. The next step in the grand tour will be to look at some of the features of modern JSP that allow us to dispense with these scriptlets in favour of tags and expressions.</p><p><div
class="article-cms-pagebreak"></div></p><h5>A Crash Course in Java-less JSP</h5><p>It&#8217;s time to take the Java out of JavaServer Pages.</p><p>We&#8217;ve split our to-do list web application into three parts: the <strong>model</strong>, classes that manage the data at the heart of our application; the <strong>controller</strong>, servlets that process incoming requests and then send display values to the view; and the <strong>view</strong>, JSP files that generate web pages from those display values.</p><p>While this approach generally did a good job of separating the Java application logic from the HTML user interface code, it still left us with some Java code in our JSP file(s). This code was needed to grab the values supplied by the controller and massage them into our HTML interface. We&#8217;ll call this <strong>display logic</strong>.</p><p>Now, I&#8217;ll show you how to get rid of the Java code ftrom your JSP files, and implement that display logic with a simpler and more powerful alternative.</p><p>Let&#8217;s start by reviewing just what the Java display logic in our example&#8217;s JSP file does. First, it gets the list of items supplied by the controller:</p><pre><code> &nbsp;List toDoItems = (List)request.getAttribute(&quot;toDoItems&quot;); &nbsp; &nbsp; &nbsp;<br />
 &nbsp;Iterator it = toDoItems.iterator();</code></pre><p>Then, it checks if there are any items in the list:</p><pre><code> &nbsp;if (it.hasNext()) {</code></pre><p>To keep the HTML <code>&lt;select&gt;</code> displaying as a standard list of the correct size and not a drop-down list, we use display logic to set the <code>size</code> attribute:</p><pre><code>&lt;select name=&quot;deleteid&quot; size=&quot;&lt;%= Math.max(2, toDoItems.size()) %&gt;&quot;&gt;</code></pre><p>Display logic is then used to process each of the to-do list items in turn:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;while (it.hasNext()) { &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ToDoItem toDoItem = (ToDoItem) it.next();</code></pre><p>Finally, display logic is used to extract the ID and text content of each to-do list item, and to escape any special characters that may appear in the text:</p><pre><code>&lt;option value=&quot;&lt;%= toDoItem.getId() %&gt;&quot;&gt;&lt;%= HTMLEscaper.escape(toDoItem.toString()) %&gt;&lt;/option&gt;</code></pre><p>Given that this is a relatively simple application, that&#8217;s quite a bit of Java code still lingering in a file which will ostensibly be created and edited by web designers &#8212; people who typically aren&#8217;t well versed in the finer points of the Java language and APIs.</p><p>So, what to do? Obviously this display logic is required, but we need a better way of implementing it than including Java code in our page.</p><p>There are actually quite a few alternatives that have been written by various groups floating around the Web. From simple <strong>JSP tag libraries</strong> (collections of custom tags that you can mix with your HTML to implement your display logic) to complete JSP replacements, the galaxy of options can be humbling. The solution proposed by the JSP 2.0 standard is a combination of a tag library called the <a
class="sublink" href="http://java.sun.com/products/jsp/jstl/"><strong>JSP Standard Tag Library</strong></a> (JSTL) and a syntax for accessing Java values without Java code called <a
class="sublink" href="http://java.sun.com/products/jsp/syntax/2.0/syntaxref207.html"><strong>JSP Expression Language</strong></a> (EL).</p><div
class="vertical">GA_googleFillSlot(&#8220;Articles_6_300x250&#8243;);</div><p>While EL is built into JSP 2.0, and therefore is available automatically in your JSP files, JSTL is a separate library that must specifically be included in your web application before you can use it. In Tomcat 5.x, you can grab the JSTL 1.1 library files from the <code>jsp-examples</code> web application included with the server. Simply go into the <code>webapps/jsp-examples/WEB-INF/lib</code> subdirectory of the server installation, grab <code>jstl.jar</code> and <code>standard.jar</code>, and copy them into the <code>WEB-INF/lib</code> subdirectory of the to-do list web app.</p><p>You can now use JSTL tags in your JSP files. Let&#8217;s modify the <code>todo.jsp</code> file to produce the same to-do list user interface without any Java scripting.</p><p>First, we need to declare our intention to use JSTL tags in the file. JSTL is actually divided into a number of sub-libraries, so you don&#8217;t have to load the entire library if you just want to use a couple of its tags. The most commonly-used tags are found in the Core sub-library, which we can load using this <code>@taglib</code> directive immediately following the <code>@page</code> directive at the top of the file:</p><pre><code>&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;</code></pre><p>Here&#8217;s the first piece of Java code in our <code>todo.jsp</code> file. We use it to get the context path (the root) of our web application, so that we can locate the CSS file to be used by the page:</p><pre><code> &nbsp;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&lt;%= request.getContextPath() %&gt;/styles.css&quot; /&gt;</code></pre><p>For example, if our web application is installed in <code>http://www.example.com/todo</code>, then the context path for the application is <code>/todo</code> and therefore our style sheet will be correctly located at <code>/todo/styles.css</code>.</p><p>The <code>&lt;c:url&gt;</code> tag of the JSTL Core library lets us produce URLs relative to the context path automatically. Here&#8217;s how the adjusted code looks:</p><pre><code> &nbsp;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&lt;c:url value=&quot;/styles.css&quot;/&gt;&quot; /&gt;</code></pre><p>Yes, you read right. That&#8217;s a JSTL tag within the attribute value of an HTML tag. XML sticklers may grit their teeth at this, but JSP was never meant to be valid XML. For XHTML standards compliance, you just need to make sure that the code <em>generates</em> valid XML, which this will.</p><p>The next chunk of Java code in our <code>todo.jsp</code> file is a little more challenging. It grabs the <code>List</code> object that the controller stored in a request object attribute called <code>toDoItems</code>, and checks if it contains any to-do items:</p><pre><code> &nbsp;&lt;% &nbsp; &nbsp; &nbsp;<br />
 &nbsp;List toDoItems = (List)request.getAttribute(&quot;toDoItems&quot;); &nbsp; &nbsp; &nbsp;<br />
 &nbsp;Iterator it = toDoItems.iterator(); &nbsp; &nbsp; &nbsp;<br />
 &nbsp;if (it.hasNext()) { &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;%&gt;</code></pre><p>The <code>&lt;c:if&gt;</code> tag lets us test a condition and output the contents of the tag only when that condition is true. The tag looks like this:</p><pre><code> &nbsp;&lt;c:if test=&quot;&lt;i&gt;condition&lt;/i&gt;&quot;&gt;...&lt;/c:if&gt;</code></pre><p>But how do we specify a condition? That&#8217;s where JSP Expression Language (EL) comes in. The <code>test</code> attribue of the <code>&lt;c:if&gt;</code> tag takes an EL expression as the condition to be tested.</p><p>EL was designed specifically to be really, really good at fetching values out of request, session, and application attributes. As a matter of fact, the EL expression that will fetch the <code>toDoItems</code> request attribute is simply this:</p><pre><code>${toDoItems}</code></pre><p>For our purposes, we actually want to go a step further and check how many items are in the <code>toDoItems</code> list. To do this, we need to use an <strong>EL function</strong>, which requires another JSTL sub-library to be added with a <code>@taglib</code> directive at the top of the page:</p><pre><code>&lt;%@ taglib prefix=&quot;fn&quot; uri=&quot;http://java.sun.com/jsp/jstl/functions&quot; %&gt;</code></pre><p>With that done, we can get the number of items in the list with this EL expression:</p><pre><code>${fn:length(toDoItems)}</code></pre><p>And we can determine if the list contains items with this expression:</p><pre><code>${fn:length(toDoItems) &gt; 0}</code></pre><p>We can now write the <code>&lt;c:if&gt;</code> tag to test this condition:</p><pre><code> &nbsp;&lt;c:if test=&quot;${fn:length(toDoItems) &gt; 0}&quot;&gt;...&lt;/c:if&gt;</code></pre><p>Next, we&#8217;ll use JSTL not to replace some Java design logic, but to improve some pure HTML in our <code>todo.jsp</code> file. The form that displays the to-do list items and allows the user to delete them begins with this <code>&lt;form&gt;</code> tag:</p><pre><code> &nbsp; &nbsp;&lt;form action=&quot;DeleteItem.do&quot; method=&quot;post&quot;&gt;&lt;/form&gt;</code></pre><p>This is just fine as long as our JSP is in the root directory of our web application, but if we were to move it into a subdirectory, the <code>action</code> attribute of this tag would no longer point to <code>DeleteItem.do</code> in the root of the application. To ensure this attribute always points to the correct URL, we can use a <code>&lt;c:url&gt;</code> tag just like we used for the style sheet URL above:</p><pre><code> &nbsp; &nbsp;&lt;form action=&quot;&lt;c:url value=&quot;/DeleteItem.do&quot;/&gt;&quot; method=&quot;post&quot;&gt;</code></pre><p>Incidentally, we can make the same change to the second <code>&lt;form&gt;</code> tag on the page, which points to <code>AddItem.do</code>.</p><p>The next piece of Java display logic in <code>todo.jsp</code> is a bit trickier to reproduce with JSTL/EL:</p><pre><code> &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;&lt;%= Math.max(2, toDoItems.size()) %&gt;&quot;&gt;</code></pre><p>There is no JSTL or EL equivalent to Java&#8217;s <code>Math.max</code> method, so to get a <code>&lt;select&gt;</code> list with a <code>size</code> equal to the number of items in <code>toDoItems</code>, but no less than 2, using only standard JSTL/EL features, we would need to implement this logic more verbosely:</p><pre><code> &nbsp; &nbsp; &nbsp;&lt;c:set var=&quot;selectSize&quot; value=&quot;${fn:length(toDoItems)}&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;c:if test=&quot;${selectSize &lt; 2}&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;&lt;c:set var=&quot;selectSize&quot; value=&quot;2&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;/c:if&gt;</code></pre><p>The JSTL <code>&lt;c:set&gt;</code> tag lets us set a variable for use in EL expressions in the rest of the page. In this case, we&#8217;d set it to the number of items in <code>toDoItems</code> (which we&#8217;d again get with the <code>fn:length</code> EL function). We&#8217;d then use a <code>&lt;c:if&gt;</code> to test if the value was less than 2, in which case we&#8217;d use another <code>&lt;c:set&gt;</code> to set the variable to that minimum.</p><p>We could then go ahead and output the value with an expression in our <code>&lt;select&gt;</code> tag&#8217;s <code>size</code> attribute:</p><pre><code> &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;${selectSize}&quot;&gt;</code></pre><p>Yes &#8212; you can use EL expressions in HTML tag attributes too.</p><p>This solution would be pretty messy, though. Wouldn&#8217;t it be nice if we had an EL function that did the same thing as <code>Math.max</code>? As it turns out, extending EL with your own functions is pretty easy.</p><p>First, you need to create a Java class with a public, static method that does what you want your EL function to do. For this project, let&#8217;s create a class called <code>com.sitepoint.jsp.Functions</code> (in <code>com/sitepoint/jsp/Functions.java</code>). The code for this class will be very simple:</p><pre><code>package com.sitepoint.jsp; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;<br />
public class Functions { &nbsp; &nbsp; &nbsp;<br />
 &nbsp;public static int max(int i1, int i2) { &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;return Math.max(i1, i2); &nbsp; &nbsp; &nbsp;<br />
 &nbsp;} &nbsp; &nbsp; &nbsp;<br />
}</code></pre><p>Next, we need to define a custom tag library to set this class&#8217;s <code>max</code> method as a custom EL function. To do this, create an XML file called <code>functions.tld</code> and put it in the <code>WEB-INF</code> directory of the project. Aside from the first tag (which is always the same), most of the code is fairly self-explanatory:</p><pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;iso-8859-1&quot;?&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;taglib xmlns=&quot;http://java.sun.com/xml/ns/j2ee&quot; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd&quot; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;version=&quot;2.0&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;tlib-version&gt;1.0&lt;/tlib-version&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;short-name&gt;Functions&lt;/short-name&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;uri&gt;http://www.sitepoint.com/jsp/taglibs/functions&lt;/uri&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;function&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;name&gt;max&lt;/name&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;function-class&gt;com.sitepoint.jsp.Functions&lt;/function-class&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;function-signature&gt;int max(int, int)&lt;/function-signature&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;/function&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;/taglib&gt;</code></pre><p>What this file does is associate a unique identifier, in the form of a URL (<code>http://www.sitepoint.com/jsp/taglibs/functions</code>), with a library of EL functions. The one function in this library will be called <code>max</code> and will call the <code>max</code> method of the <code>com.sitepoint.jsp.Functions</code> class.</p><p>To use this library in our JSP, we need to add a <code>@taglib</code> directive for it to the top of the page:</p><pre><code>&lt;%@ taglib prefix=&quot;spfn&quot; uri=&quot;http://www.sitepoint.com/jsp/taglibs/functions&quot; %&gt;</code></pre><p>We can now calculate the size attribute of our <code>&lt;select&gt;</code> tag using a single EL expression:</p><pre><code> &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;${spfn:max(2,fn:length(toDoItems))}&quot;&gt;</code></pre><p>Next up in our Java display logic, we have a <code>while</code> loop that iterates through the to-do list items, pulling each out in turn to be processed:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;&lt;% &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;while (it.hasNext()) { &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ToDoItem toDoItem = (ToDoItem) it.next(); &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;%&gt;</code></pre><p>This is almost shamefully simple to do with JSTL&#8217;s <code>&lt;c:forEach&gt;</code> tag:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp;&lt;c:forEach var=&quot;toDoItem&quot; items=&quot;${toDoItems}&quot;&gt;</code></pre><p>Again, we&#8217;re using the simple EL expression <code>${toDoItems}</code> to access the request attribute supplied by the controller. This tag will output its contents once for each item in the list, assigning that item to the EL variable name specified by the <code>var</code> attribute (<code>toDoItem</code>, in this case).</p><p>Our final tidbits of Java display logic are used to output the ID and text of the <code>ToDoItem</code> objects contained in the list:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;option value=&quot;&lt;%= toDoItem.getId() %&gt;&quot;&gt;&lt;%= HTMLEscaper.escape(toDoItem.toString()) %&gt;&lt;/option&gt;</code></pre><p>Here&#8217;s where EL really comes into its own. In addition to simplifying drastically the process of pulling values out of request attributes, it&#8217;s also really good at pulling values out of those values! Let me show you what I mean&#8230;</p><p>Although I didn&#8217;t mention it at the time, the <code>ToDoItem</code> class was designed according to the <a
class="sublink" href="http://java.sun.com/products/javabeans/"><strong>JavaBeans standard</strong></a>. Though it has some more complicated sections, the JavaBeans specification (not to be confused with Enterprise JavaBeans &#8212; a completely different spec) is mainly just a naming convention for classes and methods.</p><p>Under the JavaBeans spec, if an object has a property (a value that can be read and written), then it should have <code>getPropertyName</code> and <code>setPropertyName</code> methods to access it. If it&#8217;s a read-only property, then it should only have a <code>getPropertyName</code> method. If the property contains a boolean value, then the &#8216;get&#8217; method should be called <code>isPropertyName</code> instead.</p><p>There&#8217;s a lot more to the spec than that, but those are the bare essentials. Since the <code>ToDoItem</code> class has a <code>getId</code> method, it has a read-only property named <code>id</code>.</p><p>The point of all this is that EL is JavaBeans-savvy: EL makes it really easy to get values of JavaBean properties. So, to output the value of a <code>ToDoItem</code>&#8216;s <code>id</code> property, we can use this expression:</p><pre><code>${toDoItem.id}</code></pre><p>As for the text value of the <code>ToDoItem</code>, EL will automatically convert any object to a <code>String</code> using its <code>toString</code> method, so we could just use <code>${toDoItem}</code>. Our Java code, however, also uses the <code>HTMLEscaper</code> class to escape any characters that might be interpreted as HTML code. But wait: JSTL/EL can do that, too!</p><p>Actually, there are two ways to escape HTML special characters with JSTL/EL. The first is to use the JSTL <code>&lt;c:out&gt;</code> tag with the <code>escapeXml</code> attribute:</p><pre><code>&lt;c:out value=&quot;${toDoItem}&quot; escapeXml=&quot;true&quot;/&gt;</code></pre><p>Even more convenient is the EL function <code>fn:escapeXml</code>:</p><pre><code>${fn:escapeXml(toDoItem)}</code></pre><p>Here&#8217;s how to output our to-do list items in our new <code>todo.jsp</code> file:</p><pre><code> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;option value=&quot;${toDoItem.id}&quot;&gt;${fn:escapeXml(toDoItem)}&lt;/option&gt;</code></pre><p>Since we&#8217;re no longer using the <code>HTMLEscaper</code> class, we can remove the relevant files from our web application. We can also remove the <code>@page</code> directive that imported this and the other classes that were used by our Java display logic code: no Java code, no imports needed!</p><p>With all those changes made, our finished <code>todo.jsp</code> file looks like this:</p><pre><code>&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;%@ taglib prefix=&quot;fn&quot; uri=&quot;http://java.sun.com/jsp/jstl/functions&quot; %&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;%@ taglib prefix=&quot;spfn&quot; uri=&quot;http://www.sitepoint.com/jsp/taglibs/functions&quot; %&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;head&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;title&gt;To-Do List&lt;/title&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;meta http-equiv=&quot;content-type&quot; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;content=&quot;text/html; charset=iso-8859-1&quot; /&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;href=&quot;&lt;c:url value=&quot;/styles.css&quot;/&gt;&quot; /&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;/head&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;body&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;c:if test=&quot;${fn:length(toDoItems) &gt; 0}&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;form action=&quot;&lt;c:url value=&quot;/DeleteItem.do&quot;/&gt;&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;select name=&quot;deleteid&quot; size=&quot;${spfn:max(2,fn:length(toDoItems))}&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;&lt;c:forEach var=&quot;toDoItem&quot; items=&quot;${toDoItems}&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;option value=&quot;${toDoItem.id}&quot;&gt;${fn:escapeXml(toDoItem)}&lt;/option&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp; &nbsp;&lt;/c:forEach&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;/select&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Delete Selected Item&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;/form&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;/c:if&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;form action=&quot;&lt;c:url value=&quot;/AddItem.do&quot;/&gt;&quot; method=&quot;post&quot;&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;input type=&quot;text&quot; name=&quot;newtodo&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp; &nbsp;&lt;input type=&quot;submit&quot; value=&quot;Add New Item&quot;/&gt; &nbsp; &nbsp; &nbsp;<br />
 &nbsp;&lt;/form&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;/body&gt; &nbsp; &nbsp; &nbsp;<br />
&lt;/html&gt;</code></pre><p>Though certainly new, the JSTL/EL syntax in this file will be a lot easier for your average web designer to grasp than the Java code that was there previously!</p><p>Here&#8217;s the file and directory structure of our updated application:</p><pre><code>/todo.jsp &nbsp; &nbsp; &nbsp;<br />
/styles.css &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/functions.tld &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/web.xml &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/AddToDoServlet.class &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/AddToDoServlet.java &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.class &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/DeleteToDoServlet.java &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoItem.class &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoItem.java &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoList.class &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoList.java &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.class &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/ToDoServlet.java &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/jsp/Functions.class &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/classes/com/sitepoint/jsp/Functions.java &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/lib/jstl.jar &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/lib/mysql-connector-java-<em>version</em>-bin.jar &nbsp; &nbsp; &nbsp;<br />
/WEB-INF/lib/standard.jar</code></pre><p><a
class="sublink" href="http://www.sitepoint.com/examples/jgrind/ToDoMVC2.war">Download the code</a>. (759KB)</p><p>As far as JSP best practices go, this updated to-do list example is about as good as you&#8217;re gonna get by following the official specs. And, admittedly, we&#8217;ve got a pretty powerful web application platform happening here. You could certainly build sizeable applications using nothing but Java classes for the model, Java servlets for the controller, and JSPs using JSTL/EL for the view, but there are more powerful options out there.</p><p>Instead of hand-coding database access in your model classes, you can use a persistence framework to synchronize your database with a set of auto-generated Java objects automatically. <a
class="sublink" href="http://www.hibernate.org/">Hibernate</a> is the darling of the day in this area, though <a
class="sublink" href="http://java.sun.com/products/ejb/">EJB 3.0</a> is on the horizon with all the same benefits in a standardized package.</p><p>Instead of writing all of your application logic as a twisty set of servlets, you can use a web application framework like <a
class="sublink" href="http://www.sitepoint.com/article/struts-first-steps">Struts</a>, <a
class="sublink broken_link" href="http://www.opensymphony.com/webwork/">WebWork</a>, <a
class="sublink" href="http://jakarta.apache.org/tapestry/">Tapestry</a> or <a
class="sublink broken_link" href="http://stripes.mc4j.org/">Stripes</a> to manage the complexity.</p><p>Instead of relying on JSTL tags and EL expressions enhanced with your own custom functions, you can use other tag libraries like <a
class="sublink" href="http://java.sun.com/j2ee/javaserverfaces/">JavaServer Faces</a> or one of the many <a
class="sublink" href="http://jakarta.apache.org/taglibs/">open source taglibs</a>, or you can step away from JSP and use a templating system like <a
class="sublink" href="http://jakarta.apache.org/velocity/">Velocity</a> or <a
class="sublink" href="http://xmlc.objectweb.org/">XMLC</a>.</p><p>You could almost say that there are more ways to build web applications with Java than without it! Be sure to follow <a
class="sublink" href="http://www.sitepoint.com/blogs/category/javaj2ee/">The Daily Grind, SitePoint&#8217;s Java blog</a>, as I explore these many options, and watch <a
class="sublink" href="http://www.sitepoint.com/">sitepoint.com</a> for more articles to help you discover the joys of Java web development.</p> <span
id="pty_trigger"></span><div
style='padding:20px 0px 50px 0px;'><div
style='float:left;padding-left:40px;'><div
id='div-gpt-ad-1335489406190-0' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-0'); });</script> </div></div><div
style='float:right;padding-right:40px;'><div
id='div-gpt-ad-1335489406190-1' style='width:300px; height:100px;'> <script type='text/javascript'>googletag.cmd.push(function() { googletag.display('div-gpt-ad-1335489406190-1'); });</script> </div></div><div
style='clear:both'></div></div><div
style='clear:both'></div>]]></content:encoded> <wfw:commentRss>http://www.sitepoint.com/java-6-steps-mvc-web-apps/feed/</wfw:commentRss> <slash:comments>2</slash:comments> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using memcached
Database Caching 70/143 queries in 0.243 seconds using memcached
Object Caching 1926/2053 objects using memcached

Served from: www.sitepoint.com @ 2012-05-27 10:07:53 -->
