Matt RaibleMatt Raible is a writer with a passion for software. Connect with him on LinkedIn.

The Angular Mini-Book The Angular Mini-Book is a guide to getting started with Angular. You'll learn how to develop a bare-bones application, test it, and deploy it. Then you'll move on to adding Bootstrap, Angular Material, continuous integration, and authentication.

Spring Boot is a popular framework for building REST APIs. You'll learn how to integrate Angular with Spring Boot and use security best practices like HTTPS and a content security policy.

For book updates, follow @angular_book on Twitter.

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.
You searched this site for "form". 326 entries found.

You can also try this same search on Google.

My JSF Experience

Of all the MVC Frameworks I've developed with in the last few weeks (Struts, Spring MVC, WebWork and Tapestry) - JSF was by far the worst. And it's not the implementations that are the problem, it's the spec itself (as far as I can tell). Plain and simple, it does not simplify web development.

I spent 3 days developing a simple JSF app - most of it which I had done in the first day. The last 2 days have been spent migrating to MyFaces and trying to find clean ways to do things. My perspective on JSF after this experience? Run away. Run far, far away. All of the above mentioned frameworks are MUCH superior to this technology. Let's get on with the things I learned.

  • MyFaces handles duplicate posts nicely. If you hit "reload" on your browser after saving a record, you get presented with an empty form rather than a duplicate record. I believe I got a duplicate record with Sun's RI.
  • The ability to specify an "action" attribute on a button (or a link) and them map that action to a page (in faces-config.xml) is pretty cool.
  • Every button or link clicked results in a form post. That's just wrong - why can't I have true links like the web is supposed to? So much for bookmarks.
  • Saving state on the client results in enormously long URLs and/or hidden fields.
  • JSF support is fairly non-existent. Unlike the other MVC frameworks, the MyFaces mailing list has hardly any traffic and the Sun forums aren't much better.
  • The MyFaces website seems to be down whenever I want to look something up on it, like right now.
  • I did find some CRUD examples, like this this one, but was disappointed to find that i18n is not considered for setting success messages. I ended up using the solution described in this post. 6 lines of code to set a success message - you've got to be kidding me! Most frameworks have a simple 1-2 liner.
  • Waiting for JSPs to compile the first time has surprisingly become painful after using Tapestry, Velocity and FreeMarker for the last 2 weeks.
  • Integration with Spring is fairly easy (code is in CVS), but MyFaces spits out an error when it shouldn't be.
  • Validation messages are ugly. For instance, when a required field isn't filled in, I get: "lastName": Value is required. I was able to override the default messages, but I was never able to use the label of the field (vs. the field's id).
  • The <h:messages> tag is practically worthless. Sure it's great for displaying messages (error and success), but that's about it. It has a "layout" attribute that doesn't even work in Sun's RI, and in MyFaces it just wraps a <span> with a <ul><li> or a <table>. Both of these layouts are useless b/c you can't set a css class on them. I ended up using "table" and having to set a generic CSS rule (width: 100%) in order to get the message/error bar to show across the top of my page. This tag also doesn't allow you to escape HTML.
  • The <h:dataTable> component is nothing like the displaytag. MyFaces claims to have a pageable/sortable component, but it requires custom logic/methods in your managed-bean. Yuck. I ended up using <h:dataTable>, which has neither sorting or paging. This is only because I couldn't get an <h:commandLink> working inside a displaytag column.
  • JSF-created apps are pretty much untestable. Managed-beans are testable, but the UI seems really difficult with jWebUnit and Canoo's WebTest. IMO, it should be possible to specify a URL to edit a record (i.e. editUser.html?id=2). With JSF and my master/detail app, the link to edit actually sets about 5 hidden form fields with JavaScript and then submits the form. I could probably figure the URL out, but it'd be ugly. Also, the MyFaces <h:dataTable> will not render an "id" attribute if you specify one. This is needed to verify tables and their data with jWebUnit.
  • When using "ant reload" to reload my application (using Tomcat's Ant Tasks), I kept encountering a ThreadDeath error. This seems to be specific to MyFaces as I never saw it with other frameworks or Sun's RI.

Like Tapestry, I felt like I was banging my head against the wall a fair amount. However, with Tapestry (and all the other frameworks), I was able to get exactly the behavior I wanted w/o too much work. I could produce clean and user-friendly error messages - (Tapestry already had clean required messages built in). I was able to write a jUnitWebTest to test all CRUD activities. With JSF, I was able to test one thing - adding a new record. I couldn't edit it b/c the JavaScript support (which I tend to not use) puked every time it encountered a JSF-generated JavaScript function.

My opinion after all of this? If you know Struts, Spring MVC and WebWork are fairly easy to learn. WebWork is simpler and elegant, but Spring MVC supports more view options out-of-the-box. Tapestry is cool, but you'll have to invest a lot of time into learning it and you'll probably get caught up in its cult and forever be claiming "Tapestry Rocks!" which can get annoying to your fellow developers. ;-) Finally, I can confirm that SiteMesh rocks - it worked for all the frameworks I used and I never had to change a single line of code.

Whatever you do, don't use JSF. Not yet anyway.

Posted in Java at Aug 06 2004, 04:53:22 PM MDT 76 Comments

The Joy of developing with JSF

I plan to write up a "My JSF Experience" post later today, but first, I'm forced to rant on the state of JSF implementations. First of all, I must say that JSF isn't so bad. It's cool how you can map buttons to "actions" defined in a navigation entry, as well as to call a method in a managed bean. The problem that I'm experiencing is that the JSF implementations, both from Sun and MyFaces - are errrrr, not so good.

I actually managed to almost finish my simple JSF sample app in one day, but then decided to shoot off some questions to see if I could resolve some remaining issues. Then based on feedback I received, I decided to switch from Sun's RI to MyFaces - not only for the "sortable" grid (I still don't know if it exists), but also Spring supports it w/o using an add-on library.

Ever since I switched, things just haven't gone right. First of all, MyFaces, requires your implement a <listener> in web.xml - who knows why, but you get an error indicating you need it if you don't have it. Standard JSF doesn't require this - why does MyFaces?

OK, I can deal with adding the listener. Everything works as with Sun's RI - and even better since the "layout" attribute of <h:messages> actually works. BTW, why isn't "div" a choice instead of "table" - whoever designed these choices obviously still uses Netscape 4 and table-based layouts. I'm happy now. MyFaces seems to solve the duplicate post issue so if you refresh after adding a record, it just shows a blank form. Cool, I can live with that.

One problem I found, that likely exists in both implementations, is that it's a true pain-in-the-ass to get a declared ResourceBundle in a managed-bean. Here's the method I'm currently using to add a success message:

    public void addMessage(String key, String arg) {
        ApplicationFactory factory = (ApplicationFactory)
            FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
        String bundleName = factory.getApplication().getMessageBundle();
        ResourceBundle messages = ResourceBundle.getBundle(bundleName);
        MessageFormat form = new MessageFormat(messages.getString(key));

        String msg = form.format(new Object[]{arg});
        FacesContext.getCurrentInstance().addMessage(null, 
                new FacesMessage(FacesMessage.SEVERITY_INFO, msg, msg));
    }

There has to be an easier way! Please tell me there is. I admit that I'm a JSF rookie - having just started using it two days ago, but it seems ridiculous that all the "success message" examples out there don't even consider i18n.

So now I have my success messages working, but I discover that there's no way to escape HTML (using <h:messages>) from my ResourceBundle (to put bold around a part of the message). ALL of the other MVC frameworks I've been dealing with allow this - why doesn't JSF?! Again, I'm hoping someone tells me I'm ignorant and there is a way to do this.

Lastly, I tried to upgrade to the latest MyFaces snapshot from CVS to solve this bug and now I can't even get my fricken app to start up because of this issue. Are these the hoops that developers have to go through to get started with JSF? Thump, thump, thump. My head is starting to hurt.

Update: I'm an idiot about the "can't get my app to start thing" - I didn't copy all the new myfaces*.jar files into WEB-INF/lib. Heh. =P~

