Tuesday, January 20, 2009

An interactive Regular Expression Editor

The other day I had to filter an HTTP access log. I figured I could write a dozen or two lines of Java code to do the job, to be written with a dozen or so test-fix cycles. But I also knew that it could be done in just a few lines when using a regular expression. The things that I don't like about using regular expressions in Java code is the fact that the regular expression becomes difficult to edit because the backslash and quote characters need to be escaped with an extra backslash, and secondly I typically need even more test-fix cycles to get the expression right. Thirdly, a non-trivial regular expression becomes difficult to read.

It occurred to me that much of my reservations could be eliminated with an interactive editor that would allow me to edit the regular expression in plain text, and that would show me the results immediately. Since I've been wanting to look at NetBeans' Matisse editor, I thought I'd be able to whip out an editor in less than half an hour, and by doing so, save time not just for the project I was working on, but also for whenever I need to edit a regular expression in the future.

The Matisse editor in NetBeans is as easy as advertised. It took me only minutes to put together a basic editor. To my satisfaction, the time savings in editing regular expressions immediately proved to be enormous!

That was a few weeks ago. This week I was on vacation, and to kill time in the airplane, I've been upgrading this editor further. What I've added is the ability to convert the regular expression in the editor and convert it into Java. That is, the tool now takes care of escaping special characters such as backslashes. The tool is now sort of a code generator. But how about round-trip engineering? I also threw in an option to take a snippet of Java code with a regular expression, and remove the escaping characters. This makes it easy when you later need to revisit a regular expression: you copy the expression from the Java code, paste it into the editor, hit convert and you can edit the plain text regular expression. When done, generate the expression to Java code, paste it back in the Java source file.

Sounds easy, no? What else could you wish for? Of course the whole thing could be integrated into NetBeans and / or Eclipse. Maybe an exercise for another plain trip.

Use the Interactive Regular Expression Editor!

I’ve made the application into a JNLP application, so you can launch it from the browser.

Launch Interactive Regular Expression Editor

Sample screenshot. Click to launch the editor

How do you use the editor? The screen consists of three edit panes. The middle editor is where you edit the regular expression. Any time that you change the expression, the sample input in the top pane is evaluated, and the results are displayed in the bottom edit pane. When you're done editing the expression, click the "generate" button, and Java code will appear in the bottom pane. Copy that code and use it in your Java programs. If you later on need to edit the expression again, simply paste the Pattern definition in the regular expression pane, and hit the "extract" button. The code in the middle pane will be replaced with the clear text version.

Tips for working with Regular Expressions

Here are some tips for working with regular expressions: use the Pattern.COMMENTS flag:  it allows you to  break up your regular expression into multiple lines. Doing so makes it possible to document the parts that the regular expression consists of. This leads me to the second tip: document the parts of your expression so that you'll make it a lot easier on yourself if you later have to revisit the expression. Commenting is easy: use the # sign just like you would use // in Java. Whitespace in the expression is ignored, so if you want to insert a literal space, escape it with a backslash.

Parsing text with regular expressions

I knew that regular expressions are great for matching text, but now that I have the interactive regular expression editor, I also came to appreciate the regular expressions to parse strings -- I mean to extract fragments out of a string. It surely is a lot easier than finding positions in a string and then using String.subString().

For example, here is a regular expression with capturing groups to parse the GlassFish log file:

# Begin marker
\[\#

# Date and time
\|  (\d\d\d\d-\d\d-\d\d)\D(\d\d:\d\d:\d\d\.\d\d\d\D\d\d\d\d)

# Level
\|  (.+?)

# Product
\|  (.+?)

# Category
\|  (.+?)

# Key-value pairs
\|  (.+)?

# Msg text
\|  (.+?)

# Optional stack trace
(^\t at \s \p{javaLowerCase} .*  \.java .*)?

# End marker
\|\#\]

This will result in 8 groups. This looks like a difficult expression, but with the Interactive regular expression editor, it's pretty simple to write this expression.And showing off the Interactive regular expression editor, this is what Java code it produces:

public static Pattern REGEX = Pattern.compile("# Begin marker\r\n" + 
  "\\[\\#\r\n" + 
  "\r\n" + 
  "# Date and time\r\n" + 
  "\\|  (\\d\\d\\d\\d-\\d\\d-\\d\\d)\\D(\\d\\d:\\d\\d:\\d\\d\\.\\d\\d\\d\\D\\d\\d\\d\\d)\r\n" + 
  "\r\n" + 
  "# Level\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Product\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Category\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Key-value pairs\r\n" + 
  "\\|  (.+)?\r\n" + 
  "\r\n" + 
  "# Msg text\r\n" + 
  "\\|  (.+?)\r\n" + 
  "\r\n" + 
  "# Optional stack trace\r\n" + 
  "(^\\t at \\s \\p{javaLowerCase} .*  \\.java .*)?\r\n" + 
  "\r\n" + 
  "# End marker\r\n" + 
  "\\|\\#\\]", 0 | Pattern.COMMENTS | Pattern.DOTALL | Pattern.MULTILINE);

Blogger.com works after all

I had this issue with blogspot where it would insert a great number of line breaks just before a table.  As I found out  (thanks to Edward Chou), this behavior can be turned off in the settings page of Blogspot.

I also found out how to create Atom feeds from labels. The help text on Google is incorrect, and I found out to reference a category like Sun, the corresponding URL is: http://frankkieviet.blogspot.com/feeds/posts/default/-/Sun

Now I’m wondering if I should stick with Blogspot or with Wordpress…

Sunday, December 21, 2008

Blogger.com not a success

I’ve had great trouble to make the previous entry to appear properly.  I’m using raw HTML, but somehow when I publish, the server adds a lot of <br/> tags in my text.

I think I’ll switch to wordpress.com (http://fkieviet.wordpress.com).

The size of Java objects

Here's a blog entry / research note / note-to-self that I wrote months ago, but never found the time to publish.

At JavaOne there was an interesting BOF about Efficient XML. It made me wonder about how efficiently the use of DOM in Java is. To find out, I wrote a small program to find out how many bytes of RAM a Java object uses. The program counts how many objects it can allocate before it runs out of memory. Here's the class:

    public static class H {
public H next;
byte[] b = new byte[8];
}

By changing the size of the byte array and running the program again, the size of an H instance can be calculated, as well as the total memory space available for object allocation in the test program. This number can be used in subsequent runs. Running the program on this trivial class on a Windows machine yielded a size of 16 bytes for each allocation.

    public static class H {
public H next;
}
16 bytes

The VM apparently uses 8 byte alignment, because when another reference is added to the class above, the size does not increase, but it does increase in steps of 8 bytes when more members are added:

    public static class H {
public H next;
public H next1;
}
16 bytes

public static class H {
public H next;
public H next1;
public H next2;
}
24 bytes

public static class H {
public H next;
public H next1;
public H next2;
public H next3;
}
24 bytes

public static class H {
public H next;
public H next1;
public H next2;
public H next3;
public H next4;
}
32 bytes

Hence an empty class takes 8 bytes, and each object references takes 4 bytes. This is much better than what I intuitively expected: underneath there should be at least a pointer to a virtual method table (4 bytes), there should be a pointer to this object from some VM list of objects for memory management. I'd expected that list to be a linked list, and I'd expected that there perhaps would be some additional flags for garbage collection, etc. Clearly the VM does it much more efficiently than I would have done.

Similarly, the size of arrays can be measured. A char[] comes down to 12 bytes plus two times the number of characters, rounded up to an 8 byte boundary. The size of a String object is more interesting: it is 32 bytes plus two times the number of characters; the minimum size is 40 bytes. Hence, a string of 3 characters is 48 bytes, and an eight character string is 56 bytes.

Now let's take a look at XML, a DOM structure to be exact. How much does an element with a text node take, as in this XML snippet?

<root>
<ElementName>1000000</ElementName>
<ElementName>1000001</ElementName>
<ElementName>1000002</ElementName>
...

(line breaks and indentation added for clarity; "ElementName" is a string constant)

Measuring this yields 144 bytes per node. Let's add another child element:

<root>
<ElementName>
<SubEl>1000000</SubEl>
</ElementName>
<ElementName>
<SubEl>1000001</SubEl>
</ElementName>
<ElementName>
<SubEl>1000002</SubEl>
</ElementName>
...

Measuring this yields 200 bytes per repeating element. When we add an attribute the size increases again:

<root>
<ElementName>
<SubEl last="false">1000000</SubEl>
</ElementName>
<ElementName last="false">
<SubEl>1000001</SubEl>
</ElementName>
<ElementName last="false">
<SubEl>1000002</SubEl>
</ElementName>
...

This increases the size to 312 bytes per repeating element

Summarizing the results:

new Object()
8 bytes
""
40 bytes
"123"
48 bytes
"12345678"
56 bytes
int data member
4 bytes
byte data member
1 byte
Object reference data member
4 bytes
char[n]
12 + 2*n
<ElementName>1234567</ElementName>
144 bytes
<ElementName>
<SubEl>1234567</SubEl>
</ElementName>
200 bytes
<ElementName>
<SubEl last="false">1234567</SubEl>
</ElementName>
312 bytes

Indeed, DOM is not very efficient with respect to memory usage. The last XML snippet was only 62 single byte characters. The information content is actual a lot less: since ElementName, SubEl, and last are constant, they could be replaced with a reference. Without using schema information, the information content can be encoded with about 25 bytes. With JAXB it can be done with 88 bytes.

Hello world

This is my first blog entry on blogger.com. It's really a continuation of my other blog, the one that I started at http://blogs.sun.com/fkieviet. Why did I start a new blog? Blogs at blogs.sun.com are tied to Sun Microsystems, my employer. With the world in economic turmoil, Sun included, I felt it was a good idea to have a blog not tied to my employer. A few words about me: I'm a software engineer. Building software has been my hobby since the Commodore 64. I'm glad that I've been able to turn this hobby into a full time profession. I currently work as a Senior Staff Engineer at Sun Microsystems. There I work as a lead in the SOA/Business Integration group, and am a contributor to OpenESB, an open source platform for Integration and SOA.

It's been a long time since my last blog entry on blogs.sun.com. Been busy -- work has been piling up, and it's difficult to justify taking time to write a blog when people are waiting on me for work to be finished. (And that's another reason to start this blog instead of continuing on blogs.sun.com.) How I find the time to write this then? I'm on vacation this week!

Monday, May 19, 2008

JavaOne 2008


It's a week after JavaOne 2008 now. I finally have time to post a blog. I've been extremely busy for and before JavaOne: not only with the presentations that I gave at JavaOne, but also because the Java CAPS 6 code freeze was the week before JavaOne.

At JavaOne I gave three presentations:

For Java University (the day before JavaOne), I presented a part of Joe Boulenouar's class "How Java EE 5 and SOA Help in Architecting and Designing Robust Enterprise Applications". In my part I covered ESBs, JBI and Composite Applications.


A technical session: TS-5301 Sun Java Composite Application Platform Suite: Implementing Selected EAI Patterns. I presented this with Michael Czapski, a colleague in Sun's field organization in Australia. He's also the author of the book Java CAPS Basics: Implementing Common EAI Patterns. In this session we went over a number of EAI patterns from Hohpe and Woolf's book and showed that when you use the right Integration Middleware, you use these patterns almost without realizing it.


A Birds-of-a-feather session: BOF-6211: Transactions and Java Business Integration (JBI): More Than Java Message Service (JMS). I presented this with Murali Pottlapelli, a colleague in Monrovia. Since there was interest in the slides that we presented, and because unlike Sessions, the slides of BOFs are not made available by the JavaOne organization, you can download the slides of Transactions and JBI: More Than JMS from my blog. I also recorded the sound using my MP3 player, but the quality of the recording is pretty bad. Nevertheless, I've also uploaded the mp3 of Transactions and JBI: More Than JMS.


What's next? Now that CAPS 6 is almost out of the door, we're going to focus on the next release. Even more than in the past, we'll be doing this in open source. More to come!

Saturday, October 6, 2007

Server side Internationalization made easy

Last year I wrote a blog entry on my gripes with Internationalization in Java for server side components. Sometime in January I built a few utilities for JMSJCA that makes internationalization for server side components a lot easier. To make it available to a larger audience, I added the utilities to the tools collection on http://hulp.dev.java.net. What do these utilities do?

Generating resource bundles automatically

The whole point was that when writing Java code, I would like to keep internationalizable texts close to my Java code. Rather than in resource bundles, I prefer to keep texts in my Java code so that:

  1. While coding, you don't need to keep switching between a Java file and a resource bundle.
  2. No more missing messages because of typos in error identifiers; no more obsolete messages in resource bundles
  3. You can easily review code to make sure that error messages make sense in the context in which they appear, and you can easily check that the arguments for the error messages indeed match.

In stead of writing code like this:

        sLog.log(Level.WARNING, "e_no_match_w_pattern", new Object[] { dir, pattern, ex}, ex);

Prefer code like this:

        sLog.log(Level.WARNING, sLoc.t("E131: Could not find files with pattern {1} in directory {0}: {2}"
          ,
dir, pattern, ex), ex);

Here's a complete example:

public class X {
    Logger sLog = Logger.getLogger(X.class.getName());
    Localizer sLoc = Localizer.get();
    public void test() {
        sLog.log(Level.WARNING, sLoc.t("E131: Could not find files with pattern {1} in directory {0}: {2}"
          ,
dir, pattern, ex), ex);
    }
}

Hulp has an Ant task that goes over the generated classes and extracts these phrases and writes them to a resource bundle. E.g. the above code results in this resource bundle:

# DO NOT EDIT
# THIS FILE IS GENERATED AUTOMATICALLY FROM JAVA SOURCES/CLASSES
# net.java.hulp.i18ntask.test.TaskTest.X
TEST-E131 = Could not find files with pattern {1} in directory {0}\\: {2}

To use the Ant task, add something like this to your Ant script, typically between <javac> and <jar>:

<taskdef name="i18n" classname="net.java.hulp.i18n.buildtools.I18NTask" classpath="lib/net.java.hulp.i18ntask.jar"/>
<i18n dir="${build.dir}/classes" file="src/net/java/hulp/i18ntest/msgs.properties" prefix="TEST" />

How does the Ant task know what strings should be copied into the resource bundle? It uses a regular expression for that. By default it looks for strings that start with a single alpha character, followed by three digits followed by a colon, which is this regular expression: [A-Z]\\d\\d\\d: .\*.

Getting messages out of resource bundles

With the full English message in the Java code, how is the proper localized message obtained? In the code above, this is done in this statement:

sLoc.t("E131: Could not find files with pattern {1} in directory {0}: {2}", dir, pattern, ex)

The method t takes the string, extracts the message ID out of it (E131) and uses the message ID plus prefix (TEST) to lookup the message in the right resource bundle, and returns the substituted text. The method t lives in class Localizer. This is a class that needs to be declared in the package where the resource bundles are placed. The class derives from net.java.hulp.i18n.LocalizationSupport. E.g.:

public static class Localizer extends net.java.hulp.i18n.LocalizationSupport {
    public Localizer() {
        super("TEST");
    }
    private static final Localizer s = new Localizer();
    public static Localizer get() {
        return s;
    }
}

The class name should be Localizer so that the Ant task can be extended later to automatically detect which packages use which resource bundles.

Using the compiler to enforce internationalized code

It would be nice if the compiler could force internationalized messages to be used. To do that, Hulp includes a wrapper around java.util.logging.Logger that only takes objects of class LocalizedString instead of just String. The class LocalizedString is a simple wrapper around String. The Localizer class produces these strings. By avoiding using java.util.logging.Logger directly, and instead using net.java.hulp.i18n.Logger the compiler will force you to use internationalized texts. Here's a full example:

public class X {
    net.java.hulp.i18n.Logger sLog = Logger.getLogger(X.class);
    Localizer sLoc = Localizer.get();
    public void test() {
        sLog.warn(sLoc.x("E131: Could not find files with pattern {1} in directory {0}: {2}"
          ,
dir, pattern, ex), ex);
    }
}

Logging is one area that requires internationalization, another is exceptions. Unfortunately there's no general approach to force internationalized messages in exceptions. You can only do that if you define your own exception class that takes the LocalizedString in the constructor, or define a separate exception factory that takes this string class in the factory method.

Download

Go to http://hulp.dev.java.net to download these utilities. The jars (the Ant task and utilities) are also hosted on the Maven repository on java.net.