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.

Java-based Forums and Free Software

I've always thought that Jive was a great product, especially when I first found it. It was free then, now it costs $450. It it worth it - yes! But it's tough to recommend this to clients when there are free alternatives. Here's one courtesy of Mathias Bogaert:

Discovered mvnForum, a JSP 1.1/Servlet 2.2 based forum application (GPL), which looks kinda neat...check out their demo.

I have this same problem at work. I told my project manager that I knew of three Bug Tracking systems: Bugzilla, JIRA and Scarab. I currently use Bugzilla for a client and I'm familiar and happy with it. I also use JIRA for Roller and XDoclet, and think it's a great piece of software. Even though I've never used Scarab, I installed it thinking that it was better than Bugzilla, and also b/c the guys from Apache are moving to it. After wrestling with the setup a bit, I got it working. Scarab's main goal seems to be ease of setup - they should take some lessons from Atlassian. Actually, we all should - I had JIRA downloaded/installed/running in under 5 minutes. Anyway, back to the point - I showed Scarab to my project manager and he went off to investigate. An hour later he came back and said he just didn't get it. I didn't have the bandwidth to investigate, and since I've never used it - we're going to use Bugzilla. I prodded and poked and tried to get JIRA; I even downloaded and installed the 30 day trial. No joy, free is what they want.

Speaking of free software, I'm inspired to do some work on Roller - especially with all the stuff that Dave and Lance have done lately. Also, my RSS feed seems to refresh old stories in Radio's aggregator, so I'm due for an upgrade. I hope to add some of the following features over the next week or so (when do we release 0.9.7?):

  • Encypted password support - both programmatically and using Tomcat's Realm. The way I've done this in the past is to create a LoginServlet that my form-based authentication maps to. This servlet does the encryption and redirects to j_security_check. I'll also include an option for an SSL-based login. Both password encryption and SSL will be off by default - and changes will be allowed in web.xml.
  • Remember Me. You're gonna love this - I sure do.
  • Remember Me in Comments. It's definitely needed if you do a lot of commenting. The question is - do you automatically do it - or allow users to say "forget me." Auto is easiest.
  • Add support for e-mailing comments and subscribing to comments when posting a comment.
  • Dig into XDoclet and make the upgrade to 1.2 Beta 2 - fixing the bug we have with Castor. I hope I'm familiar enough with how XDoclet works to make this happen. I looked through the code today and it should be working from what I can tell.
  • Upgrade to Struts 1.1 Beta 3.

Sheez! I just created a whole bunch of work for myself didn't I? Hmmm, now how do I schedule all this and get it done in a week? A late night, an early morning, a weekend? I can't decide... Oooh, here's an idea - Julie and Abbie are leaving for Florida next Thursday (I'm joining them Friday) - I could do it next Thursday night. Hopefully I can get it done sooner, but hopefully a lot of this can wait until then.

Posted in Java at Jan 15 2003, 09:47:48 PM MST 1 Comment

Found: Hibernate based personal image server

I found the pixory personal image server on the hibernate-devel mailing list this morning. It looks like a regular web-based photo album, but seems to offer client side tools as well. You can checkout the screenshots if you want to get right to it.

Pixory is a personal image server based on Hibernate and HsqlDB.
-------------------------------
Pixory allows you to store your photos on your own pc but to access, compose into albums, and share them anywhere on the internet. It's your personal online photo sharing service, running on your computer using your broadband internet connection. Pixory is a client and a server, a lightweight web application for browsing photo collections on your hardrive; an album server to your friends and family or anyone on the internet. It simplifies accessing and organizing photo collections on your home network.

Today was a pretty awesome day in my development life. This morning started off great with the "remember me" feature, and I also implemented the Nested tag library from Struts. It was great - took me all of about 5 minutes to implement and get nested, indexed iterating of child objects in a form. I ended the day with disappointment as I tried to save this form. That's when I discovered that XDoclet wasn't generating getter/setters for my indexed getter/setters. I might actually have to put a form in my source tree to get this functionality. So far, all my ValidatorForms are still generated from POJOs, which Hibernate uses. Not all my POJOs are run though XDoclet -- some are generated using Hibernate's Reverse Engineering Tool. It actually seems to take less time to write the mapping file than to mark up the POJO with XDoclet tags. If you generate it with the RET, it's like taking candy from a baby.

