In any case, pass the constructor parameter to the JAXB adapter?

I am using Spring 3 IOC and JAXB / JAX-WS in the WebService that I wrote. Now I have a small problem with the data, which must be rounded before returning to the consumer, since they are not able to handle the full accuracy of the values.

To minimize the impact on WS design and calculations, I decided to use the Jaxb XmlAdapter to round the values ​​when sorting my answer. Everything is working fine.

Now my problem is that I would like to make it flexible. That is: in some cases I need to round to two decimal places, in some 4, etc. Right now, I have to create TwoDecimalAdapter and FourDecimalAdapter and use the appropriate, when necessary, in my model definitions. This means code duplication.

Do I need to create a common Rounding Adapter and pass a parameter to it? For example, instead of:

@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=FourDecimalRoundingAdapter.class,type=java.math.BigDecimal.class) 

I would like to do something like:

 @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=new RoundingAdapter(4),type=java.math.BigDecimal.class) 

Obviously this does not work, since JAXB instantiates the adapter itself, but is there any method I can use to pass parameters to the adapter? I would like to declare a rounding adapter in Spring and use it that way, but again, I cannot develop a reusable solution.

Thanks,

Eric

+8
source share
2 answers

I'm not sure how you connect this using Spring, but the following is a description of the JAXB mechanism you can use.

If you have the following:

 @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter(value=RoundingAdapter.class,type=java.math.BigDecimal.class) 

Then, using the stand-alone JAXB APIs, you can do the following. The code below means that whenever a RoundingAdapter is RoundingAdapter , the specified instance must be used.

 marshaller.setAdapter(new RoundingAdapter(4)); unmarshaller.setAdapter(new RoundingAdapter(4)); 

Additional Information

+2
source

using

 import com.company.BigDecimalAdapter.X$XXXX; ... @XmlElement(name = "QTY") @XmlJavaTypeAdapter(X$XXXX.class) private BigDecimal quantity; 

BigDecimalAdapter

 import static java.math.RoundingMode.HALF_UP; import java.math.BigDecimal; import java.text.DecimalFormat; import javax.xml.bind.annotation.adapters.XmlAdapter; public class BigDecimalAdapter extends XmlAdapter<String, BigDecimal> { public static final class X$XX extends BigDecimalAdapter { public X$XX() { super("#.##"); } } public static final class X$00 extends BigDecimalAdapter { public X$00() { super("#.00"); } } public static final class X$XXXX extends BigDecimalAdapter { public X$XXXX() { super("#.####"); } } private final ThreadLocal<DecimalFormat> format; public BigDecimalAdapter(String pattern) { format = ThreadLocal.withInitial(() -> { DecimalFormat df = new DecimalFormat(pattern); df.setRoundingMode(HALF_UP); return df; }); } @Override public String marshal(BigDecimal v) throws Exception { return format.get().format(v); } @Override public BigDecimal unmarshal(String v) throws Exception { return new BigDecimal(v); } } 
0
source

All Articles