A Java InputVerifier for Email Addresses

Every good application should verify that data which must conform to a specific pattern actually does when it is being entered. For example email addresses, social security numbers, phone numbers, IP addresses, etc all have basic formats that they should conform to. Fortunately, in Java Swing applications the javax.swing.InputVerifier allows us to easily do this.

The InputVerifier class itself is designed such that the programmer must create a subclass of it and override the verifyText method. This verifyText method has a signature that looks like:

protected boolean verifyText(String textToVerify)

The verifyText method is designed to take in a text string, and the programmer writes the logic to verify if the text is of the format that is it should be. If so, you return true. If not, return false. It’s as simple as that.

Once your custom InputVerifier class is created, you attach it to a JComponent through the JComponent’s setInputVerifier method. By attaching the InputVerifier to the JComponent (such as a JTextField), the JComponent will call the InputVerifier verifyText method when the user tries to leave the field. If the verifyText returns true then the request for the focus transfer will be granted. Otherwise, the field can be highlighted in a colored border to signify an error and the focus transfer request is denied.

Below I present my simple EmailInputVerifierClass which verifies that the email address entered into the field is of the proper format. If you type in an invalid email address, such as test@ and then press tab, you will see the JTextField draw a red border around it and your focus will still be in that field. If you type in a properly formatted email address, such as test@test.com you will be able to navigate out of the field.

The example below is a self contained example of my EmailInputVerifierClass. Simply compile and run it for a demonstration of how this InputVerifier works.

/**
 * Copyright (c) 2002-2004 by Timothy E. Archer.  All rights reserved.
 *
 * $Id: EmailInputVerifier.java,v 1.1 2004/07/07 02:54:58 tima Exp $
 *
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL TIMOTHY E. ARCHER BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 *(INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */
package com.tima.gui.inputverifier;

import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.util.regex.*;

/**
 * An input verifier to verify email addresses.
 * This accounts for email address with a 3 character extension, 
 * or a 2 character country code appended. 
 * Does not validate that email contains valid URL type (.com, .gov, etc.) 
 * or valid country suffix. 
 * This will also validate email addresses that are at an IP address, 
 * such as tima@127.0.0.1
 *
 * @author  Tim Archer 08/21/03
 * @version $Revision: 1.1 $
 */
public class EmailInputVerifier extends StdStringInputVerifier {
   
    /**
     * Verify the specified text. 
     *
     * @param textToVerify The text that is to be verified.
     * @return boolean true when valid, false when invalid
     *
     */        
    protected boolean verifyText(String textToVerify) {
        //
        //Determine if this matches an email regular expression or not
        //Accounts for email with country appended. 
        //Does not validate that email contains valid URL
        //type (.com, .gov, etc.) or valid country suffix. 
        //This will also validate email addresses 
        //that are at an IP address, such as tima@127.0.0.1
        //
        Pattern p = Pattern.compile("([a-zA-Z/\\d_\\\\\\.]+@([a-zA-Z\\d_\\\\\\.]+)"+
                                    "(\\.[a-zA-Z\\d]{2,4}))|([a-zA-Z/\\d_\\\\\\.]+@)"+
                                    "[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}\\.[\\d]{1,3}");
        
        Matcher m = p.matcher(textToVerify);

        //
        //If the text matches the acceptable pattern then we set the value 
        //of the component to the text. 
        // Setting the value only does anything if this verifier is bound 
        //to a JFormatted text field.
        //
        if (m.matches()) {
            setComponentValue(textToVerify);
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * Main Unit test procedure
     * @param args Command line arguments
     *
     */
    public static void main(String args[]) {
        //
        //Set the appropriate initial look and feel
        //
        try {
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
        } catch (Exception e) {
            System.err.println("An error occurred setting the look and feel. "+
            e.toString());
        }
        
        try {
            
            JFrame jf = new JFrame();
            JPanel jp = new JPanel();
            JTextField txt = new JTextField();
            txt.setPreferredSize(new Dimension(150, 24));
            txt.setInputVerifier(new EmailInputVerifier());
            jp.add(txt);

            JFormattedTextField ftxt = new JFormattedTextField();
            ftxt.setPreferredSize(new Dimension(150, 24));
            ftxt.setInputVerifier(new EmailInputVerifier());
            jp.add(ftxt);
            
            jf.getContentPane().add(jp);
            jf.setVisible(true);
            jf.pack();
            jf.setSize(300, 300);
            jf.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        } catch (Exception e) {
            System.err.println("Error: "+e.toString());
        }        
    }
    
}


v2.0