Speaking of babies, I started to learn a new language tonight. I call it Abbie-blah - it consists of making grunts and groans and sticking your tongue out. I swear I had an intellectual conversation with Abbie - I had her smiling like you wouldn't believe. Fun times.

Posted in Java at Jan 14 2003, 09:40:12 PM MST 3 Comments

Simple Intentions turn into Remember Me Login

I woke up this morning, and had the simple intention of blogging about one of my favorite tools, The Color Schemer. If you're a wanna-be designer like me, it's awesome. It helps you match "like" colors and also allows you to select any color on your screen. It's one of my most invaluable web design tools. Putting a tip about this was my only hope at 4:30 when I sat down at this computer. Now it's 5:39.

Why am I still here? I got caught up in reading the Colorado Bloggers mailing list - which actually got some traffic yesterday. This is one of the first times I've received a message from the list. One of the members pointed me to a another Photo Album for the web. It's called Gallery and she has an example setup. Looks like it runs on PHP. Well that shouldn't have taken me an hour, right?

The activity that's filled my last hour has been wrestling with Erik Hatcher's request for "remember me" functionality in a J2EE app, using container-managed security. The good news is that I did get it working - here's how:

  1. First, I added a checkbox called "rememberMe" to my login.jsp. When the user clicks "submit", I do some JavaScript logic. This logic entails saving the username and password as cookies - but only if the rememberMe checkbox is checked. If rememberMe is checked, a cookie is set called "rememberMe" with a value of "true."
  2. Using Roller's BreadCrumbFiler (maps to /*), I added some logic to check for the existence of the "rememberMe" cookie, and if it exists, to route the user to "j_security_check?j_username="+usernameCookie+"&j_password="+passwordCookie.