BTW, MyFaces requires a whole slew of JAR files just like Struts. Here's my current inventory:

  commons-codec-1.2.jar
  commons-collections-3.0.jar
  commons-digester-1.5.jar
  commons-validator.jar
  commons-oro.jar
  commons-logging.jar
  jstl.jar
  myfaces.jar
  myfaces-components.jar
  myfaces-jsf-api.jar

Posted in Java at Aug 06 2004, 10:35:05 AM MDT 4 Comments

My Tapestry Experience

I've finished migrating the sample app I'm working on from WebWork to Tapestry. You can also read about my WebWork experience. WebWork took me 2 full days to complete and the Tapestry version took me about 4. I had a bit of an advantage with WebWork as I've read a lot about it before working with it. I'm probably a bit biases against Tapestry because everyone thinks it's the bees knees - I don't mean to be harsh - I'm just reporting through the eyes of a developer. I'm sure I'll have similar gripes with JSF. Below is a list of things I discovered:

  • There's something wrong with a project when its documentation is outdated and folks tell you to "Buy the book" rather than "read the documentation". On that same note, most of the documentation that does exist seems to be targeted at the advanced user.
  • Like WebWork, there was no simple CRUD example I could look at. Then, like a ray of light from the sky - Warner published one yesterday! This tutorial vastly improved my productivity - thanks Warner! The only things I saw that I'd change in this tutorial is the use of individual setters vs. a domain object. Also, an ICallback is in the code, but never really used.
  • The recommended way to name templates (.html) and page specification (.page) files is starting with an Uppercase letter. So rather than home.html (which most web developers are used to), it's recommended you use Home.html. Of course, this is easy to change - just seems like a weird recommendation, almost Apple-ish or Microsoft-ish.
  • By default, all templates and pages are cached. Sure this is good because Tapestry is production-ready, but when you're developing - this needs to be off so you can get deploy+reload functionality. If you're using Tomcat, you can turn caching off by setting a $CATALINA_OPTS environment variable with value "-Dorg.apache.tapestry.disable-caching=true" (no quotes).
  • Tapestry integrates with Spring very nicely. So easy it's almost silly. When I first created my list screen, it actually had only one line: public abstract UserManager getUserManager(); - and then I used OGNL to get my list of users: userManager.users. It doesn't get much easier than that.
  • While setting success messages is fairly easy - I couldn't find a good way to prevent duplicate postings. With most frameworks, I stuff messages in the session and then retrieve them on the next page. With Tapestry, you have to throw a RedirectException if you want a true redirect (which requires a lot to calculate the URL of a page). I ended up using a PageRedirectException in hopes of simplifying this - but this seems to just do a forward instead of a redirect. In the few hours I spent on it, I couldn't find a way to save success messages and have them persist through a redirect. The reason I want to use a redirect is so a refresh of the page doesn't submit everything again. I know it's trivial, but is is an issue that most frameworks don't handle cleanly (except for Struts).
  • There's no way to test Tapestry classes - since they're abstract, you can't just invoke them and test. Granted the classes are simple - but as long as other frameworks allow you to test their .java files and Tapestry doesn't - this will be an issue.
  • When you first enter a blank form (i.e. to add a new user), the cursor's focus is put on the first required field. As a developer and user, I'd like to control this a little more (for example, by putting it on the first field). Furthermore, I'd like to control it easily - without having to subclass ValidationDelegate. On that same note, it'd be cool if required fields had an asterisk by default. WebWork does this and Spring/Struts can do this using Hatcher's LabelTag.
  • There's no easy way to get the URL of a page - for example, to use in a <button>'s onclick handler to do location.href. I ended up having to implement a method in my page class, and a @Block in my template, setting the button's value with OGNL, and then using JavaScript to do onclick="location.href=this.value". The default components that ship with Tapestry only produce links and submit buttons (that must be in a form).

When developing this sample app, I often felt like I was banging my head against the wall. This is likely because I didn't want to take the time to truly understand how Tapestry works - I just wanted to get my app done. I did end up buying Tapestry in Action, but I probably won't read it until I have time or decide to use Tapestry on a project. I agree that Tapestry is cool, but it's certainly not intuitive for a Struts guy like me. I do look forward to working with it in the future and I'm sure I'll grow to like it more as I gain more experience.

