Posts tagged ‘java’

Grails Podcast Mentions My Closure Post

Like other bloggers with an ego, I have Google Alerts set up to let me know when someone mentions me or my blog anywhere that Google knows about. I got an alert yesterday letting me know that I’d been mentioned on the latest episode of the Grails Podcast. How cool is that? Specifically, they mentioned my Groovy Sql Closure Examples post. Thanks, Glen and Sven, for the podcast love. :-)

I’ve been spending some time with Grails latest and have been really impressed with it. I spent a couple of hours on Saturday playing with it, seeing how much of my Rails knowledge was applicable to Grails. Quite a bit of it, actually. I really like what I’ve seen of Grails, so far. I’d probably have to use it on a real project to really get a feel for it, but it looks like it would be a nice environment to work in.

Dear Apple: Some Java Love, Please?

I love your machines. Truly, I do. Back in 1988 I bought a toaster-model Mac SE, with one megabyte of RAM, and I loved it. It only had a nine inch, black-and-white screen, and I loved it. For various reasons, I sort of lost the love for a while, until 2006. I acquired an iBook G4 in a hardware trade with a friend and I quickly became hooked on the sweet goodness that is OSX. That was in August, 2006. Two months later I bought a Mac Pro, which I love so much I sometimes feel the need to kiss it goodnight.

But there’s one thing about the Mac that bothers me: lousy Java support. Sun handles JDK releases for Windows and Sun machines and every Linux system on the planet. Yet, for some inscrutable reason, you have decided to handle Java for OSX yourself. And, not to be rude, but I just have to say that you suck at maintaining Java for the Mac!!! Let me ’splain.

Sun released the first version of Java 6 for Windows, Linux and Solaris in December 2006. Two days ago, Sun released the tenth update for Java 6, again for Windows, Linux and Solaris. On September 24, 2008, you guys released Java 6_07, which was nice to finally get it, but it’s only for Leopard systems and it’s only for 64bit machines. My Mac Pro is 64bit and Leopard, but my iBook is 32bit and can’t run Leopard. And what about the tons of other developers out there who don’t meet these requirements? I can’t think of a good reason you have restricted Java 6 in this way, but I can think of a few bad reasons. Probably the easiest to come up with is that you’re trying to force Java developers to buy more expensive Apple machines.

What’s really funny about the crappy state of Java on the Mac is comments from Sir Steve himself, several years ago. I was at JavaOne in 2000. Sir Steve was the Mystery Date™ for the keynote speech on Day One of the conference. His Steveness trots on stage, clad all in black, and proclaims that he was going to make the Mac the ultimate platform for Java developers. Apple would be bundling Java 2 SE with OSX. And the crowd went wild. And he did make the Mac a great Java development platform. For a while. I can’t tell you how many conferences I went to after that, Java conferences, where the majority of developers were toting Mac laptops around. 

But then you started falling behind with the releases. And then you started restricting which of your users were worthy of getting updates. What gives, Apple? If Sun can release timely versions of Java that run on a ton of disparate systems, why can’t you release timely versions that run across your own hardware family? It’s absurd that you are only supporting 64bit Leopard system for the latest versions of Java, and even then you make us wait forever. 

So, how can we fix this? I think you should go back to Sun and say something like,

I’m sorry, Sun. We like to meticulously control everything, but in this case, that desire has caused us to hose down our customers. They’re not happy, and we can’t figure out a good way to appease them. Please, Sun, would you take over maintenance of the JDK/JRE for OSX? We’d really appreciate it.

Or something like that. Something needs to happen soon. Although the lastest version sounds like just another update to Java6, there are actually lots of new features that are going to really improve Java. Except those of us on the Mac have to wait for some unknown amount of time before you guys release your own version. And if we’re not 64bit Leopard, we’re screwed.

Please, Apple, help us out with some timely Java love, OK?

Sincerely,

Joey Gibson

Groovy Sql Closure Examples

My post about closures last week generated quite a bit of traffic and comments, both positive and negative. I decided to followup on that post with a few examples of how to add a method that I believe is missing from Groovy’s Sql class that will execute a closure, and will guarantee that the connection gets closed, no matter the outcome of the closure’s contents.

I’m going to discuss three ways to add a method that does what we want:

  1. Wrap the existing class
  2. Modify the MetaClass of the existing class
  3. Use a Category

