advertisement
javaboutique
Search Tips
Articles  |   Tutorials  |   Reviews  |   Tools  |   by Category  |   by Date  |   by Name  |   Submit  |   Source  |   Forums  |  
javaboutique
Browse DevX


Partners & Affiliates











advertisement

Tutorials : Defining Technical Standards in Java Development :

Validation Errors

If your application has a user interface, then you'll need to standardize the way validation errors are handled and reported. If you've got a Web interface built with Struts, you could use the Struts Validator. If you plan to code your own validation modules, then do it early on and include ready-to-use code for at least these checks:
  • Optional/mandatory
  • Length of a string
  • Numeric (whole and fractions)
  • Numeric ranges
  • A list of (string) values
  • Dates

Bug/Issue Tracking

When you place your application in production, it's, of course, necessary to have a bug registration and tracking system available. However, issues of all sizes will pop up during application development, and it's easy to forget them if you don't have a simple and reliable way of writing them down. Anything is better than nothing, even a Word document can be used. For more serious issue tracking, take look at tools like Bugzilla.

For each issue, enter:

  • Issue date
  • Name of the person registering the issue
  • Priority-level
  • Person to whom the issue is assigned/li>
  • A short description
  • A longer, detailed description
  • Issue status (i.e., "OPEN," "WORKING," "CLOSED")

Building a Logging Framework

The well known logging framework, Log4J, and also the logging API in JDK 1.4, both demand that you select a logging severity level— "debug," "info," "warning," and "error." It's important to consider which logging severity should be used in every situation, but it would be nice if severity levels could be defined in a configuration file, like so many other application parameters. The requirements for such a solution would be:
  • The configuration file should be in XML format.
  • Every logging message should be identified by a key.
  • Every message should contain the severity level and a message text.
  • It must be possible to insert actual data values in the message text.
The XML format might look like this:

<?xml version="1.0" encoding="UTF-8"?>
<messages>
  <message>
    <key>TestINFO</key>
    <severity>INFO</severity>
    <text>This is a test info message</text>
  </message>
  <message>
    <key>TestWARNING</key>
    <severity>WARNING</severity>
    <text>This is a test warning message</text>
  </message>
  <message>
    <key>TestERROR</key>
    <severity>ERROR</severity>
    <text>This is a test error message with data: {0}</text>
  </message>
</messages>

The last message shows the syntax for inserting actual data values in the message text. {0}, {1}, and so on are be used to mark insertion points in the text.

A nice API is easy to make, based on such a message file:

logger.log("TestINFO");
logger.log("TestWARNING");
logger.log("TestERROR", "my data");

The first parameter to the log method is the key from the message file. If the message needs data inserted, then these data values are specified as extra parameters.

How can you buils such a logging API? Well, you can use the Log4J package, the JDK 1.4 logging API, or you can even build on top of another layer like the Jakarta Commons Logging package. To learn how to make a real implementation, take a look at the following example using the JDK 1.4 API.

The class, called MyLogger, which offers the log-methods will have these responsibilities:

  • To read and store data from the XML message file.
  • To fetch the proper message when a log method is called.
  • To handle substitution of data in the message texts.
Many utilities are available to read and parse the XML file. This example uses the Commons Digester package. This is a good choice for this example because the Commons Digester makes it easy to build an object structure that suits this API's needs. To learn more about using Digester, take a look at the article "Digesting XML Documents."

The XML file should only be read once, and it's convenient to store the messages in a HashMap, with the message-key as the key to the HashMap. So, the first time the MyLogger class is loaded, it will read the XML file and create the HashMap:

. . .
private MyLogger() {}

// A JDK logger for internal use
private static final Logger basicLogger = Logger.getLogger(MyLogger.class.getName());

// The message file 
private static File input = new File("logMessages.xml");

// All log messages
private static Messages messages = getMessages();

// The "real" logger
private Logger logger;

private static Messages getMessages() {
  Digester digester = new Digester();

  // Setup Digester 
  digester.addObjectCreate("messages", "dk.hansen.Messages");
  digester.addObjectCreate("messages/message", "dk.hansen.Message");
  digester.addBeanPropertySetter("messages/message/key");
  digester.addBeanPropertySetter("messages/message/severity");
  digester.addBeanPropertySetter("messages/message/text");
  digester.addSetNext("messages/message", "addMessage");

  // Parse the XML message file
  Messages messages = null;
  try {
    messages = (Messages) digester.parse(input);
  } catch (IOException e) {
    basicLogger.severe("The log messages file could not be read. Exception was: " + e);
    System.exit(1);
  } catch (SAXException e) {
    basicLogger.severe("Failed reading the log messages file. Exception was: " + e);
    System.exit(1);
  }
  return messages;
}
. . .

The complete class and all helper classes are available for download in the resources section at the end of the article.

When MyLogger is loaded, it calls getMessages, which parses the XML message file and builds a HashMap in Messages. The objects in the HashMap are instances of the Message class, which is a simple bean that holds data for one message. As you can see from the code above, both Message and Messages are specified in the setup to Digester.

When MyLogger needs a message from the HashMap, it calls the getMessage method in the Messages class:

public Message getMessage(String key) {
  Message message = (Message) messages.get(key);
  if (message == null) {
    message = new Message(key, "ERROR", "Missing message for key="
	+ key + ". Severity set to ERROR");
  }
  return message;
}