This all worked fine and dandy right off the bat - took me about 10 minutes to implement. The problem was that a user couldn't "logout." So I've spent the last hour (now it's been an hour and 1/2) with my own ignorance trying to delete cookies (and doing null checks and such) so users could logout. And I just got it working - fricken sweet! What a way to start the day! The only problem I could see now is if a user tries a username/password and selects "remember me", but then closes their browser. The BreadCrumbFilter will keep trying to authenticate them - yep, I just verified that that's a problem. It's also a problem when they enter an invalid password and select rememberMe.

One way to solve this is to not set the "rememberMe" and "password" cookies until someone has successfully authenticated. Maybe I could use the breadcrumbs in the BreadCrumbFilter to check the last URL accessed, and if it's already j_security_check, don't do the routing. Anyway, here's the code that does the heavy lifting in BreadCrumbFilter:

Cookie rememberMe = RequestUtil.getCookie(request, "rememberMe");
// check to see if the user is logging out, if so, remove the
// rememberMe cookie and password Cookie
if (request.getRequestURL().indexOf("logout") != -1 && 
	(rememberMe != null)) {
    if (log.isDebugEnabled()) {
        log.debug("deleting rememberMe-related cookies");
    }

    response =
        RequestUtil.deleteCookie(response,
                                 RequestUtil.getCookie(request,
                                                       "rememberMe"));
    response =
        RequestUtil.deleteCookie(response,
                                 RequestUtil.getCookie(request,
                                                       "password"));
}

if (request.getRequestURL().indexOf("login") != -1) {
    // container is routing user to login page, check for remember me cookie
    Cookie username = RequestUtil.getCookie(request, "username");
    Cookie password = RequestUtil.getCookie(request, "password");

    if ((rememberMe != null) && (password != null)) {
        // authenticate user without displaying login page
        String route =
            "j_security_check?j_username=" +
            RequestUtils.encodeURL(username.getValue()) +
            "&j_password=" +
            RequestUtils.encodeURL(password.getValue());

        if (log.isDebugEnabled()) {
            log.debug("I remember you '" + username.getValue() +
                      "', authenticating...");
        }

        response.sendRedirect(response.encodeRedirectURL(route));

        return;
    }
}

I can post the code for RequestUtil if you need it. The class RequestUtils (for encoding URLs) is a Struts class.

Posted in Java at Jan 14 2003, 06:07:21 AM MST 4 Comments

Tabbed Forms - Making the web look like Excel

One of the things I'm working on for my day job right now is the ability to display an Excel-like UI for editing a form. So I did a search on Google tonight and found DHTML Kitchen. On this site, they had exactly what I was looking for - a howto for creating a tabbed panel system. So I've used this example to create a prototype of what I can do. This is pretty slick b/c now I can give the users a UI that looks like the Excel they're used to, and I can use the same ValidatorForm for the entire page. It even supports remembering which tab you last selected, and also allows navigation to a tab. The DHTML Kitchen also appears to have all kinds of other goodies to checkout. I'll definitely be adding it to my list of cool bookmarks.

If someone could verify that this prototype works in IE 5.5 - that'd be awesome! This is the browser we have to support at work and all my browsers are 6.0+. In return, I offer you the source in a single zip file :-) After playing with this a bit after posting - it seems like it's got a couple of issues in IE 6. The first is that a double line shows up at the bottom of the top tabs after refreshing. Clicking on any tab at the top snaps the tab bar back into place. The second is performance - it's taking 3-8 seconds to load the page - yikes! I'm still going to use it though, and hopefully optimize and fix these issues later.

Posted in The Web at Jan 11 2003, 11:45:23 PM MST 4 Comments

My First Attempt at ConvertUtils

My first attempt at using ConvertUtils is turning out to be a painful one - most likely due to my own ignorance. Let's see if you can help me out. I have a Hibernate Bag, which is really a java.util.List on my User object. When I run the User object through XDoclet, I create a UserForm (extends ValidatorForm). The form has an ArrayList on for any instances of List or Set on the object (set through a custom struts_form.xdt template). So I created a ListConverter to convert a List object to an ArrayList. Sounds pretty simple right?! Here's my ListConverter.java:

public class ListConverter implements Converter {
    //~ Instance fields ========================================================

    protected Log log = LogFactory.getLog(ListConverter.class);

    //~ Methods ================================================================

    /**
     * Convert a List to an ArrayList
     *
     * @param type the class type to output
     * @param value the object to convert
     */
    public Object convert(Class type, Object value) {
        if (log.isDebugEnabled()) {
            log.debug("entering 'convert' method");
        }

        // for a null value, return null
        if (value == null) {
            return null;
        } else if (value instanceof Set && (type == Set.class)) {
            return new ArrayList((Set) value);
        } else if (value instanceof List && (type == List.class)) {
            return new ArrayList((List) value);
        } else {
            throw new ConversionException("Could not convert " + value
                                          + " to ArrayList!");
        }
    }
}

When I run BeanUtils.copyProperties(userForm, user), I get:

Could not convert cirrus.hibernate.collections.Bag@e2892b to ArrayList!

On another class, where I am trying to convert a List of Longs, I get:

Could not convert [-1, 1, 30129] to ArrayList!

I'm registering my custom converter in a static block of my BaseManager class. My *Manager classes do all the conversions, so this seems logical:

static {
    ConvertUtils.register(new StringConverter(), String.class);
    ConvertUtils.register(new LongConverter(), Long.class);
    ConvertUtils.register(new ListConverter(), ArrayList.class);
	
    if (log.isDebugEnabled()) {
        log.debug("Converters registered...");
    }
}

Since I'm in a major time crunch, I'll try simply making my getter/setters on my UserForm to be List. I'd like to use ConvertUtils though, so hopefully someone has a solution.

This brings me to a RANT and I think it's my first official one. My last three projects have always started small, and the goal has always been a prototype of functionality. A prototype that turns into a production system. All fricken three of them. All were supposed to take about 3 months to develop initially. The last two projects took at least 6 months. This one has a one month deadline, but the scope is a lot smaller than the previous two. But still, it's always the same scenario - the clients want a prototype, but turn it into a production system. Since it's a prototype, I tend to write "workarounds" for design patterns (see above) that I can't figure out. Is this good? It probably doesn't hurt since no one will ever look at my code - right?! When's the last time you looked at a co-workers code? (The more == the better). And the truth is, as long as it works - it's probably good enough. However, I as a developer, get heartburn when I think about maintaining the system that I created under the impression that it was a prototype. Maybe one of these days I'll figure out all the best practices to creating a robust web application, and then I'll know everything - so I won't have to write workarounds for my lack of knowledge. If you see some pigs flying, you can think to yourself - "Wow, Raible must've figured it all out" ;-)

