javajaxbxmladapter

Overriding XmlAdapter for 3rd party library class


I am generating xml using jaxbMarshaller for a third party library class. Since library XmlAdapter which converts Calendar object to string is not using TimeZone field, so marshaller is generating wrong xml for every Calendar field of pojo class.

3rd Party library XmlAdapter is using below class for Calendar to string conversion:

public class DateConversion {
    public static String printDate(Calendar value) {
        if(value != null) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            return format.format(value.getTime());
        }
        return null;
    }
}

So I want to override the behavior of XmlAdapter for Calendar field and tried below example but seems it is not working:

my custom XmlAdapter is using below class for conversion:

public class DateConversion {
    public static String printDate(Calendar value, TimeZone timeZone) {
        if(value != null) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            format.setTimeZone(timeZone);
            return format.format(value.getTime());
        }
        return null;
    }
}

and then I have done registry like:

public @Nullable
    String toPdxmlString(final @NotNull Deals input) {
        try {
            final Marshaller marshaller = jaxbContext.createMarshaller();
            final DateFormatterAdapter dateFormatterAdapter = new DateFormatterAdapter(PdxmlDateTimeUtil.FXONLINE_DEFAULT_DEAL_TIMEZONE);
            marshaller.setAdapter(dateFormatterAdapter);
            StringWriter writer = new StringWriter();
            marshaller.marshal(input, writer);
            return writer.toString();
        } catch (JAXBException exception) {
            LOGGER.error("Unable to marshall the given input Deals: {}, into String using JAXB Context: {}, ... ", input, jaxbContext, exception);
        }
        return null;
    }

Can anyone help me to know if this is doable or not, if yes where I am going wrong?


Solution

  • So I found my solution. I extended XmlAdapter of 3rd party library and pluged in TimeZone field in DateConversion like:

    public class DateFormatterAdapter extends Adapter2 {
        private final TimeZone timeZone;
    
        public DateFormatterAdapter(final TimeZone timeZone) {
            this.timeZone = timeZone;
        }
    
        @Override
        public Calendar unmarshal(String value) {
            return javax.xml.bind.DatatypeConverter.parseDate(value);
        }
    
        @Override
        public String marshal(Calendar calendar) {
            return DateConversion.printDate(calendar, timeZone);
        }
    }
    

    At last registered the extended XmlAdapter as:

    public @Nullable
        String toPdxmlString(final @NotNull Deals input) {
            try {
                final Marshaller marshaller = jaxbContext.createMarshaller();
                final DateFormatterAdapter dateFormatterAdapter = new DateFormatterAdapter(PdxmlDateTimeUtil.FXONLINE_DEFAULT_DEAL_TIMEZONE);
                marshaller.setAdapter(Adapter2.class, dateFormatterAdapter);
                StringWriter writer = new StringWriter();
                marshaller.marshal(input, writer);
                return writer.toString();
            } catch (JAXBException exception) {
                LOGGER.error("Unable to marshall the given input Deals: {}, into String using JAXB Context: {}, ... ", input, jaxbContext, exception);
            }
            return null;
        }