Should it happen that a key cannot be found in the HashMap, a new Message object is created with severity "ERROR," and some explanatory text (as shown above). A better solution might be to have a default message specified in the XML file as well. Be careful to also handle the case where this default message is absent in the file!

To use the logging system, you must first create an instance of MyLogger. This instance can be kept as a static object, in the same way that you use Log4J or the JDK Logging API. Here's a simplified example:

private static MyLogger logger = MyLogger.getLogger(UseMyLogger.class.getName());
. . .
public static void main(String[] args) {
  logger.log("TestINFO");
  logger.log("TestWARNING");
  logger.log("TestERROR", "some data");
}

The getLogger method works like this:

public static MyLogger getLogger(String className) {
  MyLogger myLogger = new MyLogger();
  // Insert a JDK logger in the class
  myLogger.logger = Logger.getLogger(className);
  return myLogger;
}

The only thing left now is to code the log method. Here's a general method that accepts an array with parameters:

public void log(String key, String[] parameters) {
  // Get the message for the map
  Message message = messages.getMessage(key);

  // Get message text 
  String text = message.getText();
  // Any substitution?
  if (parameters != null && parameters.length > 0)
    text = MessageFormat.format(text, parameters);

  // Get severity
  String severity = message.getSeverity();
  if (severity.equals(Message.INFO))
    logger.info(text);
  else if (severity.equals(Message.WARNING))
    logger.warning(text);
  else
    logger.severe(text);
}

The message substitution is very simple since you can use Java's MessageFormat API to do the work.

Make sure to include code to handle a case where the message severity is spelled incorrectly in the message file. The most straightforward would probably be to add a DTD or a style sheet to the XML file and have it validated during parsing, but I have not succeeded in doing so. If any of you have a suggestion for how to do this I'd be happy to receive an e-mail.

Working Efficiently

It’s important to any project for developers to work efficiently. One way of achieving this is to document and standardize the tasks involved in every application: logging, error handling, testing, etc. By doing so, developers can concentrate on working out the business tasks, which should always be a developer's main focus.

Happy coding!

Other Resources

How to Add Java Applets to Your Site

New on the Java Boutique:

New Review:

Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling API boasts simplicity, ease-of-integration, a well-rounded feature set, and it's free!

New Applet:

Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA sequences into three useful formats.

Elsewhere on internet.com:

WebDeveloper Java
Lots of Java information on webdeveloper.com

WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.

ScriptSearch Java
Hundreds of free Java code files to download.

jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.

 DevX Skillbuilding from IBM developerWorks
 RIA Run Contest: Build Next-Gen Apps in Microsoft Silverlight 2
 Avaya DevConnect Center
 Intel Go Parallel Portal
 Internet.com eBook Library
 Microsoft RIA Development Center
 Destination .NET
XML error: not well-formed (invalid token) at line 53
advertisement
Receive Articles via our XML/RSS feed
Receive Articles via our XML/RSS feed

JavaBytes
Internet Cyclone
This powerful, easy-to-use, internet optimizer is for Windows 95, 98, ME, NT, 2000 and XP. It's designed to automatically optimize your Windows settings, boosting your Internet connection up to 200%.

Alfresco's Latest ECM: Prying Open a Sector?
SaaS Tool Offers Custom Database Development
Microsoft’s Automated Agent: Can We Talk?
Borland Finally Sells CodeGear
Red Hat Heads for the JON 2.0
Out with the Old, in with the New at JavaOne
Trolltech Expands WebKit Footprint
Oracle: Eating its Own Open Source Food
Big Money and Open Source May Not Compute
Open Source Embrace Gives Sun New Fans

Getting Started with TBB on Windows
Moving to VoIP: Should You Go It Alone?
Introduction to the WPF Command Framework
7.0, Microsoft's Lucky Version?
Will Hyper-V Make VMware This Decade's Netscape?
Eliminate Fragmentation Frustration with Netbiscuits
Taming Trees: Building Branching Structures
Clean Up Function Syntax Mess with decltype
Sutter Speaks: The Future of Concurrency
INTEL SCAVENGER HUNT, LENOVO X300 AND APPLE IPOD TOUCH GIVEAWAY (the "Giveaway")

Advertising Info  |   Member Services  |   Contact Us  |   Help  |   Feedback  |   Site Map  |   Network Map  |   About



JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

Solutions
Whitepapers and eBooks
Microsoft Article: Will Hyper-V Make VMware This Decade's Netscape?
Microsoft Article: 7.0, Microsoft's Lucky Version?
Microsoft Article: Hyper-V--The Killer Feature in Windows Server 2008
Avaya Article: How to Feed Data into the Avaya Event Processor
Microsoft Article: Install What You Need with Windows Server 2008
HP eBook: Putting the Green into IT
Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
Avaya Article: Setting Up a SIP A/S Development Environment
IBM Article: How Cool Is Your Data Center?
Microsoft Article: Managing Virtual Machines with Microsoft System Center
HP eBook: Storage Networking , Part 1
Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
Intel Video: Are Multi-core Processors Here to Stay?
On-Demand Webcast: Five Virtualization Trends to Watch
HP Video: Page Cost Calculator
Intel Video: APIs for Parallel Programming
HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Sun Download: Solaris 8 Migration Assistant
Sybase Download: SQL Anywhere Developer Edition
Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
Red Gate Download: SQL Compare Pro 6
Iron Speed Designer Application Generator
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
IBM Article: Collaborating in the High-Performance Workplace
HP Demo: StorageWorks EVA4400
Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
Microsoft How-to Article: Get Going with Silverlight and Windows Live
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES