Archive

Archive for October, 2004

IBM, Python, and the Blues

October 20th, 2004

I gave a talk about Python at IBM’s Toronto lab yesterday. It seemed to go pretty well—Paul Buck, who’d invited me out there, said that his group in IBM sees LAMP (Linux, Apache, MySQL, and Perl/Python/PHP) as being as big a threat to Java as .NET, so they want to learn more about all of ‘em.

That’s the good news. The bad news was the makeup of the audience: roughly 40 people attended, all of them male (except for admin who’d handled the arrangements). I can’t imagine giving a talk to that many doctors or lawyers and finding myself in front of a single-gender audience. *sigh*

Uncategorized

Bayesian Filtering for Newsgroups?

October 14th, 2004

Paul Gries and I were working at the same desk this morning. He was paging through dozens of posts to the bulletin board for a first-year course, many of which were repeats of questions that had already been answered. At the same time, I was setting up SpamBayes on my no-longer-new laptop. We looked at each other, and thought, “Why not use Bayesian filtering on posts to newsgroups and mailing lists?” If the filter decides that what you’ve asked to post is closer than it likes to something that’s already there, it can point you at the previous message, and ask you to confirm that you actually want to post. Sure, people could do this on their own, but many don’t.

Anyone ever seen anything like this?

Uncategorized

Virtual Internet Appliances

October 14th, 2004

I had mail from Joel Spolsky yesterday in response to my postings about how difficult it is to get a working Java web development environment set up. His suggestion? Give everyone VMWare, and distribute machine images that have everything pre-configured. The more I think about this, the cooler it gets—does anyone know if anyone’s ever actually tried shipping “virtual Internet appliances” this way?

Uncategorized

Apt and Extensible Programming

October 13th, 2004
Comments Off

Over in the java.net community forums, Bruce Chapman suggests that we deprecate javac in the next major Java release. Yup, that’s right: no more javac. Instead, he suggests that we all start using apt, which allows developers to run their own code inside the compiler. As he says, “Do you want a compiler error when you implement an interface and the javadocs say that implementations must have a public default constructor, and yours doesn’t? Well apt [can] do that…”

It’s a pretty cool idea. It’s also a perfect example of the kind of extensible tools that I think are going to dominate programming in the years to come. If I’d read it a week earlier, I would have mentioned it in my extensible programming article, which has just gone off to ACM Queue. Maybe I can throw it in as a late footnote…

Extensible Programming

E4X and Configuration

October 13th, 2004

Jon Udell posted some more comments about E4X today. If you haven’t been following along, it’s a proposal to make XML a native data type in JavaScript, so that programmers can manipulate it as naturally as they do strings or lists.

The most exciting thing for me about E4X (and variants)
is that it provides a path away from the morass of “passive” XML
configuration files that currently plague web development. My
students (hand-picked, all with good GPAs, most with industrial
experience) have had a hard time getting the “standard” Java
web toolset—Eclipse, Ant, JUnit, Hibernate, Tapestry, and Tomcat—up
and running. Most of their grief has stemmed from the fact that
much of what developers care about is in XML config files, for which
there isn’t any kind of break-and-inspect debugger.

RubyOnRails and
other “pure scripting” solutions are easier to use in part because
all of the config glue is in the language the programmer is using,
so she can bring all her programming power tools to bear when something goes
wrong. (Oh, and she doesn’t have to wedge conditionals, loops, and
the like into some hashed-together XML syntax.) From what I’ve seen
so far, JavaScript with embedded XML (and the reverse) would give us
a way to migrate from the existing undebuggable mess toward programmatic configuration.

Extensible Programming

Blogging vs. Venting

October 12th, 2004
Comments Off

Christian, Steve, and Anthony, from the Hibernate development team, have commented on my postings about the trouble I’m having getting things to work. I’m not sure what ‘seem swoon by “academic woe”‘ means, and I think that trying to get Hibernate into the undergrad curriculum will do more to help it grow than writing patches, but I take their point: less venting would be more productive.

So, my apologies—I’ll wait until the next day from here on in before blogging my experiences. In the meantime, though, let me throw it open: what could/should I have done four weeks ago to get my students over the learning curve more quickly? More to the point, what can I do this coming January, when the next generation joins the project? I believe it took this term’s students an average of 30-40 hours to get their first (trivial) app going with Eclipse, Ant, JUnit, Hibernate, Tapestry, and Tomcat, which is a third to half of the time they’re supposed to spend on the course in total. Options I see are:

  1. Just accept that getting your first Java web app to run is a full-term venture, and try to find room in the curriculum for _two_ courses (one introducing the tools, the second putting them into the proper software engineering context). The problem with this is that the curriculum is pretty crowded already…
  2. Hand students a working self-contained starting point (but then when things go wrong, they won’t know where to start debugging);
  3. Have each student pick just one part of the tool stack and master it (but then they don’t learn how to build complete web apps, and are lost when bugs arise out of interactions);
  4. Simplify the tools, esp. their configuration, and their interactions. A lot of recent articles and books have complained that the Java web app tool chain has grown too complicated (see Better, Faster, Lighter Java, for example; there are lots of others). However, I haven’t yet seen consensus on what to do about it.

Ideas? Pointers?

Uncategorized

Oh, You Mean You Wanted It to *Work*…

October 8th, 2004

Finally back on track building a simple Hibernate example to give future generations of students…or am I? In case you haven’t been following along, I had my project laid out as follows:

  • build.xml
  • hibernate.cfg.xml
  • src/User.hbm.xml
  • src/Test.java

After building, I had all of the above, plus:

  • gen/User.java
  • class/User.hbml.xml
  • class/User.class
  • class/Test.class
  • class/hibernate.cfg.xml

Why copy the .hbm.xml and .cfg.xml files to the class directory? Because they have to be on the classpath at runtime, and I’m eventually going to deploy only what’s in class.

Great—now let’s try to run it. Hm, missing a couple of JAR files… No problem, I can copy them out of hibernate-2.1/lib (I’m doing this on-demand, since I want a minimal set of JARs when I deploy). But wait—even once all the required JARs are there, I still can’t run my test class.

Mutter, mutter… *whack* as my forehead bounces off the wall again… Guess what? It turns out that Hibernate doesn’t read settings from hibernate.cfg.xml at startup, even if said file is on the classpath. It’ll read from hibernate.properties, but you can’t list your .hbm.xml mapping files in a .properties file. So, your options are:

  1. Duplicate information (never a good idea).
  2. Separate information (i.e. put some settings in hibernate.properties, and some in your Java code).

*sigh* All right, I’ll do the latter, and there’s another half hour lost googling, flipping through books, and trying things out. Go ahead, ask me whether I’m looking forward to adding JUnit to this stew…

Uncategorized

Open Source, Cold Shoulder

October 8th, 2004
Comments Off

I’m very pleased to announce that an article Michelle
Levesque and I wrote about why so few women get involved in open source
computing, and what that reveals about open source’s weaknesses, is now
on-line at:

http://www.sdmagazine.com/documents/sdm0411b/

(The trailing slash is required.) You may have to register to view it, but registration is free.

Equity

Ant + Hibernate: There’s More Than One Way to Fix It

October 8th, 2004

I don’t know who William Lopez is—I’ve never met the man, and before yesterday at 19:40 EST, I’d never heard of him. But then a mail message landed in my inbox saying, “I think I’ve solved your Ant + Hibernate problem.” He included his solution in a ZIP file; it took me all of five minutes to download it, edit a couple of settings for my machine (library files in different places), and convince myself that yes, it did work. It took another ten minutes to figure out which of his changes was the crucial one, and guess what: it’s an Ant bug.

Or maybe not, because three hours later, Eric Burke added a comment to the original posting. His solution was to rearrange some of the Hibernate-specific stuff in the build file. So who’s fault is it really, Ant’s or Hibernate’s? Let’s take a look.

I was trying to get Ant to clean my workspace, generate a Java source file from a Hibernate mapping file, compile that file and another one I’d written by hand, and then generate a database schema, all in one invocation. The problem was that when I got to the schema generation step, the Hibernate schema generation task told me that the compiled class file for the generated class didn’t exist. If I ran Ant twice, though, everything worked; it also all worked if I ran Ant as far as “compile the Java”, then ran it again to do the schema generation. But how could there be a timing bug in a strictly sequential chain of operations?

William Lopez’s solution was to create all of the temporary directories the build process needed once, at the start of the build process, rather than creating each directory just before it was needed. Basically, I had:

<target name="clean">
    <delete dir="${gen}"/>
    <delete dir="${class}"/>
    <delete dir="${data}"/>
</target>

<target name="codegen">
    <mkdir dir="${gen}"/>
    <hbm2java output="${gen}"> />
</target>

<target name="compile" depends="codegen">
    <mkdir dir="${class}"/>
    <javac srcdir="${gen}" destdir="${class}" ...> />
    <javac srcdir="${src}" destdir="${class}" ...> />
</target>

<target name="schema" depends="compile">
    <mkdir dir="${data}"/>
    <schemaexport ... />
