Jaxb: global double type conversion using XMLAdapter

I have an element defined as xsd: double. If I try to add the value 285 to the element, and then I marshal it, I get the output 285.0 ... This is normal. However, if I put a value from 285292746, I get output 2.85292746E8 when I am marshal. I like something that double output doesn't convert to scientific decimal notation? Mostly I want 285292746 or 2852292746.0000000

java.lang.Double.toString () uses "computer scientific notation" for specific values ​​that produce isues for xml.

I know that the double representation of the setpoint is beautiful. But the fact that the value was in exponential format, the system I'm working on accepts my XML, but does not know what to do with the exponential value, and this makes my program work incorrectly. Changing xsd: double type in WSDL or server is not possible for me. I work on the client side.

I came across Jaxb: binding for xsd: double type. It is still not easy for me to fix the problem in order to send the values ​​of the double value to a non-exponential format.

package com.logger.client import javax.xml.bind.annotation.adapters.XmlAdapter; import javax.xml.bind.DatatypeConverter; public class JaxbDoubleSerializer extends XmlAdapter<String, Double> { public Double unmarshal(String value) { return ((double)javax.xml.bind.DatatypeConverter.parseDouble(value)); } public String marshal(Double value) { if (value == null) { return null; } return (javax.xml.bind.DatatypeConverter.printDouble((double)(double)value)); } } 

I need help how to use DoubleSerializer so that I can pass values ​​without exponents. I tried using xmlAdapter Annotation in my class MyLogClient.java. I need to know how I can solve this situation.

 package com.logger.client import javax.xml.ws.BindingProvider; import javax.xml.bind.JAXBElement;import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlValue; public class MyLogClient { //Private member fields /** Object factory used to create user-and-role specific objects. */ private static final ObjectFactory _of = new ObjectFactory(); @XmlJavaTypeAdapter(JaxbDoubleSerializer.class) public JAXBElement<Double> msgFileId; @XmlJavaTypeAdapter(JaxbDoubleSerializer.class) public Double dNumber; public final void createEntry; ( final String userName, final String time, final String logMsgStringId, final Params logMsgParamsVal, final Integer logMessageFieldID ) throws JAXBException { JAXBElement<String> username = _of.createParamsParam(userName); JAXBElement<String> strTime = _of.createLogRequestTime(time); // Build the LogRequest request. final LogRequest _LogRequest = _of.createLogRequest(); _LogRequest.setUserName(userName); _LogRequest.setTime(strTime); //Following is the main problem int nMsgArgs = 285292746; dNumber = Double.parseDouble(Integer.toString(nMsgArgs)); //After parsing double Value I get dNumber is now 2.85292746E8 //MsgFile Id is of Type JAXBElement<Double> //CreateLogMessageIdentifier takes Double param //So the main problem is here..the value of double field in soap request //is being sent in exponential format. I need to send as I explained above //285292746. msgFileId = _of.createLogMessageIdentifier(dNumber); JAXBElement<String> strIdVal = _of.createLogMessageFileId(logMsgStringId); final LogMessage logMessage = _of.createLogMessage(); JAXBElement<Params> _logMsgParams =_of.createLogMessageParams(logMsgParamsVal); //Following is where I am trying to use marshall for double type. JAXBContext context = JAXBContext.newInstance("package com.logger.client "); context.createMarshaller().marshal(msgFileId, System.out); logMessage.setIdentifier(msgFileId); //Method takes JAXBElement<Double> logMessage.setFileId(strIdVal ); logMessage.setParams(_logMsgParams); JAXBElement<LogMessage> logMsgValue = _of.createLogRequestLogMessage(logMessage); _LogRequest.setLogMessage(logMsgValue); // Set the log entry port.log(_LogRequest); //Request is sent to server. 

}

WSDL xsd declaration: below: -

  <xsd:complexType name="LogMessage"> <xsd:sequence> <xsd:element name="fileId" type="xsd:string" minOccurs="0" nillable="true" /> <xsd:element name="identifier" type="xsd:double" minOccurs="0" nillable="true" /> <xsd:element name="params" type="tns:Params" minOccurs="0" nillable="true" /> </xsd:sequence> </xsd:complexType> 

Output for identifier field: -

  <identifier> 2.85292746E8</indentifier> Whereas I want to send as. Because system does accept/recognize following types. <identifier> 285292746</indentifier> or <identifier> 285292746.00000000</indentifier> 
+7
source share
2 answers

You can use an external binding file as shown below:

binding.xml

 <jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1"> <jxb:globalBindings> <jxb:javaType name="java.lang.Double" xmlType="xs:double" parseMethod="javax.xml.bind.DatatypeConverter.parseDouble" printMethod="javax.xml.bind.DatatypeConverter.printDouble" /> </jxb:globalBindings> </jxb:bindings> 

root.xsd

 <?xml version="1.0"?> <xs:schema elementFormDefault="qualified" targetNamespace="http://www.example.com" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexType name="root"> <xs:sequence> <xs:element name="foo" type="xs:double" /> <xs:element name="bar" type="xs:double" /> </xs:sequence> </xs:complexType> </xs:schema> 

XJC call

 xjc -d out -b binding.xml root.xsd 

Root

A class created for the root type will have the XmlAdapter classes registered in the Double properties:

 package com.example; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.w3._2001.xmlschema.Adapter1; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "root", propOrder = { "foo", "bar" }) public class Root { @XmlElement(required = true, type = String.class) @XmlJavaTypeAdapter(Adapter1 .class) @XmlSchemaType(name = "double") protected Double foo; @XmlElement(required = true, type = String.class) @XmlJavaTypeAdapter(Adapter1 .class) @XmlSchemaType(name = "double") protected Double bar; public Double getFoo() { return foo; } public void setFoo(Double value) { this.foo = value; } public Double getBar() { return bar; } public void setBar(Double value) { this.bar = value; } } 

Adapter1

The XmlAdapter uses the methods configured in the binding.xml file.

 package org.w3._2001.xmlschema; import javax.xml.bind.annotation.adapters.XmlAdapter; public class Adapter1 extends XmlAdapter<String, Double> { public Double unmarshal(String value) { return (javax.xml.bind.DatatypeConverter.parseDouble(value)); } public String marshal(Double value) { if (value == null) { return null; } return (javax.xml.bind.DatatypeConverter.printDouble(value)); } } 
+7
source

A better way would be to use a custom binding (javaType clause) with your JAXB compiler. The documentation can be found here . Depending on whether you need to marshal and cancel doubling, the solution can be as simple as redefining the mapping to something like BigDecimal at the global level (on the understanding that although double and decimal numbers are completely different things, you it seems like you need a decimal representation) or use a data type converter (the link above gives you examples for all of these options).

+1
source

All Articles