Many thanks to Erik for his tech support and knowledge and to Warner for his nice kickstart tutorial.

Posted in Java at Aug 03 2004, 04:39:42 PM MDT 6 Comments

My WebWork Experience

Yesterday I began converting a small application from Spring MVC to WebWork. By the end of the day I was pretty much finished, but shot an e-mail off the the user's list to figure out a few more things. Today was spent incorporating that knowledge and making the app follow more WW "best-practices". Below is a list of things I discovered:

  • WebWork's documentation is actually quite good. I was able to figure out most things just by reading it. I'm still surprised that most web app frameworks don't describe a simple CRUD operation as their first example. In my experience, CRUD is 80% of a webapp's job.
  • WebWork integrates with Spring quite nicely. It's interesting to see that Spring has most of its MVC Framework support as part of the core, but WW has its own. I wonder why? Who cares, it works!
  • WebWork is a bit better than Spring MVC in that they have a mechanism for saving/displaying success messages. However, it doesn't live past a redirect, so you're still stuck putting messages in the session. Struts (as of 1.2.1) allows you to use a saveMessages(session, messages) call - and subsequent JSP tag to display (and automagically remove). Like it or not, Struts seems like the easiest solution for developers to use.
  • There's no clean mechanism for cancelling validation when a user clicks on a "cancel" or "delete" button. Struts supports cancelling using it's <html:cancel> button and it's pretty easy to detect "delete" and cancel validation in a form's validate() method. I ended up using an onclick handler for my cancel button and not worrying about validation on delete. This is the way I did it with Struts for years. Spring is cool in that it has a processFormSubmission() method that you can override before validation kicks in.
  • With Commons Validator, I'm used to specifying generic validation messages like "errors.required={0} is required.". This is possible with WW by using "errors.required=${getText(fieldName)} is required.". However, WW is a bit unique in that validation rules and ResourceBundles are defined on a per-action basis. I like having a central location for all my messages - like Spring and Struts have. I know it's possible with WW, but I'm trying to develop a "best-practices" sample app.
  • I really dig that fact that you can use one JSP tag to render an entire <tr> in a table. This <tr> ends up having a label and an input field - which is very cool IMO. I did find some issues with the XHTML output, but found it very easy to submit patches. Good stuff.
  • The config files (xwork.xml and validators.xml) must be in WEB-INF/classes. This is because they're XWork configuration files, and XWork is a non-web framework. It would be nice if I could put these in WEB-INF - where the rest of my config files (Spring, SiteMesh, etc.) reside.
  • Many of the JSP tags require you to use "'literal value'" - where you put single and double quotes back-to-back. IMO, this is just ugly and I'd much rather put some sort of indicator that it's a dynamic value - i.e. ${...} or #.
  • I couldn't get client-side validation to work. Seems cool though.

My experience with WebWork has been quite pleasant. I received excellent support from the mailing list - even though it took me a while to subscribe. The mailing list archives are woefully out-of-date, but this is a general java.net problem - not a WW issue. Maybe they should create a forum until the mailing lists get back on track?

Hopefully this last day and a 1/2 will make it much easier to implement WebWork in AppFuse. Thanks for the support gents - now I'm off to learn Tapestry!

Posted in Java at Jul 21 2004, 03:41:58 PM MDT 8 Comments

Want to learn more about AppFuse?

AppFuse Home A couple of weeks ago, I wrote an article on AppFuse for java.net. I'm proud to say it was published today: AppFuse: Start Your J2EE Web Apps. This is my first "published" article - so it's pretty cool to see it up there.

One thing that's strange is the TOC links on the top right don't seem to work in any browser other than IE. Wierd. Now I just hope this site stays up since there's a lot of links that point here. It's a sort of weblog timeline about the birth of AppFuse - hope you enjoy!

Posted in Java at Jul 15 2004, 07:17:59 AM MDT 6 Comments

[JavaOne] What's new and cool in the J2ME Wireless ToolKit

