Collection item of type X has no binding defined
Posted by davidnewcomb on 10 Nov 2008 in Techie
I’ve been doing a lot of work recently with the SpringFramework. It helps with all aspects of building a large scale application by, among other things, providing a generic exception hierarchy which is used by all the component modules. The upshot of this is that I can use Castor or JibX for my XML serialiser without having to change my core code to handle JiBXParseException or a CastorRuntimeException - SpringFramework will abstract away the differences.
This is all very handy but when the spring exception is thrown up from the library it contains the original exception (”cause“) which is where all the meaty information lives. Naturally these are specific to the library.
During my rounds this one came up when using JibX 1.1.6a, and it took a little while to figure it out:
org.springframework.oxm.jibx.JibxMarshallingFailureException: JiBX marshalling exception: Collection item of type uk.co.bigsoft.proj.event.DeleteEvent has no binding defined; nested exception is org.jibx.runtime.JiBXException: Collection item of type uk.co.bigsoft.proj.event.DeleteEvent has no binding defined at org.springframework.oxm.jibx.JibxUtils.convertJibxException(JibxUtils.java:49) at org.springframework.oxm.jibx.JibxMarshaller.convertJibxException(JibxMarshaller.java:169) at org.springframework.oxm.jibx.JibxMarshaller.marshalWriter(JibxMarshaller.java:193) at org.springframework.oxm.AbstractMarshaller.marshalStreamResult(AbstractMarshaller.java:256) at org.springframework.oxm.AbstractMarshaller.marshal(AbstractMarshaller.java:97) at uk.co.bigsoft.proj.event.TestDeleteEvent.testGet(TestDeleteEvent.java:104) 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:597) at junit.framework.TestCase.runTest(TestCase.java:168) at junit.framework.TestCase.runBare(TestCase.java:134) at junit.framework.TestResult$1.protect(TestResult.java:110) at junit.framework.TestResult.runProtected(TestResult.java:128) at junit.framework.TestResult.run(TestResult.java:113) at junit.framework.TestCase.run(TestCase.java:124) at junit.framework.TestSuite.runTest(TestSuite.java:232) at junit.framework.TestSuite.run(TestSuite.java:227) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) Caused by: org.jibx.runtime.JiBXException: Collection item of type uk.co.bigsoft.proj.event.DeleteEvent has no binding defined at uk.co.bigsoft.proj.event.DeleteEvent.JiBX_MungeAdapter.JiBX_jibx_isa_marshal_1_0() at uk.co.bigsoft.proj.event.DeleteEvent.JiBX_jibx_isa_marshal_1_0(EventsContainer.java) at uk.co.bigsoft.proj.event.DeleteEvent.JiBX_jibx_isaEventsContainer_access2.marshal() at uk.co.bigsoft.proj.event.DeleteEvent.marshal(EventsContainer.java) at org.jibx.runtime.impl.MarshallingContext.marshalRoot(MarshallingContext.java:1041) at org.jibx.runtime.impl.MarshallingContext.marshalDocument(MarshallingContext.java:1133) at org.springframework.oxm.jibx.JibxMarshaller.marshalWriter(JibxMarshaller.java:190) … 22 more…but there is a binding definition for my type X!
<mapping name="eventscontainer"
class="uk.co.bigsoft.proj.event.EventsContainer">
<collection
field="events"
factory="uk.co.bigsoft.proj.event.createEventsContainer">
<structure
name="isaeventcreate"
type="uk.co.bigsoft.proj.event.CreateEvent">
<value name="zone" field="zone"/>
</structure>
<structure
name="isaeventmodify"
type="uk.co.bigsoft.proj.event.ModifyEvent">
<value name="zone" field="zone"/>
</structure>
</collection>
In JibX you can serialise collections. The collection may contain different types. In my case they were a set of classes which all implemented the same interface. In JibX you need to define the elements that can appear in a collection, but the collection is by default ordered. When de-serialising the collection it can contain 3 of the first element, 0 of the second, 2 of the next and so on - but they have to be in the order laid out in the binding-mapping. What you can’t do, is have them come in any order.
If you want the collection to be able to de-serialise objects in any order, you need to flag it as not ordered. There is a performance hit for this but I think it is worth it. Alternatively, you must make sure that your collection is ordered in the same way as your XML schema definition, which is not always possible.
So from the example above add the ordered attribute to the collection elements:
<mapping name="eventscontainer"
class="uk.co.bigsoft.proj.event.EventsContainer">
<collection
field="events"
ordered="false"
factory="uk.co.bigsoft.proj.event.createEventsContainer">
:
No feedback yet
Form is loading...