Hi,
I have a schema that specifies for some attributes an enumerated type
and a use="optional" + default value.
The idea was that the user is free to leave out the attribute, and a
default is applied, but at the same I expected that if the user gives a
clearly invalid value then an exception is raised, regardless of whether
schema validation is enabled or not.
This is not the case, without schema validation the invalid value is
silently "eaten", and the member field is set to null. As the default
value is returned from a getter if the member is null, I cannot detect
at all whether the input was wrong.
The main question is whether this is intentional behavior, or whether
this is a bug :)
As example (attached as maven project with a failing test):
-- schema definitions --
<simpleType name="enumType">
<restriction base="string">
<enumeration value="enumA"/>
<enumeration value="enumB"/>
</restriction>
</simpleType>
<complexType name="fooType">
<attribute name="enum" type="tns:enumType" use="optional"
default="enumA"/>
</complexType>
<element name="foo" type="tns:fooType"/>
------------------------
Assume the input XML looks like:
<foo enum='invalid'/>
I tried parsing it like:
JAXBContext ctx = JAXBContext.newInstance(FooType.class);
Unmarshaller u = ctx.createUnmarshaller();
FooType foo = u.unmarshal(theXml);
If the unmarshaller has a schema then an expected validation exception
(cvc-enumeration-valid) is thrown at the unmarshall call, but if there
is no schema then:
1) the value 'invalid' is given to
com.sun.xml.bind.v2.model.impl.RuntimeEnumLeafInfoImpl#parse(String),
which doesn't find the value in the map of valid values, and returns
null.
2) null is set on the foo instance as value for the enum member.
3) when using the getter foo.getEnum() it will determine that
enum is null, and return the default value.
RuntimeEnumLeafInfoImpl#parse() has a comment "TODO: error handling":
public T parse(CharSequence lexical) throws AccessorException, SAXException {
// TODO: error handling
B b = baseXducer.parse(lexical);
if(b instanceof String) { // issue 602 - ugly patch
b = (B) ((String)b).trim();
}
if(b==null) {
return null;
}
return parseMap.get(b); <-- here
}
I think the method should throw some sort of exception if parseMap.containsValue(b) == false, or
call UnmarshallingContext#handleError(), similarly to how other parse() methods are implemented.
Can anyone explain this behavior?
Regards,
--
Andreas
--
Never attribute to malice that which can be adequately explained by
stupidity. -- Hanlon's Razor