Skip to content
This repository has been archived by the owner on Feb 5, 2019. It is now read-only.

Reusing unmarshaller results in an unexpected result #450

Closed
glassfishrobot opened this issue Nov 27, 2007 · 8 comments
Closed

Reusing unmarshaller results in an unexpected result #450

glassfishrobot opened this issue Nov 27, 2007 · 8 comments

Comments

@glassfishrobot
Copy link
Contributor

If you use an unmarshaller once for decoding an XML document of which root
element is not a registered root element in the JAXB context but xsi:type
attribute signifies the content's type, next time you use it again for decoding
another XML document of which root element is a registered one, you will see
that the result is not an instance of the registered class but a wrapper
JAXBElement object. Of course, if you use a 'fresh' unmarshaller for the latter
document, you will get an instance of the registered class as expected.

The cause of this seems to reside in UnmarshallingContext$DefaultRootLoader
class. Here I quote the part.

private static final class DefaultRootLoader extends Loader implements
Receiver {
public void childElement(UnmarshallingContext.State state, TagName ea)
throws SAXException {
Loader loader = jaxbContext.selectRootLoader(state,ea);
if(loader!=null)

{ state.loader = loader; // <----- (1) state.receiver = this; return; }

// the registry doesn't know about this element.
// try its xsi:type
...
state.prev.backup = new JAXBElement(...); // <----- (2)
...
}
...
public void receive(State state, Object o) {
if(state.backup!=null)

{ // <---- (3) ((JAXBElement)state.backup).setValue(o); o = state.backup; }

state.getContext().result = o;
}
}

First time its childElemnt() method is called, it cannot find the root element's
definition in the context, so the control reaches to the line marked (2). Next
time the method is called again while it is decoding another XML document, it
finds registered class information in the context and the control reaches the
line marked (1). Note that this 'state' object is reused from the previous run
and its 'backup' field still holds an instance of JAXBElement.
And the control finally reaches to the line marked (3), since 'state.backup'
field is set, the result becomes a wrapping JAXBElement, not a registered
class's instance. If the first run had not occurred, 'state.backup' field would
have stayed null and the results would have been, as expected, a registered
class's instance.
I believe 'state.backup' field should be cleared somewhere between two runs,
however, I am not clear about where the appropriate location is.

Environment

Operating System: All
Platform: All

Affected Versions

[2.0.5]

@glassfishrobot
Copy link
Contributor Author

Reported by kamishim

@glassfishrobot
Copy link
Contributor Author

Was assigned to snajper

@glassfishrobot
Copy link
Contributor Author

File: jaxb-issue-450.java
Attached By: kamishim

@glassfishrobot
Copy link
Contributor Author

kamishim said:
Created an attachment (id=222)
a JUnit test case to clarify the issue

@glassfishrobot
Copy link
Contributor Author

snajper said:
Assigning right priority.

@glassfishrobot
Copy link
Contributor Author

Marked as fixed on Tuesday, January 11th 2011, 12:04:08 am

@glassfishrobot
Copy link
Contributor Author

snajper said:
I believe this was fixed in 2.2.4 with another issue requesting Unmarshaller state to be cleared in between runs.

@glassfishrobot
Copy link
Contributor Author

This issue was imported from java.net JIRA JAXB-450

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant