Category Archives: hibernate

Maven is like apt-get for Java

When I first learned Linux, I used Slackware 3.0.  In those days, if you wanted to install extra software, you pretty much had to compile it yourself.  And they didn’t even have configure scripts back then, if I recall correctly.  Eventually, Redhat took over, and software was easier to install via RPM packages.  At first, RPMs weren’t available for everything, so you still had to compile some stuff, but eventually they became pretty ubiquitous.  Dependencies could be a big pain though.  You download one RPM you want, and you find out you need to download five more that it depends on.  And those five each depend on five others.  Remember rpmfind.net?  Then came yum and apt-get, and those trouble were alleviated.

Now, building Java apps is almost like managing a Linux system.  There are so many great third party libraries available, you can find ones to do almost any common task you need, saving lots of time when coding stuff.  But, the people that write those libraries also use other libraries.  Things like Hibernate have a lot of dependencies.  Getting all of the jars for the libraries you need can be somewhat like the old RPM hunt.  This is where Maven comes in.  Just tell it you need Hibernate and it will make sure you have everything else you need.  It’s pretty awesome, and it can completely eliminate those sessions where you waste a lot of time looking for jar files.

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.

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.