Details
Description
java.lang.NullPointerException
at org.jibx.binding.def.PropertyDefinition.getName(PropertyDefinition.java:308)
at org.jibx.binding.def.ValueChild.createBackfillClass (ValueChild.java:185)
at org.jibx.binding.def.ValueChild.genParseIdRef(ValueChild.java:282)
at org.jibx.binding.def.ValueChild.genUnmarshal(ValueChild.java:400)
at org.jibx.binding.def.ValueChild.genContentUnmarshal(ValueChild.java:587)
at org.jibx.binding.def.NestedCollection.genContentUnmarshal(NestedCollection.java:130)
at org.jibx.binding.def.ObjectBinding.genUnmarshalContentCall(ObjectBinding.java:611)
at org.jibx.binding.def.ObjectBinding.genContentUnmarshal(ObjectBinding.java:723)
...
occurs with the following binding excerpt:
<mapping name="form" class="com.livis.xforms.desc.Form">
<collection name="constraints" field="constraints"/>
<value name="typeref" field="typeref" usage="optional"/>
<collection field="constraintrefs">
<value name="constraint-ref" type="com.livis.xforms.desc.Type" ident="ref"/>
</collection>
<structure field="layout" usage="optional"/>
</mapping>
<mapping name="type" class="com.livis.xforms.desc.Type">
<value name="name" field="name" ident="def" style="attribute"/>
</mapping>
...
This makes it impossible to unmarshall a list of pointers.
-
Hide
- srcTest.zip
- 02/Dec/04 12:07 PM
- 9 kB
- Martin Vachon
-
- srcTest/build.xml 2 kB
- srcTest/java/example5b/Airport.java 2 kB
- srcTest/java/example5b/binding.xml 2 kB
- srcTest/java/example5b/Carrier.java 2 kB
- srcTest/java/example5b/data.xml 2 kB
- srcTest/java/.../Example5bTestCase.java 3 kB
- srcTest/java/example5b/Flight.java 2 kB
- srcTest/java/example5b/Route.java 2 kB
- srcTest/java/example5b/TimeTable.java 2 kB
Activity
This is a known issue, which I'll add to the status page. The problem is with forward references to objects from collections. If your XML defines the IDs before the references to them from inside the collections there won't be a problem; this obviously doesn't help if you're stuck with XML documents that use forward references.
As Falk pointed out on the mailing list, there is a workaround for this problem if you have control over the Java data structures. The workaround is to use a wrapper class for the forward references, rather than using the references directly in the collection. The wrapper class can be as simple as just:
public class ForwardWrapper
{ public ForwardObject object; }(where ForwardObject is the class of the objects being referenced before they're defined), but this will allow JiBX to fill the actual references in once they've been unmarshalled.
I also get the NPE when compiling my binding.
The is a backwards reference, both in the mapping file and in the XML document.
I tried adding forward="false" to the jibx-binding root element, but I still got the NPE.
The following binding (with much snipped)
<mapping name="HardwareInstallation"
class="edu.iris.dmc.isis.HardwareInstallation" >
<structure name="dbInfo" >
<value name="uid" field="uid" ident="def" />
</structure>
[snip]
</mapping>
<mapping name="StationConfiguration"
class="edu.iris.dmc.isis.StationConfiguration" >
[snip]
<collection name="InstalledItems"
add-method="addHardwareInstallation"
iter-method="getInstalledHardwareIterator" >
<value name="Installation"
type="edu.iris.dmc.isis.HardwareInstallation"
ident="ref" />
</collection>
[snip]
</mapping>
And I get a NPE when I try to compile the binding.
(from runtime binding![]()
[java] Exception in thread "main" java.lang.NullPointerException
[java] at org.jibx.binding.def.PropertyDefinition.getName(PropertyDefinition.java:307)
[java] at org.jibx.binding.def.ValueChild.createBackfillClass(ValueChild.java:185)
[java] at org.jibx.binding.def.ValueChild.genParseIdRef(ValueChild.java:283)
[java] at org.jibx.binding.def.ValueChild.genUnmarshal(ValueChild.java:401)
[java] at org.jibx.binding.def.ValueChild.genContentUnmarshal(ValueChild.java:587)
[java] at org.jibx.binding.def.NestedCollection.genContentUnmarshal(NestedCollection.java:132)
[java] at org.jibx.binding.def.ElementWrapper.genContentUnmarshal(ElementWrapper.java:272)
[java] at org.jibx.binding.def.NestedStructure.genContentUnmarshal(NestedStructure.java:153)
[java] at org.jibx.binding.def.ObjectBinding.genUnmarshalContentCall(ObjectBinding.java:611)
[java] at org.jibx.binding.def.ObjectBinding.genContentUnmarshal(ObjectBinding.java:723)
[java] at org.jibx.binding.def.ElementWrapper.genContentUnmarshal(ElementWrapper.java:272)
[java] at org.jibx.binding.def.MappingDefinition.generateCode(MappingDefinition.java:499)
[java] at org.jibx.binding.def.DefinitionContext.generateCode(DefinitionContext.java:593)
[java] at org.jibx.binding.def.BindingDefinition.generateCode(BindingDefinition.java:562)
[java] at org.jibx.binding.Loader.processBindings(Loader.java:292)
[java] at org.jibx.binding.Run.main(Run.java:190)
[java] Java Result: 1
First of all I am very satisfied with the JiBX binding library !
I need to know if there is a possibility to populate a collection
by using reference (ident="ref" and ident="def")
I have been able to populate a field using a reference with no problem
but the only way I found to populate a collection by reference was by
creating a wrapper object, so I populate the only field of the wrapper
with a reference and create a collection to this wrapper object...
Even if it works, the solution is not acceptable for our project because we do
not wish to modify the java classes.
Here I'm sending you a modified version of the tutorial no 5.
In attachement you'll see the complete code I use for testing.
By reading the previous messages I think I'm not the first one
to encounter this problem. Maybe by sending a complete example
someone will have a better idea of what the problem is ((-;
Our Configuration:
-------------------
jibx-beta3c (also tried cvs version)
java version "1.4.2_04"
Thanks in advance, and i'll be watching for any suggestions.
==================== binding.xml (START) ==========================
<mapping name="timetable" class="example5b.TimeTable">
<collection name="carriers" field="carriers"/>
<collection name="airports" field="airports"/>
<collection name="flights" field="flights"/>
<structure name="route" field="route" type="example5b.Route">
<value name="from" style="attribute" field="from" ident="ref"/>
<value name="to" style="attribute" field="to" ident="ref"/>
<collection name="flights" field="flights">
<structure name="flight" type="example5b.Flight">
-------------------------------------------------------------------
- The value element with the ident attribute generates the error
- org.jibx.runtime.JiBXException:
- No mapping defined for java.lang.Object used as IDREF target
-------------------------------------------------------------------
<value name="refid" style="attribute" field="id" ident="ref"/>
</structure>
</collection>
</structure>
</mapping>
<mapping name="carrier" class="example5b.Carrier">
<value style="attribute" name="code" field="code" ident="def"/>
<value style="attribute" name="rating" field="rating"/>
<value name="url" field="url"/>
<value name="name" field="name"/>
</mapping>
<mapping name="airport" class="example5b.Airport">
<value style="attribute" name="code" field="code" ident="def"/>
<value name="location" field="location"/>
<value name="name" field="name"/>
</mapping>
<mapping name="flight" class="example5b.Flight">
<value name="id" style="attribute" field="id" ident="def"/>
<value name="carrier" style="attribute" field="carrier" ident="ref"/>
<value name="number" style="attribute" field="number"/>
<value name="depart" style="attribute" field="departure"/>
<value name="arrive" style="attribute" field="arrival"/>
</mapping>
====================== binding.xml (END) ==========================
====================== data.xml (START) ==========================
<carriers>
<carrier code="NL" rating="4">
<url>http://www.northleft.com</url>
<name>Northleft Airlines</name>
</carrier>
<carrier code="CL" rating="9">
<url>http://www.classyskylines.com</url>
<name>Classy Skylines</name>
</carrier>
</carriers>
<airports>
<airport code="BOS">
<location>Boston, MA</location>
<name>Logan International Airport</name>
</airport>
<airport code="SEA">
<location>Seattle, WA</location>
<name>Seattle-Tacoma International Airport</name>
</airport>
<airport code="LAX">
<location>Los Angeles, CA</location>
<name>Los Angeles International Airport</name>
</airport>
</airports>
<flights>
<flight id="01" carrier="CL" number="796" depart="4:12a" arrive="1:26a"/>
<flight id="02" carrier="NL" number="328" depart="2:54a" arrive="1:29a"/>
<flight id="03" carrier="CL" number="401" depart="4:12a" arrive="1:25a"/>
<flight id="04" carrier="CL" number="634" depart="7:43a" arrive="9:13a"/>
<flight id="05" carrier="NL" number="508" depart="4:38p" arrive="6:12p"/>
<flight id="06" carrier="CL" number="687" depart="1:38p" arrive="3:08p"/>
</flights>
<route from="BOS" to="SEA">
<flights>
<flight refid="01"/>
<flight refid="02"/>
<flight refid="03"/>
</flights>
</route>
======================= data.xml (END) ===========================
The JiBX code generation is unable to handle references embedded directly in a collection. I've supplied custom marshaller/unmarshaller base class examples (which need to be subclassed by the user) as org.jibx.extras.IdRefMapperBase and org.jibx.extras.IdDefRefMapperBase which can be used within collections as long as there are no forward references; for forward references you'd need to take these and extend them to handle the whole collection, with backfill generation. I've also added a check for using a reference directly within a collection as a binding error, so that users will know when they're doing something that's not supported. That's the best we can do on this, at least until 2.0.
BTW. Marking the value with ident="ref" as optional does not help. I tried all sort of syntax, all lead to some NullPointerException when trying to get a name.