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.

Multiple Monitors? Get this software!

I haven't used Synergy, but Chris seems to like it. It sure sounds cool.

With synergy, all the computers on your desktop form a single virtual screen. You use the mouse and keyboard of only one of the computers while you use all of the monitors on all of the computers. You tell synergy how many screens you have and their positions relative to one another. Synergy then detects when the mouse moves off the edge of a screen and jumps it instantly to the neighboring screen. The keyboard works normally on each screen; input goes to whichever screen has the cursor.

I highly recommend setting up dual monitors if you are a developer. I did it this summer after purchasing a 19" Dell Trinitron for $150 from eBay. If you're buying off eBay, make sure you know exactly what monitor you're getting. The first one I bought was a 21" Sony that sucked. Luckily, I was able to re-sell it fairly easily. Now, I actually believe that my two 19" Trinitrons might be better than the 23" Cinema Display I long for.

Posted in General at Mar 10 2003, 11:44:32 PM MST 1 Comment

Struts Training: Week 2

I'm planning on attending today's Struts training and will be reporting here again. I got up at 6, hoping to do the labs and discovered the first step was downloading the latest Basic Portal setup. Since it's 200 MB, I've been dicking around for the last hour and a half, waiting for it to download. Yikes - I thought struts-resume was bad at 10.5 MB! I guess the difference is that it includes JRockit, Mozilla, OpenOffice, Vim, Ant, Eclipse, JMeter, Jikes, PostgreSQL and Resin.

Today's session seems to be covering databases, SQL and database performance. Vic mentions that 90% of performance is in the data model design. If you can fit your database on a laptop, then performance will probably not be an issue. I agree with this. I did the first lab during the first half-hour of the preso. Pretty simple stuff: creating HTML files and accessing them through a browser. This is probably a good lab to get everyone going and stuff installed. Also proves that Resin is running. Of course, it took me two hours to complete this lab, including the download, so I guess it's not that short!

Commons SQL is a new version of Torque (a manual persistence layer). Vic uses RowSets a lot, has one site with 40,000 concurrent Struts users with sub-second response times. He attributes this to rowsets. He says, "To create high-scalable applications, you need to know SQL and use things like RowSet, Ibatis.com, Commons SQL and Scaffolding." I tend to disagree - I think that EJBs (and possibly Hibernate) are your best bet for highly scalable application (i.e. 10,000+ hits per second). If your EJBs are slow, it's probably your code or your appserver. Try EJBs on JBoss and I'm betting you will be pleased. Then again, I've never created a highly-scalable application, and Vic has, so I'm not much of an authority. He, he - he mentions that Castor has lost a lot of mindshare; "Great for development, but not very scalable in production." So true - or at least Roller seems to prove this. From the folks he's talked to, Vic says that TopLink has a horrible reputation.

Hmmmm, interesting. Vic puts all the database connections and CRUD in his ValidatorForms. This is not saying that his bean matches his database tables. I don't know that I'd recommend this, but it certainly might simplify things. However, personally, I'm more comfortable with keeping my POJOs and ActionForms pretty dumb (just getters and setters). He has a DAO that handles CRUD and population of the bean. I wonder where you'd put the business rules in this implementation? In the DAO? If it's in the DAO, what if you have to write a new DAO implementation. For instance, if we used this approach on Roller, we'd have to re-write our business rules for Hibernate and Castor. Ugh.

For testing, he puts a test() method on his beans and uses a Servlet or a plain class with a main() method. Personally, I'd recommend using JUnit and JUnitDoclet (and Ant) to generate and run your unit tests. It's much easier than writing a servlet to test - and can easily separate your tests from your real code. See struts-resume for examples. I'll be releasing AppFuse in the next couple of weeks. This (hopefully) will provide a nice starting point for creating web applications. In reality, if no one uses it, I'll probably be better off (less support). It's been working great for me on my current project and has easily saved us a month of startup time. Right now, appfuse == struts-resume.

Vic mentions using a BaseAction that dispatches to the appropriate method in your subclasses. He says that the only difference between this technique and DispatchAction (or LookupDispatchAction) is you can specify a default method. Here's a tip: use the unspecified method. Here's how to make your edit() method the default:

public ActionForward unspecified(ActionMapping mapping, ActionForm form,
                                 HttpServletRequest request,
                                 HttpServletResponse response)
throws Exception 
{
    return edit(mapping, form, request, response);
}

Vic hints that the next iteration of Basic Portal will be written to use the iBATIS Database Layer and MySQL. Interesting, I thought iBATIS was a company, but nope: it's from the author (Clinton Begin) of JPetstore. On most days, I'd recommend Hibernate here, but I've spent the last 3 days wrestling like mad with it, so I won't. Of course, after leaving work last night, I think I might've figured out the problem. My brain is likely to blame more so than Hibernate.

Ted Husted chimed in at the end and mentioned that he is going to touch on Hibernate next week. Cool!

Posted in Java at Mar 08 2003, 08:13:11 AM MST 4 Comments

Struts-JSF Demo

I've setup another demo - this time it's the struts-example app ported to use JSF and Struts. Nothing ground breaking here that I can tell, and after looking at the code, I don't know what to think of JSF. It seems to make it much harder to code a JSP page.

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="s" uri="http://jakarta.apache.org/struts/tags-faces" %>

<f:use_faces>
<s:html locale="true">
<head>
  <title><
    <s:message key="registration.title.edit"/>
    </title>
  <s:base/>
  <s:stylesheet path="/stylesheet.css"/>
</head>
<body bgcolor="white">

<s:errors/>

<s:form action="/saveRegistration" focus="username"
         onsubmit="return validateRegistrationForm(this);">

  <h:input_hidden id="action" modelReference="registrationForm.action"/>

  <h:panel_grid
           columns="2"
        panelClass="form-background"
       headerClass="form-header"
     columnClasses="form-prompt,form-field">
.
.
.

Ugh, a whole new set of Tag Libraries to learn? Seems like JSF is a lot of bloat, while JSP 2.0 has been made things simpler. One interesting thing is the use of the single-letter (i.e. "h", "s") for the tag libraries. I suggested this a while ago on the struts-dev list, and it looks like it's been implemented. Bravo! I doubt I'm the reason for it, but it's always nice to see your ideas implemented.

I apologize that this site was down most of the day today. It seems that the monitoring/restarting scripts were not running and this should/will be fixed shortly. I need a gig where I can restart this site when it goes down. Anyone know of a way to telnet/ssh via an HTTP Proxy?

Posted in Java at Mar 07 2003, 03:38:29 PM MST 1 Comment

Struts Validator: Validating Two Fields Match

In the Struts Validator Guide, there is a section on how to create a pluggable validator that matches two fields. I've been using this server-side validator (as shown in the example) to do password/confirm password validation. This has worked great for me, but I've always wanted the Validator to have the client-side JavaScript method for it too. I wrote my own that just compared the two fields, but it's not the same as having one rendered for you (from validator-rules.xml). So yesterday, I did some tinkering and figured out how to add the JavaScript method to validator-rules.xml. So here's how to configure the whole thing (most of this is contained in the Validator Guide, save the JavaScript).

How To Add a TwoFields Validator

Step 1: Create a class with a validateTwoFields method. In my code, my class is ValidationUtil and has the following method:

public static boolean validateTwoFields(Object bean, ValidatorAction va,
                                        Field field, ActionErrors errors,
                                        HttpServletRequest request) {
    String value =
        ValidatorUtil.getValueAsString(bean, field.getProperty());
    String sProperty2 = field.getVarValue("secondProperty");
    String value2 = ValidatorUtil.getValueAsString(bean, sProperty2);

    if (!GenericValidator.isBlankOrNull(value)) {
        try {
            if (!value.equals(value2)) {
                errors.add(field.getKey(),
                           Resources.getActionError(request, va, field));

                return false;
            }
        } catch (Exception e) {
            errors.add(field.getKey(),
                       Resources.getActionError(request, va, field));

            return false;
        }
    }

    return true;
}

Step 2: Edit validator-rules.xml to contain the "twofields" rule.

