Category Archives: work

Tapestry 5: radio buttons coming back with value "on"

I ran into a problem today where I was setting the value of a radio button in Tapestry 5 to a long field within a property. I was getting back the value “on” and Tapestry was crashing trying to coerce it into a long type. It turns out the value was null, and the default value for a radio button is “on”. So, if you encounter this, make sure your value fields are not null.

The end of Netbeans week


I have finished my week of Netbeans usage and so far am pretty impressed. I was able to go all week without using Eclipse once. A large part of that is thanks to the fact that I’ve been using Maven 2 for a large number of my most recent projects. If you have a pom.xml, Netbeans will be able to check out your project and open it without you doing a single bit of configuration. This is great, since it goes a long way in preventing IDE lock-in. If you are working on a Maven project, you can use Netbeans easily, even if everyone else is using Eclipse. I didn’t get very deep into working on non-Maven projects, so that may have been quite a bit more hassle. All in all, though, Netbeans has come a long way since the last time I gave it a serious test. Here are some of my favorite features:

  • Autocomplete seems quite a bit faster than Eclipse
  • Maven integration is good, but I only briefly tried projects with parent-child relationships, which seemed to trip it up a bit
  • Adding getters/setters is a lot less hassle than Eclipse.
  • Using jetty:run right inside Netbeans was pretty easy, though it did require the use of external Maven, I’m not sure why.
  • The web.xml editor is pretty cool
  • It has a built in SOAP client, although it seems pretty clunky.
  • SVN integration seems complete and not very buggy. The interfaces are quick and simple, though I might say it’s a bit oversimplified from the way Eclipse does things.
  • The built in editor support for non-Java files seems less buggy than in Eclipse.

I may give Netbeans another week. It should be pretty obvious to anyone that it takes longer than a week to fully get a feel for such a complicated piece of software.

The modern Java web app

I’m always looking for ways to streamline Java web app development. In case I haven’t spread the word to you, here’s the current set of technologies I’m liking:

  • Tapestry 5 – This is the framework I’m using, but I’m not saying it’s better than anything in particular, but I like some of the stuff they are doing.
  • Hibernate with annotations – I’ve been a big fan of hibernate for a long time, using the annotations seems to simplify the mapping process quite a bit.
  • Spring Hibernate integration – makes transaction/error handling way way easier in Hibernate. I am using HibernateDaoSupport as a base class. Tapestry 5 also has Spring integration, allowing you to inject the DAO’s right into your page classes
  • Maven 2 – So much easier than ant and dependency hell, once you get used to the paradigm shift. It might cause issues with your Eclipse tomcat integration, but I always found that to be flaky anyway. Use Jetty instead.
  • Maven Jetty plugin – Allows you to build/deploy your app with one command (mvn clean jetty:run). Much easier than dealing with some of the flakiness of tomcat deployment, and allows you to just run one of your apps at a time.

I am also looking into Spring Security, and hoping it will simplify authorization, and I’m doing some IDE evaluations to see if it’s time to ditch Eclipse.

IDE of the week: Netbeans 6.1

Happy Monday morning. After battling with Maven and the Tomcat plugin in Eclipse a bit last week, I have decided to try some alternative IDEs. I’ve heard good things about IntelliJ, and I think the Maven integration in Netbeans is supposed to be good. So, I’ve decided to give each of them a week of use and see if they can beat out Eclipse. This week is Netbeans 6.1. So far, I’ve spent a few minutes installing updates and reading up on the Maven support (you have to install a plugin through the plugin manager). Now that the plugin is installed, it automatically recognizes Maven projects when I check them out, so that is cool. Hopefully I can make it through the week without reverting to Eclipse.

Tapestry 5: First Impressions

My new group at ASU is loosely standardizing on Tapestry, so I’ve been spending some time learning it. We are officially using 4.1, I think, since it’s the latest official release, but I decided to go all rogue style and switch to 5.0 after spending some time on 4.1. From the noise on the web, it sounds like Tapestry gets completely rewritten for every new version, so 5.0 is pretty different from 4.1. Anyway, it seems much better, but there are still some weird problems. Here are some of the interesting things I’ve run into:

  • If you need to call some Tapestry page from an outside app with data, you can simulate Tapestry’s “activation/passivation” by building URL strings which will feed your onActivate method. They look like this: http://localhost:8080/app/page/param1/param2, where param1 and param2 will be passed in a List (not an array, as I found out the hard way) to onActivate. I’m not sure if this is the best way to do it.
  • If you loop through a list of items and want to be able to edit those items (like by having a checkbox), you pretty much need to set up a PrimaryKeyEncoder, otherwise it will serialize/deserialize stuff and all your changes will be lost. This was very hard to figure out.

So far I’m only moderately impressed. There seem to be too many assumptions that don’t fit the model of my first app very well, but we’ll see how it goes once I get better at it.

Getting tomcat to stop deleting your context xml files

I’ve been plagued with this annoying problem in tomcat for about a year, and it has been driving me crazy. I’ve looked through the code, joined the mailing list, etc. etc. The problem is when you have context xml files, such as /usr/local/tomcat/conf/Catalina/localhost/app.xml. Generally, you would use such files to set up JNDI data sources for database connections, but I also use them to set up configuration beans in order to keep environment-specific data outside of your application code (which I consider the whole war file to be). Anyway, tomcat seems to randomly delete those files when I change anything in the application files. I tried various configurations using war files, no war files, and war files in funny locations, and it happened to all of them.