Posted in Java at Jan 11 2003, 04:04:43 PM MST 1 Comment

Upgrading to Struts 1.1b3 - Tips

I upgraded one of my client's applications from Struts 1.1b2 to Struts 1.1b3 tonight. It was a small headache, but not too bad. As far as the differences b/w 1.1b2 and 1.1b3 - they're pretty significant. Some classes/methods are downright gone - not just deprecated, but gone. Oh well, that's why it's a beta - and it's free, so who's complaining? I'll try to remember a few issues I found. The first is how to create a DynaActionForm. The code below worked with 1.1b2:

DynaActionForm messageForm = 
    (DynaActionForm) DynaActionFormClass.getDynaActionFormClass(
                     Constants.MESSAGE_KEY).newInstance();

But the getDynaActionFormClass method is now gone, so you have to use this:

FormBeanConfig cfg =
    mapping.getModuleConfig()
           .findFormBeanConfig(Constants.MESSAGE_KEY);

DynaActionForm messageForm =
    (DynaActionForm) DynaActionFormClass.createDynaActionFormClass(cfg)
                                        .newInstance();

A few deprecation errors cropped up as well.

  • Action.MESSAGE_KEY -> Globals.MESSAGE_KEY
  • Action.ERROR_KEY -> Globals.ERROR_KEY
  • org.apache.struts.validator.StrutsValidatorUtil -> org.apache.struts.validator.Resources

Finally, I found an issue with using BeanUtils.populate(dest, orig). It worked fine with 1.1b2, but throws a NPE with 1.1b3. I replaced this with BeanUtils.copyProperties(dest, orig) and everything works as it should. My guess (from doing a toString() on the orig) is that "multipartRequestHandler=null" was messing things up.

It's interesting doing maintenance/enhancements on code that I wrote a year ago. I've learned sooooo much since then. I wish I could go back and re-factor a bunch, but my client would never go for it - it works right?! Maybe I'll refactor some for kicks - just to see if it's possible. I'd love to replace a few DAOMySQL's with DAOHibernate's ;-)

Posted in Java at Jan 06 2003, 11:16:48 PM MST 6 Comments

RE: ArrayList vs. Vector - which is better for webapps?

What the hell was I thinking?! I must've been tired this morning when I wrote the last post. I meant to say Serializable not Synchronized!! Yikes - what a blunder! Does this change your feelings? What if I have a UserForm (extends ActionForm) that has an ArrayList of children? I usually put a user's Form in the session, so I can access their information at any time.

Posted in Java at Jan 02 2003, 08:19:16 PM MST 1 Comment

Java Development with Ant, The Application

Ant Book If you've been fortunate enough to read Erik Hatcher's Java Development with Ant, you know that there's tons of good tips in it. I read it and I've been recommending it every since. Erik has been continuing development of the sample app for the book ever since it was released. I got many tips from Erik in developing AppFuse and I have to say, it really is a nice example. Maybe I'll get some more stuff now that it appears to have jumped from version 0.4 to 0.9! Here's a message Erik sent about the latest release.

All -

I'm proud (and worried about the support e-mails! :) to announce the 
near-final release of a project demonstrating Ant, XDoclet, Struts, 
JUnit, Cactus, and Lucene.  Its called JavaDevWithAnt as it was written 
for the book Steve and I co-authored and has been refined during 
several presentations I've been giving on Ant, XDoclet and Struts.

The documentation is in draft stage, and my primary goal is to collect 
feedback on polishing the documentation (and the application if there 
are any bugs that surface).  The site where I'm hosting the 
distribution and documentation is:

	http://www.ehatchersolutions.com/JavaDevWithAnt/

Please let me know if you try it out and have suggestions for 
improvement, or just to let me know you tried it and hate it or love 
it, etc.  Feedback more than welcome!  Direct feedback to me at 
[email protected]

	Erik

p.s. Since this e-mail is directed to the XDoclet, Lucene, and Cactus 
lists, here is a brief teaser for you:

XDoclet - its used extensively, even using a custom tag handler to 
generate starter JSP's from Struts form beans.