All three of these are extremely simple. I think it mostly comes down to preference as to which one you might want to use. Before we get started, let me say that Groovy is optionally-typed. What this means is that you don’t have to declare variable types if you don’t want to. I like not having to declare variable types, so I have not done so in any of these example. You might hate that, and think it sloppy/heretical/evil. If so, and you choose to use any of the code I present, feel free to declare your variable types. So, with that out of the way, let’s start with the wrapping approach.

Wrap the existing class

First, we’ll create a class called ISql that wraps an instance of Sql.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import groovy.sql.Sql
 
public class ISql
{
   public static newInstance(url, user, pass, driver, closure)
   {
     def con
 
     try
     {
       con = Sql.newInstance(url, user, pass, driver)
 
       if (closure)
       {
         closure.call(con)
       }
     }
     finally
     {
       con.close()
     }
   }
}

You can see that we’ve got a class with a single static method called newInstance, to mimic the standard way of creating a Sql instance. It takes the same four arguments that the Sql class does, but it takes one extra argument: a Closure. All this method does is create an instance of Sql, executes the closure, passing in the Sql instance, and then ensures that the connection gets closed, through the call to con.close() in the finally block. To use this class, you can do this

1
2
3
4
5
ISql.newInstance(url, user, pass, driver) {con ->
  con.eachRow("select * from Foo") {row ->
    println "ID: $row.id"
  }
}

In this test, we call our special newInstance method, passing in the connection parameters, and then tacking on a closure at the end. Inside the closure, we get access to the connection through the con variable, and then we can do anything we would normally do with a Sql connection. In this case, we execute a query and print the value of each row’s Id column. Nothing too exciting, but it works. No matter what happens inside those closures, the connection is guaranteed to be closed at the end. 

Modify the MetaClass of the existing class

The second way to do this is to add a method to Groovy’s built-in Sql class by modifying its MetaClass. Here’s the code to do that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Sql.metaClass.static.newInstance << {url, user, pass, driver, closure ->
  def con
 
  try
  {
    con = Sql.newInstance(url, user, pass, driver)
 
    if (closure)
    {
      closure.call(con)
    }
  }
  finally
  {
    con.close()
  }
}

Everything after line three is exactly like what we did in the wrapping approach. The magic occurs in line one. In that line, we get the Sql class’ MetaClass, and then grab the static property of the MetaClass. We then add another method called newInstance by using the << operator to append a closure taking the right number of arguments. To call it, we have code that looks almost identical to our last example, but instead of using the ISql class, we’re using Groovy’s built-in Sql class with our special method included.

1
2
3
4
5
Sql.newInstance(url, user, pass, driver) {con ->
  con.eachRow("select * from Foo") {row ->
    println "ID: $row.id"
  }
}

You can see that with the exception of the missing ‘I’, the code is exactly the same.

Use a Category

Groovy also provides something called Categories that allow you to add methods to existing classes, but they are only usable while the Category is in use. It’s somewhat confusing, and is my least favorite approach, but here’s how it works. You create a class with a static method taking the arguments you want to pass, plus an extra argument, usually called “self”, that will get passed the thing on which you’re calling this method. This special required argument must be the first in the list. Here’s our category called SqlHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import groovy.sql.Sql
 
public class SqlHelper
{
  def static newInstance(self, url, user, pass, driver, closure)
  {
    def con
 
    try
    {
      con = Sql.newInstance(url, user, pass, driver)
 
      if (closure)
      {
        closure.call(con)
      }
    }
    finally
    {
      con.close()
    }     
  }
}

Notice that the first parameter to newInstance is that special “self” variable. If you don’t include that argument in the method declaration, calling the method won’t work. I should add that you don’t actually pass any argument for “self” yourself when calling the method. This is handled by Groovy, in much the same way Python programs stuff values into a method’s “self” argument. So, to use the category, you have to wrap your operation in a “use” block

1
2
3
4
5
6
7
8
use(SqlHelper)
{
  Sql.newInstance(url, user, pass, driver) {con ->
    con.eachRow("select * from Foo") {row ->
      println "ID: $row.id"
    }
  }
}

Here, we declare that we want to use SqlHelper by using a “use” block that contains the category in parentheses. Within the curly brackets of the use (also a closure), Groovy will see our call to newInstance on the Sql class, and will figure out that we want to use the one in the category. It will then call that method, passing the Sql class as the self parameter, and all our other arguments as you would expect. With the exception of having to use the “use” block, this code looks just like the second example.