I'm continuing my theme to only attend sessions I know little about. I'm sitting in a session on the J2ME Wireless ToolKit. So far it's fairly boring. This guy's been rambling on for a while about all the JSRs that the toolkit implements. Now he's doing a demo and using the Network Monitor to demonstrate looking at the HTTP requests when making soap calls.

This is only my 4th session of JavaOne, and I haven't been to any BOFs. I don't feel like I'm missing anything. Most of my time in Moscone is spent sitting in the main lobby, hacking away at my e-mail and talking with folks. I never imagined I'd meet so many people. It's pretty damn cool to meet all the bloggers.

The tools and demo that this guy is showing look like good monitoring and emulating tools. The WTK doesn't appear to have an IDE, just a way to run midlets and see the results. It doesn't appear to have an IDE. If I was to compare this to the web world, I'd say that the WTK is really just a web browser. Of course, it's much more than that since it can emulate HTTP requests, and well as bluetooth. From what I can tell, a midlet is really just a Java application that can run on a mobile device. After googling a bit, it looks like I was right. How easy is it to unit test midlets? Do you have to constantly use an emulator to test stuff? I'd like to write an AppFuse client for my phone, but I also want to use TDD to do it.

I missed the rest of the presentation b/c I got lost in reading blogs. Attending these sessions with an open laptop is not a good idea. I hope I can make one more session today - my goal was 5 for the week. As Dion said, this conference is all about networking.

Posted in JavaOne at Jun 30 2004, 03:57:53 PM MDT 2 Comments

JDNC: Simplifying Java Desktop Client Construction

Next session: Java Desktop Network Components. I'm trying to attend sessions that I don't know much about. J2EE ones are likely to bore me. I just noticed that Amy Fowler is one of the presenters - and I've heard she's hot - so I'm sitting up close (5th row).

JDNC is designed to provide shortcults for building common archetypal applications. Better clients with less effort. Less (maybe no) coding. Gentle learning curve and incremental development model. Assumes network or web data source. Geared towards Java application and XML developers. Sun is going to do a lot of work to get Tools vendors to include JDNC. It seems similar to AppFuse, but I'm guessing it's more of an API than a project template. Their goals seem to be the same - get something to show your manager in a matter of hours, not weeks.

Swing Extensions API: targeted for Swing developers, extended components with more features, networked data connectivity and data-binding. I wonder how JDNC compares to Spring's RCP project? Amy mentions JGoodies and how they'd like to include it as part of JDNC.

Feature Highlights:

JXTable: Asynchronous data loading. Sorting, filtering and highlighting.
JTreeTable: Hiearchical-columnar view (outline)
JForm: Data-binding and Validation (as you type). Sounds a lot like what Keith is working on for Spring.
Damn - missed one...

JDNC API: Very high-level components. Built on the foundations of SpringSwing/JFCX. Solution focused and conforms to the JavaBeans Architecture Spec - BeanInfos provided for tool friendliness. Encapsulates complex operations (threading, network connectivity, data modeling). Provides usability features.

Components: JNTable, JNTree, JNTreeTable, JNForm, JNEditor. These components wrap, rather than extend lower level component. Expose simpler API and provide more defaults (i.e. scrolling).

Now we're looking at the Bug Editor Demo (WebStart). The features they're showing are similar to what folks want in the display tag - sorting, filtering, column visibility. It's very cool to see that this is now a built-in feature of Swing. I wonder how hard it is to use JDNC and JGoodies in project? Is it just a matter of adding a couple of JARs to your classpath? It'd be cool to add J2ME and Swing clients to AppFuse. I think the hardest part would be emulating the current (container-managed) security model that exists in the webapp clients.

Sorry, zoned out on e-mail for a while there.

Amy is now showing code and how to create a form for the detail view. It's interesting that the data-binding, including exceptions, is similar to Spring.

JDNC Markup Language: Looks very cool. You can actually develop a Swing app with XML!

Important thing to remember: JDNC simplifies rich client development on all levels. Overall I think JDNC is a very cool open-source project - it's nice to see Sun trying to make developer's lives easier. For more information on developing Swing apps, checkout javadesktop.org.