Lucene - my <index> Ant task is used to index text and HTML files, and 
Lucene's API is used at run-time to query the index.

Cactus - StrutsTestCase is used, although no direct Cactus tests.

Happy information-overload! There's a lot there, but if I could figure it out - I'm sure you can. Erik - finally on Jaguar eh? What took you so long ;-)

Posted in Java at Dec 27 2002, 07:25:45 PM MST 1 Comment

Copying Properties: The Good, the Bad and the Ugly

I realize that having an ActionForm and a POJO with the same getters/setters is ridiculous, but please bear with me for this example. I have a Form and a POJO with Strings, Longs and Dates. The Longs and the Dates get converted into Strings when I get the data from the database using BeanUtils.copyProperties. This works great.

BeanUtils.copyProperties(userForm, user);

However, when going back, it's a different story - here's the ugly way:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

Date dateChanged = format.parse(userForm.getDateChanged());
Date dateCreated = format.parse(userForm.getDateCreated());

user = new User(userForm.getUserId(), userForm.getPassword(), 
                Long.valueOf(userForm.getDesktopId()),
                Long.valueOf(userForm.getCubeId()), 
                userForm.getCreatedBy(), dateCreated,
		userForm.getChangedBy(), dateChanged);

While this works, it's ugly and a pain. I want something like the ActionForm-Value Object mapper. This mapper allows you to easily copy properties between VOs (or Hibernate Objects) and Forms, and vise-versa.

vo = FormToVOMapper.map(form, new ExampleVO());

So I could do something as simple as user = FormToVOMapper.map(userForm, new User()); I like this mapper and I used it on my last project, where it works great. However, I get the feeling that developers in the Struts Community are using something better - and I want to use it. So please, tell me what it is and lets figure out the best way to do this. Another method I've used in the past is to set the VO (or object) on the form itself, allowing for setting of Strings without copying - and setting dates on the form, to be manipulated by the setter. This framework worked great, and I was actually the happiest with it out of any of the above. Chime in and give me your opinions!

Posted in Java at Dec 27 2002, 03:14:29 PM MST 6 Comments

ChainedExceptions and BeanUtils.copyProperties

I am wondering about a few things, so thought I'd try and get some help from the best source I know - the java.blogs community. First, an update on last night. I experienced some difficulty with Hibernate (persisting child objects) and Struts (nightly build doesn't quite work right with Tiles and Modules) and gave up at 2:00 a.m. Luckily, my head cleared up this morning after a deep 4 hours of sleep and I figured out Hibernate and it appears that a fix for the Tiles/Modules problem was checked into CVS by Cedric.

Now I'm wondering if it's possible to use declared exceptions in Struts to grab all your Exceptions from the bottom up. I can do this in an Action (or even a filter) using the following:

// caught exception e
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,
           new ActionError("errors.general"));

while (e != null) {
    errors.add(ActionErrors.GLOBAL_ERROR,
               new ActionError("errors.detail", e.getMessage()));
    e = (Exception) e.getCause();
}

request.setAttribute(Globals.ERROR_KEY, errors);

Can I do this with declared exceptions? Man that would be sweet if I could - I wouldn't have to have any exception handling in my Actions. Maybe that's the easy way out, but it also makes for rapid development - and you can always add them in when you really want them. Two other things I need to do.

  • I have a java.util.Set on my User (Hibernate) object. This refers to a collection of Resume objects. When I generate my StrutsForms, I need to do something in my XDoclet template to turn a java.util.Set into a java.util.ArrayList. I don't know that I have to do this, but I've always used ArrayLists or Vectors on ActionForms for child objects.
  • I am using BeanUtils.copyProperties in a Business Delegate to transfer properties from my User object to a UserForm object. When I do this, the child objects come through as Resume objects - where I really want them to come through as ResumeForms. Is this possible using BeanUtils, or do I have to do this manually?

I should probably do some research now to try and figure this stuff out on my own - but hopefully an answer will come through while I'm doing that ;-). I'll post to the proper mailing lists if I can't figure it out by COB. BTW, if you're using Hibernate, the FAQ is awesome. I wish more OSS (or closed-source software) had documentation this good.

Posted in Java at Dec 27 2002, 11:40:40 AM MST 9 Comments