I never did find out why it deletes the files, but I did find a solution, thanks to a user on the tomcat mailing list. All you have to do is turn off “autoDeploy” on the “Host”. Basically, you need to edit /usr/local/tomcat/conf/server.xml and change the xml element, so that it says autoDeploy=”false” instead of autoDeploy=”true”. And with that, all my problems are over.

Hibernate error reporting

Sometimes, Hibernate is really bad at error reporting. Today I added a NOT NULL constraint to a column in my database and ran my unit tests. Several failed with errors like this:

testAddInstructor(edu.asu.cem.test.dao.CourseDAOTest) Time elapsed: 0.009 sec <<
org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:92)
at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:87)
at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:222)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2229)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2665)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:60)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeInserts(ActionQueue.java:158)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:245)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
at edu.asu.cem.test.dao.CourseDAOTest.setUp(CourseDAOTest.java:103)
at sun.reflect.GeneratedMethodAccessor6.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.junit.internal.runners.MethodRoadie.runBefores(MethodRoadie.java:122)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:138)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:125)
at org.apache.maven.surefire.Surefire.run(Surefire.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:308)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:879)
Caused by: java.sql.BatchUpdateException: failed batch
at org.hsqldb.jdbc.jdbcStatement.executeBatch(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeBatch(Unknown Source)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
… 44 more

I had made several changes since running the tests, so I had to think about what might be making a database call crash. Luckily, I was able to remember, but I have spent hours debugging these before. I wish the JDBC exception was floated to a higher point in the exception chain so it would be displayed. In this case, all I had to do was set a value for the fields that were no longer nullable.

Online Learning Systems and Search

Back when I was a CS undergrad, Blackboard was not very popular yet (at least among the nerdy CS faculty).  Most classes had a class web site involving a tilde, the professor’s username and some quick and dirty HTML.  They were generally extremely simple, concise, and easy to navigate.  Additionally, they were open to the public either out of intention or lack of effort to secure them.  As a result, one could visit the ASU web site and search for a class like CSE 340 and find a collection of class web sites with syllabi, assignments, etc.  This was really useful for getting a feel for a class and/or professor’s style before actually registering for it.  You could read the syllabus and see what material would be covered, whether group work would be involved, how it would be graded, etc.  It was all very nice.

Now, everyone uses Blackboard and all of the course resources are on lockdown (perhaps for the reverse reasons as they were previously public).  You pretty much can’t find anything useful if you search for a class number on the ASU web site, based on my quick testing.  I suppose this is a good thing, because many professors consider such materials part of the intellectual property and don’t want them to be freely available, but I think quite a few wouldn’t mind if prospective enrollees were able to read through the course materials.  Perhaps an opencourseware system is the answer.

Drupal 5.7 on Resin 3.1.4

So, in case you didn’t hear, Caucho has a component called Quercus built into their Resin product which is a pure Java PHP interpreter. With this product, it is claimed that one can achieve 4x performance gains with Drupal (phew…that was a lot of links). The concept of being able to call into Java code as well seems appealing to me. Although Drupal is now at version 6.0, I tried it with 5.7, since I know most modules work with 5.x, but I’m not sure about 6. Here’s a quick guide…

  1. Download Caucho Resin 3.1.4 (open source)
  2. Download Drupal 5.7
  3. Unzip Resin
  4. Put a copy of mysql JDBC driver in the lib directory under resin
  5. Put a copy of JavaMail mail.jar in the lib directory also
  6. Create mysql database for drupal and a user to access it
  7. Go into webapps under the resin directory
  8. Unzip drupal here
  9. Rename drupal-5.7 to drupal
  10. Create WEB-INF/resin-web.xml under the drupal directory:



    jdbc:mysql://localhost:3306/databasename
    username
    password








    index.php








  11. Modify drupal/sites/default/settings.php
    • Change database name
    • Change username/password
  12. Start resin (java -jar lib/resin.jar)
  13. Go to http://localhost:8080/drupal/install.php (you need to explicitly go to install.php, since drupal gets confused about the modified settings.php, but no data in the db)
  14. Your drupal should now be functional

Xen, HVM, and running out of memory

I think I’m in an uncommon situation, but I needed to set up lots of HVM (full virtualization) hosts on my Xen install, since the dom0 is a different distribution (debian) than the domU hosts (Fedora). With paravirtualization, the “balloon driver” takes care of memory allocation, I think. But in HVM mode, you actually have to have the amount of memory required by your VM available outside of dom0. If you don’t have enough, you get an error like this:

Error: Error creating domain: (12, ‘Cannot allocate memory’)

It took forever to figure this out, but the key is to limit dom0’s memory, so that you have enough for your VMs. The machine I’m working with has 16 gigs, so I limited dom0 to 1 gig by using this line in the menu.lst for grub:

kernel /xen-3.0.3-1-amd64.gz dom0_mem=1024M

Yours will probably look different, but the key is the dom0_mem parameter. Once you add that, you will have 15 gig left for allocating virtual machines.