Lately, I've been working a lot with the Object Relational Bridge (aka ObJectRelationalBridge or OJB), which is one of the Apache database projects. Its purpose is to make it easy to persist Java objects into traditional relational databases. For the most part, it works very well. It's still a bit young as a technology, and occasionally, the error messages leave something to be desired. One such case happened to me recently. While working with a new class that I was persisting into the database, I got the following exception message:
My first reaction to the error was wondering how could any application think java.lang.Long is not capable of being persisted. Then I realized the actual problem is that java.lang.Long isn't in OJB's respository. I assumed that was the repository of classes it knows how to persist, so that still seemed a bit silly. Several of the classes I had already been successful at persisting with OJB contain Longs and longs.
Luckily for me, I had downloaded the OJB source from Apache.org. (Actually, I downloaded the latest source using a Subversion checkout from the OJB_1_0_RELEASE tag.) The distributed binaries are compiled without debug information, so I recompiled it so that I could use the debugger to step through the OJB source as well. I was able to trap the exception and track backwards to find out that the exception was being raised when trying to persist the references in the new class. I suspected it was a configuration issue in my version of the repository_user.xml, used by OBJ, but I couldn't figure out what the problem exactly was.
The fact it was in the reference-description section was the clue I needed. My original repository_user.xml file looked something like the following. (I changed the names of the classes to something more generic to protect the innocent/guilty.)
<class-descriptor
class="com.somecompany.ValueSet"
schema="REPORTING"
table="RPT_VALUE_SET"
>
<field-descriptor
name="mValueSetId"
column="VALUE_SET_ID"
jdbc-type="BIGINT"
primarykey="true"
autoincrement="true"
sequence-name="RPT_VALUE_SET_ID_SEQ"
/>
<field-descriptor
name="mSomeOtherStringField"
column="SOME_OTHER_FIELD"
jdbc-type="VARCHAR"
/>
<field-descriptor
name="mValueId"
column="VALUE_ID"
jdbc-type="BIGINT"
/>
<reference-descriptor
name="mValueId"
class-ref=" com.somecompany.Value"
auto-retrieve="true"
auto-update="true"
>
<foreignkey field-ref="mValueId"/>
</reference-descriptor>
</class-descriptor>
My obvious and silly mistake in the file above is the cut and paste error highlighted in green. Namely, I put the ID value, mValueId, in the name field of the reference descriptor where the name of the class, mValue, should have been. This caused OJB to go look for a class in the OJB Repository equivalent by the name java.lang.Long. Since such a class definition doesn't exist in the OJB repository (that is, there's no class-descriptor with a class field set to "java.lang.Long), I got the org.apache.ojb.broker.metadata.ClassNotPersistenceCapableException exception. The correct repository_user.xml file should have contained the following.
<class-descriptor
class="com.somecompany.ValueSet"
schema="REPORTING"
table="RPT_VALUE_SET"
>
<field-descriptor
name="mValueSetId"
column="VALUE_SET_ID"
jdbc-type="BIGINT"
primarykey="true"
autoincrement="true"
sequence-name="RPT_VALUE_SET_ID_SEQ"
/>
<field-descriptor
name="mSomeOtherStringField"
column="SOME_OTHER_FIELD"
jdbc-type="VARCHAR"
/>
<field-descriptor
name="mValueId"
column="VALUE_ID"
jdbc-type="BIGINT"
/>
<reference-descriptor
name="mValue"
class-ref=" com.somecompany.Value"
auto-retrieve="true"
auto-update="true"
>
<foreignkey field-ref="mValueId"/>
</reference-descriptor>
</class-descriptor>
The class descriptor for the mValue class would be found elsewhere in the repository_user.xml file. (The definition of mValue is left as an exercise for the reader.) So there it is. Easy error to make; odd exception awarded for doing so.