<validator name="twofields" 
    classname="org.appfuse.webapp.util.ValidationUtil" method="validateTwoFields" 
    methodParams="java.lang.Object,
                  org.apache.commons.validator.ValidatorAction,
                  org.apache.commons.validator.Field,
                  org.apache.struts.action.ActionErrors,
                  javax.servlet.http.HttpServletRequest" 
   depends="required" msg="errors.twofields">
    <javascript><![CDATA[
        function validateTwoFields(form) {
            var bValid = true;
            var focusField = null;
            var i = 0;
            var fields = new Array();
            oTwoFields = new twofields();
            for (x in oTwoFields) {
                var field = form[oTwoFields[x][0]];
                var secondField = form[oTwoFields[x][2]("secondProperty")];
            
                if (field.type == 'text' ||
                    field.type == 'textarea' ||
                    field.type == 'select-one' ||
                    field.type == 'radio' ||
                    field.type == 'password') {
            
                    var value;
                    var secondValue;
                    // get field's value
                    if (field.type == "select-one") {
                        var si = field.selectedIndex;
                        value = field.options[si].value;
                        secondValue = secondField.options[si].value;
                    } else {
                        value = field.value;
                        secondValue = secondField.value;
                    }
                
                    if (value != secondValue) {
                    
                        if (i == 0) {
                            focusField = field;
                        }
                        fields[i++] = oTwoFields[x][1];
                        bValid = false;
                    }
                }
            }
            
            if (fields.length > 0) {
                focusField.focus();
                alert(fields.join('\n'));
            }
            
            return bValid;
        }]]></javascript>
</validator>

Step 3: Configure validation for your form in validation.xml:

<field property="password"
     depends="required,twofields">
  <msg
    name="required"
    key="errors.required"/>
  <msg
    name="twofields"
    key="errors.twofields"/>

  <arg0 key="userForm.password"/>
  <arg1
    key="userForm.confirmPassword"
  />
  <var>
    <var-name>secondProperty</var-name>
    <var-value>confirmPassword</var-value>
  </var>
</field>

Where errors.twofields=The '{0}' field has to have the same value as the '{1}' field. An alternative to Step 3 is to use XDoclet to generate your validation.xml. This requires (1) configuring XDoclet (of course) and (2) adding some @struts tags to your form on the setPassword method.

/**
 * Returns the password.
 * @return String
 *
 * @struts.validator type="required" msgkey="errors.required"
 * @struts.validator type="twofields" msgkey="errors.twofields"
 * @struts.validator-args arg1resource="userForm.password"
 * @struts.validator-args arg1resource="userForm.confirmPassword"
 * @struts.validator-var name="secondProperty" value="confirmPassword"
 */
public String setPassword() {
	return password;
}

I've sent this as a proposal to the struts-dev mailing list yesterday, but haven't heard anything yet. Enjoy!

Update: You'll need to update ValidationUtil.java and validator-rules-custom.xml for Struts 1.2. Full files: ValidationUtil.java and validation-rules-custom.xml.

Posted in Java at Feb 26 2003, 12:29:56 PM MST 10 Comments

Struts Update: 1.1 beta 3 to 1.1 RC1

While upgrading Hibernate last night and this morning, I also upgraded Struts. Now I'm having some issues there, so I'd better document those too. First of all, the following line doesn't seem to be rendering any client-side JavaScript anymore:

<html:javascript formName="resumeForm"
      dynamicJavascript="true" staticJavascript="false"/>

Update 1: Nevermind, it seems my Internet connection went dow while starting Tomcat. Since the Digester couldn't validate the Struts' XML configuration files with their respective DTDs, it stopped them from loading.

Update 2: This turned out to be a legitimate issue. Adding cdata="false" to the above tag enabled the browser to see the JavaScript by removing the "<![CDATA[" after <script type="text/javascript">

Revisiting the Hibernate upgrade, I needed to add dom4j.jar to WEB-INF/lib to solve java.lang.NoClassDefFoundError: org/dom4j/Node.

Now I'm getting:

java.lang.NoClassDefFoundError
	at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:571)

What the @#$*%#? hibernate2.jar is in WEB-INF/lib??

Update 3: I had to add cglib.jar to WEB-INF/lib as well. Now back to an issue I'm having with the Validator where client-side validation is working when I click "cancel" (as in, it's disable), but server-side is kicks in. Argghhhh!