</target>

and William changed it by moving the mkdir actions inside the clean target:

<target name="clean">
    <delete dir="${gen}"/>
    <delete dir="${class}"/>
    <delete dir="${data}"/>
    <mkdir dir="${gen}"/>
    <mkdir dir="${class}"/>
    <mkdir dir="${data}"/>
</target>

<target name="codegen">
    <hbm2java output="${gen}"> />
</target>

<target name="compile" depends="codegen">
    <javac srcdir="${gen}" destdir="${class}" ...> />
    <javac srcdir="${src}" destdir="${class}" ...> />
</target>

<target name="schema" depends="compile">
    <schemaexport ... />
</target>

So it has to be an Ant problem—except that Eric Burke fixed the problem by moving the schema export taskdef inside the schema export target, like this:

<target name="schema" depends="compile">

    <taskdef name="schemaexport"
             classname="net.sf.hibernate.tool.hbm2ddl.SchemaExportTask"
             classpathref="cpath.compile" />

    <mkdir dir="${data}"/>

    <schemaexport .../>

</target>

and that works too. His explanation says:

I suspect the taskdef is resolving the classpath at the instant Ant parses the taskdef tag. Since one of the required .class files has not been generated yet, the SchemaExportTask does not find the necessary files…
While you could blame Ant, I think it’s more likely that the SchemaExportTask should probably be modified to accept a classpath of its own. This would make the task more flexible since you wouldn’t have to worry about where you define it.

He then goes on to say:

I hope someone finds this useful. [Yes, Eric, very; thank you, and thanks to William, too.] There is still a very steep barrier to entry for tools like Hibernate, various AOP frameworks, etc… The barrier is figuring out all of the initial configuration options and getting your build process to flow. These things are overwhelming when you are first getting started.

Amen, Eric. Eleven of my department‘s brightest undergraduates have been banging their heads against Eclipse, Ant, JUnit, Tomcat, Hibernate, Tapestry, and Checkstyle for more than four weeks now. They’re smart, they work very hard, and they really want to master this stuff, but the learning “curve” they face is more like a vertical wall. If the open source community wants colleges and universities to include modern tools and frameworks in the curriculum, they’re going to have to do a better job fixing the “last 10%” of problems that so often gobble up all the hours students are supposed to spend learning…

Uncategorized

Ant + Eclipse = More Pain

October 8th, 2004

The biggest problem with classpaths is that there is no standard way of defining them. Classpaths can be set through environment variables (which have an OS-specific syntax), command-line arguments to the VM, system properties (which can be set through the command-line or a properties file), and even by arbitrary code running within a JVM.

For instance, Eclipse keeps track of classpaths for individual projects through the .classpath XML file in the project’s root directory.

Ant, on the other hand, builds its classpath from many places. It looks through environment variables (CLASSPATH and ANT_OPTS, in particular), the system properties, and the build script that’s currently loaded. On top of that, Ant uses at least two distinct classloaders, which maintain their own individual classpaths: one for loading Ant, the tasks, and their dependencies, and one for for actually executing the tasks.

When you put Eclipse and Ant together, the potential for distaster increases exponentially.

About four-hundred revisions back in time (revision 94, to be exact), I changed the build file around to unify the data model of Hippo with the UI layer, which used to be contained within separate Eclipse projects. Like all servlet-based web applications, the UI layer stored its class files in $WEBAPP_ROOT/WEB-INF/classes. The test case classes were stored in build/test.

In the meantime, Eclipse’s .classpath file was still set to compile all classes directly into the build directory.

This isn’t a problem if you use Eclipse’s build system exclusively to build and run your code. It’s also not a problem if you use Ant to exclusively build and run your code.

However, if Ant and Eclipse’s classpath configurations are not in sync (which has been the case from revision 94 up to just a few days ago) and you use Ant to build and Eclipse to run, you will get many ClassNotFoundExceptions.

Why did that happen? Eclipse was set to compile classes into the build directory. Therefore, it added the build directory to its default runtime classpath.

When you use Ant to build the project, Ant stores the compiled class files in two places. The test classes are saved in build/test while everything else is put into $WEBAPP_ROOT/WEB-INF/classes.

Now when you go to run the tests in Eclipse, Eclipse looks for them in build, but they’re really stored in build/test and $WEBAPP_ROOT/WEB-INF/classes.

So what’s the solution? Configure Ant so that its build process is in sync with Eclipse. Right now, this is being done redundantly and manually, but I’m sure with a little extra effort, Ant can be taught to read Eclipse’s .classpath configuration automatically.

Uncategorized