When Something Goes Wrong

I said that in each case, no matter what happens in the closure, the connection was guaranteed to get closed. Someone commented on the last post that he was concerned that the use of closures would somehow obscure where the problem occurred. It doesn’t. You still get the line number of where things went pear-shaped. For example,

35
36
37
38
39
40
41
42
43
44
45
46
try
{
  ISql.newInstance(url, user, pass, driver) {con ->
    con.eachRow("select * from boingo") {row ->
      println "ID: $row.id"
    }
  }
}
catch (Exception e)
{
  e.printStackTrace()
}

In this case, there is no table called “boingo,” and so when I execute this code I get an exception thrown, and from the stack trace, I can see where the problem occurred:

java.sql.SQLException: Invalid object name 'boingo'.
  ...
  at groovy.sql.Sql.eachRow(Sql.java:559)
  at groovy.sql.Sql.eachRow(Sql.java:541)
  ...
  at ISqlTest$_testBadness_closure2.doCall(ISqlTest.groovy:38)

I cut some of the stack dump out for brevity, but you can see that it was a java.sql.SQLException that was thrown, and it references line 38 in the code. That just as much information as you’d get from straight Java in this case, so you should be able to diagnose the problem.

Other Approaches

I should add that you should be able to subclass the Sql class, adding a static method called newInstance that accepts a closure in addition to the four connection arguments. I tried that, but it didn’t work. Actually, it partially worked. The newInstance method I added worked like a champ, but the original newInstance method was no longer visible. I don’t know why, but that’s the behavior I was seeing. It might just be that I’m not familiar enough with Groovy, but I couldn’t get it to work. If anyone knows why, let me know.

To Sum Up

So, those are three ways to add a closure-with-guaranteed-connection-closing method to Groovy. Which of these approaches should you use? Personally, I prefer the second way, adding a method to Sql through its metaclass, but it really comes down to preference. Whichever way you choose should be documented so your teammates understand what’s going on.

I hope that someone on the Groovy team will realize that they left this functionality out of the previous versions and decide to add it for a future version. It really strikes me as odd that this is not in there already, since it seems to fit so well with the language. The fact that various methods inside the Sql class take closures, but not the construction method, makes me think it was just an oversight.

Why I Love Closures

I’ve been a big fan of closures for years. I was first introduced to them in Smalltalk, where they were just called blocks. Ruby has them and also calls them blocks. Java does not have them, though there are proposals (such as this one) to add them to a future version of the language. Groovy has them now, and while they aren’t as shiny as those in Ruby, they do work.

So what’s so great about closures anyway? They are blocks of code that retain links to things that were in scope when they were created, but they also have access to things that are in scope when they execute. They can be passed around, usually to methods that will execute them at a later time, in a possibly different context. That doesn’t sound all that exciting, but what is exciting is when the language in question lets you pass in a closure to do some work, and then cleans up after you when the work is done. Here’s an example of some Ruby code that I have written in tons of scripts.

1
2
3
4
5
6
7
8
9
10
11
12
count = 0
 
DBI.connect(*CREDENTIALS) do |con|
  File.open("results.txt", "w") do |file|
    con.select_all(sql) do |row|
      file.puts "... interesting data from the query ..."
      count += 1
    end
  end
end
 
puts "Total records: #{count}"

What that code does is declare a variable, count, that will be used to keep track of how many records we processed. It then connects to a database, creates a file called “results.txt,” executes a SQL select, writes some of the data from each row to the file and increments the count variable. At the end, we print out the count variable.

There are three closures in that bit of code. They begin on lines 3, 4 and 5, respectively. The first connects to the database. The second creates the output file and the third performs a SQL select, writes the output and bumps the counter. Rather concise code, don’t you think?

Do you notice anything missing from this code? Two very important things are not there: closing the file and closing the database connection. I said these bits are not there, but they really are. The block version of DBI.connect ensures that no matter how events unfold, either successfully or with an exception, the database connection will get closed. Similarly, the File.open ensures the file will get closed. This is one of the most beautiful aspects of languages that support closures.

As I said earlier, Groovy has closure support baked in. While I’m not completely thrilled with the syntax, it’s close enough to Ruby’s that it’s not bad. As I was writing this post, I was surprised to discover that Groovy’s SQL module doesn’t support a closure passed to the connection, which means you still have to worry about closing your connection when you’re done. Anyway, Groovy’s file-writing idiom looks like this