Update 4: I found an issue (via the struts-user list) about using the Validator with LookupDispatchAction. It basically doesn't allow you to control validation on a method level, so I've hacked the following workaround.

I changed <html:cancel> to be <html:button> and added onclick="cancel()", where cancel() is the following JavaScript method:

<script type="text/javascript">
function cancel() {
    location.href = '<html:rewrite forward="cancelUser"/>';
}
</script>

The "cancelUser" forward points to "/editUser.do?action=Cancel", which is an action-mapping that doesn't have validation (validation="false") and this hits the "cancel" method on UserAction and routes appropriately.

Phew - I'm beat. I never realized being an upgrade-happy-keyboard-monkey could be so much work!

Posted in Java at Feb 24 2003, 11:10:46 AM MST 4 Comments

Easy Windows Authentication with Tomcat 4.x

The original blog entry by Robert Rasmussen has disappeared from the Internet (cannot find server) so I'm reproducing it here via Google's caching feature. I've made a few changes to pretty up the formatting, but that's about it.


I've been pulled into a little internal project, and one of the requirements is that users should be able to authenticate with their Windows login and password. IIS may or may not be in the picture.

Since the server is a Windows 2000 machine, this turns out to be extremely simple to do thanks to Andy Armstrong's JAAS login modules.

Once you've downloaded the login modules, set your classpath accordingly and make sure that the directory holding NTSystem.dll is in your %PATH% variable. Next, in the "Sample config" folder you'll find a tagish.login file and a java.security.sample file. The last line in the .sample file is significant, and it needs to be in your $JAVA_HOME/jre/lib/security folder (in a file named java.security). You should copy the tagish.login file there as well. If your users will always be logging into the same domain (which is the case in my situation), just set the defaultDomain property in tagish.login, like this:

NTLogin
{
    com.tagish.auth.win32.NTSystemLogin required returnNames=true returnSIDs=false defaultDomain=YOUR_DOMAIN_HERE;
};

