Reputation: 4605
In our product we use apache CXF. Because of performance restriction, the schema validation has been set to false. Now, for an integer element if I am providing an invalid value, JAXB is unmarshaling it to some thing else. For example,
9999999999 is converted into 1410065407.
988888888888 is converted into 1046410808.
My question is what is the logic (formula) that is being followed here?
How to handle this (Considering the validation will be off)? I want such a value to be rejected.
Upvotes: 4
Views: 5491
Reputation: 149057
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
SHORT ANSWER
This appears to be a bug in the JAXB reference implementation. I would recommend entering a bug for it at the following location:
This same use case works correctly in EclipseLink JAXB (MOXy).
LONG ANSWER
Below is a complete example that demonstrates the issue:
Root
Below is a domain class with int
and integer
fields.
package forum13216624;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
int int1;
int int2;
Integer integer1;
Integer integer2;
}
input.xml
Below is an XML document with the values from your question.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<int1>9999999999</int1>
<int2>988888888888</int2>
<integer1>9999999999</integer1>
<integer2>988888888888</integer2>
</root>
Demo
In the demo code below I've specified a ValidationEventHandler
on the Unmarshaller
. This should catch a ValidationEvent
for any invalid values encountered during an unmarhsal
operation.
package forum13216624;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(new ValidationEventHandler() {
@Override
public boolean handleEvent(ValidationEvent event) {
System.out.println(event.getMessage());
return true;
}}
);
File xml = new File("src/forum13216624/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
System.out.println(root.int1);
System.out.println(root.int2);
System.out.println(root.integer1);
System.out.println(root.integer2);
}
}
Output - JAXB Reference Implementation
This output matches the behaviour you are seeing.
1410065407
1046410808
1410065407
1046410808
Output - EclipseLink JAXB (MOXy)
If you specify MOXy as your JAXB provider (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html) this use case works as expected. You will get a ValidationEvent
for each invalid value, and if the ValidationEvent
is handled the field/property won't be set to a invalid value.
Exception Description: The object [9999999999], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[int1-->int1/text()]] with descriptor [XMLDescriptor(forum13216624.Root --> [DatabaseTable(root)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "9999999999"
Exception Description: The object [988888888888], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[int2-->int2/text()]] with descriptor [XMLDescriptor(forum13216624.Root --> [DatabaseTable(root)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "988888888888"
Exception Description: The object [9999999999], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[integer1-->integer1/text()]] with descriptor [XMLDescriptor(forum13216624.Root --> [DatabaseTable(root)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "9999999999"
Exception Description: The object [988888888888], of class [class java.lang.String], from mapping [org.eclipse.persistence.oxm.mappings.XMLDirectMapping[integer2-->integer2/text()]] with descriptor [XMLDescriptor(forum13216624.Root --> [DatabaseTable(root)])], could not be converted to [class java.lang.Integer].
Internal Exception: java.lang.NumberFormatException: For input string: "988888888888"
0
0
null
null
POTENTIAL WORKAROUND
If your fields/properties are of type Integer
and you can switch from the JAXB reference implementation then you could create an XmlAdapter
to do your own Integer
to/from String
conversions.
IntegerAdapter
Below is an example of an XmlAdapter
demonstrating how you could provide your own conversion logic.
package forum13216624;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class IntegerAdapter extends XmlAdapter<String, Integer>{
@Override
public Integer unmarshal(String string) throws Exception {
return Integer.valueOf(string);
}
@Override
public String marshal(Integer integer) throws Exception {
return String.valueOf(integer);
}
}
package-info
Using the @XmlJavaTypeAdapter
annotation at the package level means that the XmlAdapter
will apply to all fields/properties of type Integer
for classes in this package.
@XmlJavaTypeAdapter(value=IntegerAdapter.class, type=Integer.class)
package forum13216624;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
Output
Below is the updated output when the RI is used. The int
values are still wrong, but not the Integer
values are null
and ValidationEvents
are produced as expected.
java.lang.NumberFormatException: For input string: "9999999999"
java.lang.NumberFormatException: For input string: "988888888888"
1410065407
1046410808
null
null
For More Information
Upvotes: 7