1
2
3
new FileWriter("results.txt").withWriter {writer ->
  writer.write("... interesting data ...")
}

I don’t really like using the -> as the closure parameter delimiter; I’d rather use a | (pipe symbol) like Smalltalk and Ruby do. Regardless of syntax differences, that’s how you write the file, but what about the SQL stuff? Since we can’t use a closure, it’s a bit more involved.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
con = Sql.newInstance(url, user, pass, driver)
 
try
{
  new FileWriter("output.txt").withWriter {writer ->
    con.eachRow("select * from foo") {row ->
      writer.write("Foo: ${row.id}\n")
    }
  }
}
finally
{
  con.close()
}

You can see that even though we can’t use a closure to ensure the database connection gets closed, there are still two closures in use. The one beginning on line five opens the file, while the one beginning on line six writes out some of the data from each row returned by the query. Pretty nifty, eh? I’m disappointed that Groovy doesn’t support passing a closure to the database connection, but maybe we’ll get that in a future version.

For comparison, here’s how you would write this program in straight Java.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
 
try
{
  Class.forName(driver);
  con = DriverManager.getConnection(url, user, pass);
  stmt = con.createStatement();
 
  rs = stmt.executeQuery("select * from Foo");
 
  PrintWriter writer = new PrintWriter(new FileWriter("output.txt"));
 
  try
  {
    while (rs.next())
    {
      writer.println("Foo: " + rs.getString("Id"));
    }
  }
  finally
  {
    writer.close();
  }			
}
catch (Exception e)
{
  e.printStackTrace();
}
finally
{
  try
  {
    if (rs != null)
    {
      rs.close();
    }
 
    if (stmt != null)
    {
      stmt.close();
    }
 
    if (con != null)
    {
      con.close();
    }
  }
  catch (Exception e)
  {
    e.printStackTrace();
  }
}

The majority of that code deals with cleaning up when the real work has been finished. I don’t know what Java’s closures will ultimately look like, or if we’ll get them at all. I’m hopeful, though, that we’ll get a decent implementation, and can then jettison code like you see above. (I know that using Hibernate or some other mapping tool can eliminate code like this, but not every situation needs that type of framework.)

When Does an HQL Typo *Not* Cause A Parse Error?

I found something interesting at work yesterday. One of our developers mentioned that when he called a certain method with various sets of parameters, he wasn’t getting back what he expected to get back, based on what he knew was in the database. I put on my sleuth hat and began my investigation.

We use Hibernate for our database layer, and we prefer to use the @NamedQuery annotation to store our queries with the entities they represent. This works out very well for us. But back to the problem. I quickly got to the appropriate .java file and inspected the query. (Obviously I’ve changed the class names, but this is essentially what I found in the file.)

1
2
3
4
5
6
select distinct f
from Foo f
left join fetch f.bar
left join fetch f.baz
lef join fetch f.plonk
where f.id = :fooId

Now, do you notice the typo? Check out line five. It says “lef” instead of “left.” When I first saw this, I thought to myself, “How can this even get parsed by Hibernate into SQL, let alone return any results.” We all work in a large room together, so I mused out loud about this problem. One of our other Really Smart Guys™ came over to have a look. He saw the typo, thought for a second and said, “‘lef’ is being treated as an alias for f.baz on the previous line.” And sure enough, he was right. Just as on the second line where you see “from Foo f,” that ‘f’ is an alias for the entity called Foo. We could have put aliases on each “left join” line, at each line’s end, had we wanted or needed to. By misspelling “left” on line five as “lef,” we unintentionally slapped an alias on the join that is on line four. Even though the query is split across multiple lines here, the HQL parser would see it as one continuous string, and after passing by “fetch f.baz” the next token it would see would be “lef,” which it would interpret as an alias for “f.baz.”

So, as far as parsing the query and translating it into SQL goes, everything is just fine. But there is still a problem caused by the misspelling. Since the parser decided that “lef” was actually an alias, the next bit that it sees is “join fetch f.plonk” which results in a regular inner join, instead of the outer join we really wanted. What this means is that for records in the Foo table who can’t be joined to records in the Plonk table, either because the key is null, or there just isn’t a record in the Plonk table that matches, those records will be excluded from the result set. That’s the behavior our developer was seeing. Changing “lef” to “left” made the whole thing work and the developer got the results he needed.

I’m Digging Java Again