Now, all you need to do to use Windows authentication in your webapps is to make one addition to your server.xml file (or to your specific context's definition):

<Realm className="org.apache.catalina.realm.JAASRealm" debug="99"
       appName="NTLogin"
       userClassNames="com.tagish.auth.win32.NTPrincipal"
       roleClassNames="com.tagish.auth.win32.NTPrincipal" />

I'll admit this config is slightly hokey. If you look at the Catalina JAASCallbackHandler (which is hardwired to JAASRealm), the way that I have the realm configured above pretty much counts on the User principal (in effect, the user name) being the first principal returned. This is evil, but it works. It would be nice if either Catalina allowed a pluggable CallbackHandler so that I could take advantage of the NTPrincipal.getType() method or if Andy's code returned subclasses of NTPrincipal like UserPrincipal or GroupPrincipal that I could specify in server.xml.

Once you've got this all configured, the various groups your users belong to equate to role names (so if I belong to an administrators group, my authenticated user will be in role "administrators"), and you can configure security in your webapps using these roles.


Posted in Java at Feb 17 2003, 04:11:52 PM MST 19 Comments

Help: Which servers support HTTP Digest Authentication?

In my security chapter, I am describing HTTP Digest Authentication (please correct me if I'm wrong on any of this).

This (HTTP Digest) authentication mechanism identifies a user based on a username and password, and the client transmits the password in an encrypted form such as SHA or MD5. HTTP 1.1-enabled browsers are required to support it, at least according to this page. According to the Servlet 2.4 spec, it is not currently in widespread use, and therefore Servlet containers are not required to support it.

Now for the part I need help on. Which of the following servers support HTTP Digest? Tomcat, JBoss, Resin, Orion, WebLogic, WebSphere and Sun ONE. To test this, in your web.xml you would configure your <auth-method> to be DIGEST:

<security-constraint>
    <web-resource-collection>
        <web-resource-name>My Application</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>DIGEST</auth-method>
    <realm-name>My Test Application</realm-name>
</login-config>

According to this implementing WebSphere Security article from December 2002, WebSphere 4 doesn't support it. I wonder if version 5 does? Thanks for any assistance you can offer!

Update: I was missing a required element (<web-resource-name>) in the XML above, and I added <realm-name> for display on the dialog box. Tomcat (v4.1.18) supports DIGEST just fine. The dialogs do change between the types though - the differences are below.

HTTP Basic Dialog Screenshot
HTTP Basic Dialog

HTTP Digest Dialog Screenshot
HTTP Digest Dialog

Posted in Java at Feb 13 2003, 06:42:56 AM MST 4 Comments

The war in Iraq

I don't believe it's started yet, but "The war in Iraq" was the only title I could think of. Anyway, I haven't been too concerned with it up to this point. I don't know that I support it, but I don't want to be the victim of chemical or nuclear warfare either. However, it became pretty personal today when I received an e-mail from one of my best friends.

For those of you who didn't already know, I was recently activated and deployed to Kuwait on the seventh of February. Obviously I had to withdraw from school and could be here for up to a year. However, this is very unlikely and I'm speculating and hoping that out unit will be sent home in either May or June.
....
I'm stationed at Al Jaber Air Base approximately 45 miles northwest of Kuwait City. As you can imagine the base in a very busy place right now with units from all four service braches present, along with a small contingency of British troops. I can't disclose too much information about the resources in place or our mission, but I can tell you the base is well fortified and protected. I'm sorry I didn't get in touch with some of you before I left. I had a very limited amount of time between the time I was notified and actually deployed, and was very busy taking care of personal affairs.

Yikes! Now I really hope we don't go to war!

Posted in General at Feb 10 2003, 09:48:28 PM MST 2 Comments

[HTML] Fieldset and Legend

I was reminded today of the <fieldset> and <legend> tags in HTML (BTW, they also work in XHTML). Basically, they are used to draw and label a box around input elements. Here's an example:

<form action="">
<div>
    <fieldset>
        <legend>Name Information</legend>
        <label for="firstName">First Name:</label>
        <input type="text" name="firstName" id="firstName" value="" /><br />
        <label for="lastName">Last Name:</label>
        <input type="text" name="lastName" id="lastName" value="" /><br />
    </fieldset>
    
    <fieldset>
        <legend>Address Information</legend>
        <label for="address">Address:</label>
        <input type="text" name="address" id="address" value="" /><br />
        <label for="city">City:</label>
        <input type="text" name="city" id="city" value="" /><br />
    </fieldset>
</div>
</form>

I added a little CSS for the fieldset and legend tags, and you end up with this:

Name Information

Address Information

Pretty cool eh? The labels end up in the text boxes (on some browsers) courtesy of the the label.js script.

Posted in The Web at Jan 31 2003, 11:47:45 AM MST 2 Comments

ConvertUtils and Indexed Properties

Now I have a new issue with ConvertUtils. I've resorted to creating a Form, rather than generating one from a POJO using XDoclet. In this form, I've added indexed properties, so that properties can be accessed and retrieved with an index.

So now I have getPropertyList() and setPropertyList(ArrayList) on my form. I also have getPropertyList(int index) and setPropertyList(int index, Property prop). However, when I add these methods, my ListConverter.convert method quits working! So now when I call:

BeanUtils.copyProperties(cmcfForm, c);

it returns null for the ArrayLists on my form? I don't get why, esp. since the methods have different signatures. It works fine if I remove the indexed methods.

Update: I solved my problem by removing the getPropertyList(int index) method. I had to add some funky stuff in the reset method of my Form to ready it for Struts auto-population, but it works. Specifically, I had to create an ArrayList for my child, and then populate it with empty child forms. This allowed setPropertyList(int index, Property prop) to work as expected. FYI - I don't think this is a Struts thing, but how webapps work. Anyway, I'm happy with how this works - as I know have indexed properties working for display and saving. Now I have to figure out saving parents/child in Hibernate (I've done it with struts-resume and MySQL, just not with Oracle). I've posted my problem to the Hibernate mailing list if you're really interested in my problem.

Next up, indexed property validation using the Validator. Should be oh so fun...

Posted in Java at Jan 16 2003, 11:03:31 AM MST Add a Comment