Posted in JavaOne at Jun 29 2004, 04:09:19 PM MDT 14 Comments

[JavaOne] State of the Web Tier

I'm sitting here with Bruce, listening to Craig McClanahan and others speak about the "state of the web tier." After the first 15 minutes, it seems like a waste of time. I should go to something I don't know about. The first 15 minutes touched on MVC frameworks and things like filter and tag libraries. I was impressed that they mentioned WebWork, Tapestry and Spring. Heck, they even mentioned SiteMesh when they talked about filters. Now Craig is talking about portlets.

It would be cool to do some portlet development. I took a class a couple of years ago to become a Portal Server instructor. I got certified, but never actually taught a course.

JSF: A server-side user interface component framework for Java technology-based web application. It's not an application framework for your business logic - it's for the UI only. JSF looks cool - especially since it uses the same "form backing object" like Spring MVC has. I think JSF has an advantage over a lot of other frameworks because (1) it'll be well documented and (2) it'll be well tested and (3) it'll be widely used. Having a widely-used technology is sooooo much easier to learn than ones that aren't. I'm willing to bet that the JSF version of AppFuse will be the most popular one in a year from now. By the end of the year, AppFuse will support WebWork, Tapestry and JSF in its web layer - in addition to Struts and Spring MVC.

Demo time. Craig is showing us the JSF demo app that we saw in the keynote. We're looking at Java Studio Creator now. There's a Creator party tomorrow night - get tickets from downstairs at the Creator booth.

J2EE 5.0: New name, same great platform. Final release in second half of 2005. Ease of Development is the primary theme. Based on J2SE 5.0, with great benefits (shouldn't it be J5SE and J5EE - WTF!?). New JSRs: JSP 1.2/JSF 1.2 - EL alignment is key. Toolability is key. Maintenance reviews: Servlets and JSTL. J2EE.next - successor J2EE 5.0. Work will begin shortly after JavaOne and JSRs will be filed after JavaOne. Experts groups are on Java.net - JSP and JSTL are there today. Also,the JSF Reference Implementation is now on java.net. BTW, I'm on the J2EE 5.0 Expert Group so hopefully I can contribute to making J2EE 5.0 easier too. They'll let just about anyone onto these expert groups - can you believe they let both Hani and I in? ;-)

Posted in JavaOne at Jun 28 2004, 03:29:35 PM MDT 5 Comments

Quick 'n Easy SiteMesh Tutorial

SiteMesh is a kick-ass tool. It's much easier to use and configure than Tiles, although I don't know if its as powerful. Tiles has Controllers that you can assign to a definition and it supports easy i18n. I've been using Tiles for over 3 years and I've only used SiteMesh for a few months. However, SiteMesh already seems to suite all my needs. I'm guessing that most people use Tiles over SiteMesh because they haven't given SiteMesh the 10 minute test.

Anyway, back to the point of this post. Rick Reumann has put together a nice tutorial titled Use SiteMesh instead of Tiles.

I think you will quickly see the benefits after going through this brief example. In summary, the main reason I like SiteMesh more than Tiles is that SiteMesh is much easier to configure and use (less typing and easier to understand).

Good stuff - thanks Rick! As part of the WebWork integration into AppFuse, I was planning on using SiteMesh. I'm already using it in Spring Live sample app and it's pretty slick. I haven't had to touch it since I integrate it. Compare this with Tiles where you have to add a new definition (or JSP) everytime you want a new page. If nothing else, I think Tiles needs to learn from SiteMesh and add a Filter that can be used to decorate pages.

Posted in Java at Jun 13 2004, 02:15:50 PM MDT 9 Comments

[Construction] Photos from May

It's been a while since I last posted about our house. I guess I'm due to post some new pictures. Click on either image below to see photos we took in May. The builder thinks the house will be finished and we'll be able to move in by Labor Day. Julie is due on Labor Day, so it should be an interesting race. My money is on the baby arriving first.

View form the back
Raible Designs new HQ
From the front
From the front
From the front
Great Room

Posted in General at Jun 10 2004, 01:26:37 AM MDT 2 Comments