I first started doing Java back in 1995. That’s quite a long time ago. Once I got going, I wrote Java code every single day, for thirteen years. I co-authored a Java book, gave talks on Java and was an all-around, Java Guy™. And sometime around 2006, I got bored with it. Completely and totally bored. I was a one-man shop at a small company, my code was running just-fine-thanks-very-much, and I didn’t feel like doing anything new with it, at all. I was more interested in Ruby and, to a lesser degree, Rails, so Java changes didn’t really interest me. And thus, I failed to notice some really cool stuff that was going on in Java-land.

In June of this year I joined a new company that is doing some rather advanced Java work. I had to get current, tout de suite, and in so doing, I’ve really gotten interested and engaged again. Spring and Hibernate have really changed from the older versions I was using, and so has JUnit. All for the better, from what I can tell.

And with this renewed interest, I’ve bought my first new Java books in over 3 years. I bought Effective Java (2nd Edition) to replace my first edition and Java Concurrency in Practice, because I heard good things about it. So far, I’ve read about 2/3 of  Effective Java. I used to buy Java books all the time. I have tons of them. But when I got bored, I stopped shelling out the cash on the Java books.

Java-land is still a very nice place to play. Sometimes you have to get an outside perspective to realize that.

Strange Obi-Wan Error

I was doing some JDBC today and I forgot that column indexes are 1-based instead of 0-based. It took me a while to figure out what was wrong since the exception message I kept getting was

java.sql.SQLException: Column Index out of range, 0 > 11.

Despite the fact that zero is not, in fact, greater than 11, I checked to make sure I had used < and not <= in my loop because I thought I was going beyond the maximum index… but I wasn’t. The problem was that I wasn’t even getting to the first index! Then I remembered that I started my loop at 0 and that JDBC ResultSets start indexing at 1. Changing it to 1 fixed the problem, but the error message is wrong. It should have told me that 0 was less than 1 or, more helpfully, that ResultSet indexes start at 1…

Can Someone Help With These Eclipse Files?

Is anyone familar with the format of the files in .metadata/.plugins/org.eclipse.core.resources/.projects in the workspace of Eclipse 3.0? I have an Ant task that uses the .classpath file of a project, along with the JDT preferences to build an Ant classpath for a project with an external build file, and I’m now trying to support projects that depend on other projects. I can see from the .classpath file which projects are referenced, either as a “src” type or a “lib” type, depending on how you added it, but I need to actually FIND those projects and get their build info.

I poked around in my workspace and discovered the directory I mentioned above. For each project that Eclipse knows about there is a subdirectory for it. Inside each subdirectory is a file called .location. I can see by looking at this file with a hex editor, that it does indeed contain the full path to the project. But it’s a binary file, and I don’t know the format. Is it documented anywhere?

I also did a little poking around the Eclipse API. I found a ResourcePlugin which sounded useful, but experiments from within Jython were fruitless. I would also like to avoid hooking into the Eclipse API since I’m trying to support multiple versions of Eclipse, but if that’s the only way to get to the data, I’ll do it.

The question, then, can be broken down into three subparts:

  1. Does anyone know the file formats?
  2. Does anyone have a code snippet of using the proper Eclipse API outside of Eclipse to get to the info in those files?
  3. Does anyone have a better solution to this problem?

Since I’ve taken down the writeback feature of this blog, thanks to certain miscreants, if you have a suggestion, please email it to joey@joeygibson.com. Thanks.

Free Eclipse Classpath Ant Task

This software is no longer supported! I have neither used nor updated this software since I originally posted it, back in 2004. You are welcome to both the binary and source versions, but I no longer do anything with it or support it. If you need something changed, you will have to do it yourself, using the source. Sorry, but after I released it, I realized how little I really needed it, and thus stopped using it.

I’ve just released version 1.0 of a free Ant custom task to make it a little easier to work on a project using both Ant and Eclipse. What this task does is read the .classpath file that Eclipse uses to maintain your project’s classpath, combines that with your Eclipse preferences to expand classpath variables and then creates a path-like structure in your Ant project that you can compile against.

I wrote this because I use Eclipse and I always also have a build file. Keeping the two in sync, classpath-wise, was always a hassle. Now I can simply update the classpath inside Eclipse, and whenever I do an Ant build it will automatically be in sync.

I wrote it against Eclipse 3.0 M8 originally. Then I upgraded to M9 and it stopped working. So with a bit of futzing about, I got it to work with both 3.0 versions and 2.1.3, all three of which keep the preferences file in completely different places with completely different names. But that’s taken care of now. I have also tested on both WindowsXP and Linux, but more on XP than Linux.

To use it, drop the jar file (plus jdom.jar if you don’t already have it) in ANT_HOME/lib. Then taskdef the task

  <taskdef resource="com/joeygibson/ant/eclipseclasspath.properties"/>  

Then call the task. There are several optional attributes, but if you want the classpath to end up in a path called “classpath”, then you can probably get by with just this

  <eclipsecp workspace="/home/me/workspace"/>  

If you are on Windows, and using Eclipse 3.0 M8 or later and you keep your workspace in C:/Eclipse/workspace then you don’t even have to do that much. You can get by with

  <eclipsecp/>   

Once you’ve executed the task, just reference the newly-created path from your javac task or anything else that takes a path as an argument.

You can read more about it in the README.txt

I’ve got several downloadable versions available, in both zip and tar.gz formats, with and without source, and with and without jdom.jar. If you use it and like it/don’t like it/have suggestions, please let me know.

Downloads
Binary only ect.zip
ect.tar.gz
Binary w/ JDOM ect-with-jdom.zip
ect-with-jdom.tar.gz
Source only ect-src.zip
ect-src.tar.gz


I’ve heard there are other tools out there that do this, but I didn’t find them, so I wrote my own. Please email me with any comments you have about it.

Ant Talk At CJUG

I want to thank the folks at CJUG for having me up last night to speak on Ant. I thought the talk went well, though I did run long. I must say it’s rather embarrassing to discover that your presentation, which is supposed to fit in about an hour and a half, in reality needs three hours to be done right… I need to pare it down so this doesn’t happen again. Those in attendance didn’t seem to mind too much, and everyone stuck around a bit longer than planned, which was nice to see.

What I’d really like to do is to extract a subset of the slides into a smaller presentation, yet still have them linked so that I would only have to revise the slides in one PowerPoint file instead of two. Does anyone know if that’s possible?

I’m Presenting at NFJS: Atlanta

If anyone will be in or around Atlanta, GA, October 24 - 26, you should think about attending the Atlanta Java Software Symposium which is part of the No Fluff, Just Stuff symposium series. I’ll be presenting a session entitled “Scripting on the JVM” in which I will present various scripting languages like Python and Ruby running on top of the Java virtual machine and trying to explain why that’s cool. The session abstract is located on the sessions listing page; I’m about 1/3 of the way down the page.

I attended this symposium last year and had an excellent experience. The ratio of useful information to vendor-specific sales-weasel crap was extremely high, which is a good thing. I wrote about it in the February Java Developer’s Journal if you want to read about it. There is also a review of one of the other symposia in the series in the current issue.

I’m really looking forward to presenting at it this year’s symposium.

Java Regex APIs and Quoting

I’ve just been digging through the J2SE 1.4 regex stuff, and every time I have to do regex work in Java I keep thinking how much easier it is in other languages. Specifically I’m talking about the clunkiness of the various regexen APIs in Java and the requirement to double-backslash regex operators. We need a better way. Ruby and Perl both have native regex support built in to the language, so the backslashes are just fine. Python, which doesn’t have native regex support (it’s in the library), does have “raw” string quoting, which allows you not to double-up the backslashes. So what I have to write like this in Java:

1  Pattern p =
2      Pattern.compile("(\\(\\d+\\))?\\s*(\\d{3}\\s*\\-\\s*(\\d{3})");
3  Matcher m = p.matcher(my_string);
4  if (m.matches())
5  {
6      ...;
7  }

or

1  if (Pattern.matches("(\\(\\d+\\))?\\s*(\\d{3}\\s*\\-\\s*(\\d{3})", my_string))
2  {
3      ...;
4  }

looks like this in Python:

1  if re.match("(\(\d+\))?\s*(\d{3}\s*\-\s*(\d{3})", my_string):
2      ...

and could be even more easily written in Ruby thus:

1  if my_string =~ /(\(\d+\))?\s*(\d{3}\s*\-\s*(\d{3})/
2      ...
3  end

See the difference? The built-in regex support is really nice and the ease of quoting is a beautiful thing. I doubt that we’ll ever see either of these in Java since they would certainly be considered non-trivial to add.

J2SE 1.4.2 + WLS 7.0 + weblogic.ejbc = Problem

I discovered something interesting the other day at the office. We have a guy who has been unable to build a certain entire jar of entity beans ever since he started working there and I had only given it scant thought as to why. I knew that I had had no problems… So he came by my office on Wednesday and I said “OK. Let’s figure this out.” I ran our Ant build file that is specifically used for building this particular jar full of entity beans and got the same errors he was reporting. Odd, thought I. The errors being reported by ejbc were that the compiler couldn’t resolve symbols with names like Foo$ValueObject. That was odd since that looked like the inner classes defined in each of the entity beans were not there. But looking at the classes directory, those classes were definitely there. What was really odd was that simply dropping back to J2SE 1.3.1, or even 1.4.1 worked.

For reference, we have a group of entity beans that each have a nested class called ValueObject. (I don’t particularly like that, but they’re there nonetheless.) Essentially we have 80 entity interfaces that follow this basic pattern:

public interface Foo extends EJBLocalObject
{
   ...

   public ValueObject getValueObject()

   public static class ValueObject
   {
       ...
   }
}

and then 80 entity bean classes that actually implement the getValueObject method.

It was at this point that I started looking at that “$” in the class name. It then hit me that the code should be using a “.” between the outer and inner class names, not a “$”. But the code where the error was occurring was generated by ejbc. I’ve tried this now with WLS 7.0 sp2 and sp3 and the results are identical.

Even though I’ve not been able to find this documented in the release notes of J2SE, it would appear that versions prior to 1.4.2 allowed code to specify an inner class using a dollar sign, even though it was not technically correct, and that 1.4.2 has stopped being lenient in this regard. Yes, I know that WLS 7 is not officially supported with 1.4.2… I haven’t tried with WLS 8 yet; I would assume that since it is supported with 1.4.2 they’ve changed the code generation routines inside ejbc.

So the moral of the story is that if you find yourself needing to run WLS 7 with J2SE 1.4.2, and you happen to have entity beans that you need to run through ejbc, first run your build file for those entities using J2SE <= 1.4.1, and run everything else under 1.4.2.

Eclipse 3.0 M2 Is Out

I just got the notice that Eclipse 3.0 M2 is now available. I’ve already been using 3.0, but judging by the release notes there’s a lot of chewy Eclipse goodness loaded in this release. I’ve already downloaded it and “installed” it, such as it is. I’ve upgrading my JDK to 1.4.2 and will fire the new Eclipse up shortly.

Update: OK, I’ve got M2 and JDK 1.4.2 installed. While it does monopolize my CPU on startup, once up it is fast! And there are lots of spiffy new features. My favorites so far are the JavaDoc and Declaration views. The JavaDoc view shows the javadoc for the selected method and the declaration view shows the declaration. Clicking on the “println” part of System.out.println results in the javadoc or the source code being shown, depending on which view is selected. Another feature, which mimics something that is in the new IntelliJ is a change indicator in the gutter on lines that you’ve changed in this editing session. Hovering over the marker shows what the line looked like before and allows you to revert changes. Very nice, indeed!

A Golden Gem

JavaPro Magazine has done a review of my book, Ant Developer’s Handbook!!! The first line is the best:

The Ant Developer’s Handbook is one of those golden gems that appear every once in a while.

That is music to my ears. Now go read the whole review and then go buy your very own copy!

No (Apparent) Love Lost In JBoss Group Split

After this morning’s surprise announcement that JBoss Group was essentially forking, there has been a lot of speculation about what this means for JBoss Group specifically and JBoss in general. The new company was started by 8 now-former JBoss Group consultants and was announced with much fanfare this morning. Ben Sabrin of JBoss Group just posted a “rebuttal” of sorts to the jboss-user mailing list. He took a few jabs at the departing consultants and made one statement that’s a bit hard to swallow. The jabs:

“…the most important developers are on board with JBoss Group.”

“WE have the financial resources to patch the departures of three consultants in our US consulting operation.”

and the dinger is

“It is business as usual and JBoss Group is currently growing.”

The statement that all the “important” developers are on board is an attempt to downplay the reputations of those who have left by implying that they were second string, while the second is attempting to indicate that the new company is going to be strapped for cash, probably to scare off potential customers. I have no personal info on either statement or situation, nor do I know if the developers in question are useful or not. From what I can tell, though, in reading the various articles about the split, the consultants who left all seem like integral parts of the team… I can’t blame JBoss Group for being ticked off, but these statements just strike me as a little smarmy.

The dinger is a dinger because how can you be growing if half of your consultants just left?

I think it will be interesting to see how all this plays out over the next several months. Will this lessen or increase the business use of JBoss? I actually think the potential is there to increase it because you have more options for support, but that’s just me.

Jython Is Just Too Useful

A colleague just came to me asking about Java serialization and output options. We’re going to store some partially filled Serializable DTOs in a BLOB in our database so he needed some info. Our talk then turned to options for storage and such. He already knew about using ObjectOutputStream on top of a FileOutputStream, but I also told him how to get a byte array from the object using a ByteArrayOutputStream. To illustrate, I fired up Jython in interactive mode and typed the following:

[c:\tmp] jython
*sys-package-mgr*: processing modified jar, 'C:\AspectJ1.1\lib\aspectjrt.jar'
Jython 2.1 on java1.3.1_02 (JIT: null)
Type "copyright", "credits" or "license" for more information.
>>> from java.io import *
>>> from java.util import*
>>> m = ArrayList()
>>> m.add("Foo")
1
>>> m.add("Bar")
1
>>> m
[Foo, Bar]
>>> baos = ByteArrayOutputStream()
>>> oos = ObjectOutputStream(baos)
>>> oos.writeObject(m)
>>> oos.close()
>>> dir(baos.class)
['__init__', 'reset', 'size', 'toByteArray', 'toString', 'write', 'writeTo']
>>> baos.toByteArray()
array([-84, -19, 0, 5, 115, 114, 0, 19, 106, 97,
  118, 97, 46, 117, 116, 105, 108, 46, 65, 114, 114,
  97, 121, 76, 105, 115, 116, 120, -127, -46, 29,
  -103, -57, 97, -99, 3, 0, 1, 73, 0, 4, 115, 105,
  122, 101, 120, 112, 0, 0, 0, 2, 119, 4, 0, 0, 0,
  10, 116, 0, 3, 70, 111, 111, 116, 0, 3, 66, 97,
  114, 120], byte)
>>> bais = ByteArrayInputStream(baos.toByteArray())
>>> ois = ObjectInputStream(bais)
>>> x = ois.readObject()
>>> x
[Foo, Bar]
>>> m
[Foo, Bar]

There are lots of cool things there, but specifically, notice the bits in red. I couldn’t remember the method to call to get the byte array, so by using the Python dir() method on the class of the object, I got a list of available methods. toByteArray() was the ticket and you can see both the array itself and then that I went further and deserialized the byte array using a ByteArrayInputStream. Think about how many lines of Java code I would have had to write to show him the same thing. But even if the syntax were just as verbose as Java, not having an edit-compile-run cycle made the demo far faster and productive than it would have otherwise been.

Tracking Down a Log4J Problem

I had a really interesting time tracking down a Log4J problem. We’ve been using Log4J for over a year now happily and even happier with the Commons Logging package on top of it. But last week (while I was on vacation) something went pear shaped: the logs got created but after some initial log messages got sent to the logs, no further messages would get logged. I checked the config file (the XML variety, not the properties file) and it was correct. I then set about digging through code to see if someone had programatically changed the logger, but found nothing. Finally today I found the culprit: a rogue log4j.properties file in a war file in our ear file (that had been there the whole time) had been changed to set the root logger to a level of WARN. Since all of our log messages are at INFO level, thus they never made it. I’ve tested this and it is indeed the problem.

That was a real pain to diagnose, especially since the offending file had not been checked into our source repository. Had it been checked in, I probably would have spotted the change sooner.

Ant Developer’s Handbook at JavaRanch

Starting today over at Java Ranch they are doing a book promotion with my book, Ant Developer’s Handbook. If you are interested in Ant and want a chance to win a copy of my book, go register with JavaRanch and hang out in the Ant Forum and you just might. They are giving away four copies of the book this week and Kirk, Andy and I will all be around answering questions all week.

My One Complaint About The Latest Eclipse

I have but one complaint about the latest release of my favorite IDE, Eclipse. Everyone who uses Eclipse knows that to close an editor you click on the little ‘X’ button on the right side of the editor’s tab. But for the past several months there’s been another way: Control-Click anywhere on the tab. (You can also Ctrl-F4.) The Ctrl-Click struck me as odd when I first read about it, but I’ve come to do it reflexively. Now they’ve taken it away!!! I don’t know why, but they did. And I’m not happy about it… I keep Ctrl-clicking on those tabs and they just don’t go anywhere now…