July 12, 2010

XmlAdapter - JAXB's Secret Weapon

The XmlAdapter mechanism in JAXB ensures that there is no such thing as an unmappable class (with a little programmatic help). However there appears to be some confusion on how to use XmlAdapter, below is the general concept:
  1. Identify the unmappable class
  2. Create an equivalent class that is mappable
  3. Create an XmlAdapter to convert between unmappable and mappable objects
  4. Specify the XmlAdapter
Part of the problem may be due to the Javadocs on the XmlAdapter class. Below I'll flush out the example used there.


1. Identify the Unmappable Class

 In this example the unmappable class is java.util.Map.

2.  Create an Equivalent Class that is Mappable

Map could be represented by an object (MyMapType), that contained a list of objects with two properties: key and value (MyMapEntryType).

import java.util.ArrayList;
import java.util.List;

public class MyMapType {

   public List<MyMapEntryType> entry = 
      new ArrayList<MyMapEntryType>();

}

and
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.XmlAttribute;

public class MyMapEntryType {

   @XmlAttribute
   public Integer key; 

   @XmlValue
   public String value;

}

3. Create an XmlAdapter to Convert Between Unmappable and Mappable Objects


The XmlAdapter<ValueType, BoundType> class is responsible for converting between instances of the unmappable and mappable classes. Most people get confused between the value and bound types. The value type is the mappable class, and the bound type is the unmappable class.
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.annotation.adapters.XmlAdapter;
 
public final class MyMapAdapter extends
 
   XmlAdapter<MyMapType,Map<Integer, String>> {
 
   @Override
   public MyMapType marshal(Map<Integer, String> arg0) throws Exception {
      MyMapType myMapType = new MyMapType();
      for(Entry<Integer, String> entry : arg0.entrySet()) {
         MyMapEntryType myMapEntryType = 
            new MyMapEntryType();
         myMapEntryType.key = entry.getKey();
         myMapEntryType.value = entry.getValue();
         myMapType.entry.add(myMapEntryType);
      }
      return myMapType;
   }
 
   @Override
   public Map<Integer, String> unmarshal(MyMapType arg0) throws Exception {
      HashMap<Integer, String> hashMap = new HashMap<Integer, String>();
      for(MyMapEntryType myEntryType : arg0.entry) {
         hashMap.put(myEntryType.key, myEntryType.value);
      }
      return hashMap;
   }
 
}

4. Specify the XmlAdapter

The @XmlJavaTypeAdapter annotation is used to specify the use of the XmlAdapter. Below it is specified on the map field on the Foo class. Now during marshal/unmarshal operations the instance of Map is treated as an instance of MyHashMapType.

import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {

   @XmlJavaTypeAdapter(MyMapAdapter.class)
   Map<Integer, String> map = 
    new HashMap<Integer, String>();

   public Map getMap() {
      return map;
   }

   public void setMap(Map map) {
      this.map = map;
   }

}

In upcoming posts I'll describe extensions in the EclipseLink JAXB (MOXy) implementation that reduce the dependency on XmlAdapter.

Further Reading

If you enjoyed this post, then you may also be interested in:
  • JAXB and Immutable Objects
    In this post an XmlAdapter is used map a domain object with a mult-argument constructor and fields marked final.  This example also demonstrates how the @XmlJavaTypeAdapter annotation can be used at the type level.
  • @XmlTransformation - Going Beyond XmlAdapter
    In this post an EclipseLink MOXy extension (@XmlTransformation) is used instead of @XmlAdapter to provide a little more flexibility for an interesting use case.

55 comments:

  1. Nicely explained!

    But I have even more subtle problem. I have complex data structures such as Vector > and HashMap> i.e. vector inside vector and vector inside hashmaps. Could you please help me on how I should marshall/unmarshall?

    ReplyDelete
  2. The process would be very similar.

    Vector Inside a HashMap
    If we consider you case with a Vector inside a HashMap. You would change the MyMapEntryType so that the value property was a Vector.

    Vector Inside a Vector
    For this use case your intermediate object would be a Vector of Value objects, each Value Object would have a value property representing the nested Vector.

    ReplyDelete
  3. Great post Blaise!

    I'm using XMLAdapter with a List, but I'm having a problem. Marshalling the entities of the List, the < and > tags are replaced by < and >

    A Customer as some attibutes (id, name, ...) and a DocumentSet (basically a List). This DocumentSet is extendind the XMLAdapter where I do this;

    public class DocumentSetAdapter extends XmlAdapter {

    public String marshal(DocumentSet val) throws Exception {

    java.io.StringWriter sb = new java.io.StringWriter();

    for (Document d : val.getDocument()) {
    if (d instanceof IdentificationCard) {
    sb.append(((IdentificationCard) d).toXml(false));
    } else if (d instanceof DrivingLicense) {
    sb.append(((DrivingLicense) d).toXml(false));
    } else if (d instanceof Passport) {
    sb.append(((Passport) d).toXml(false));
    }
    }

    return sb.toString();
    }

    IdentificationCard and DrivingLicense extend Document.

    The toXML method does the marshalling, and is the same in every class.

    The one is called first is the Customer and is like this:

    public String toXml(boolean header) throws javax.xml.bind.JAXBException {

    java.io.StringWriter sw = new java.io.StringWriter();
    javax.xml.bind.JAXBContext jc = javax.xml.bind.JAXBContext.newInstance(Customer.class);
    javax.xml.bind.Marshaller m = jc.createMarshaller();
    m.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
    m.marshal(this, sw);

    return sw.toString();
    }

    The output xml is:


    customer1
    Carlos
    EMPLOYEE
    premium
    active
    2010-11-12T16:20:48.752Z
    <identificationCard>
    <id>1</id>
    <description>BI</description>
    <issueDate>2010-11-12T16:20:48.759Z</issueDate>
    <expireDate>2010-11-12T16:20:48.759Z</expireDate>
    <birthPlace>Aveiro</birthPlace>
    <identificationNumber>123131231</identificationNumber>
    </identificationCard><drivingLicense>
    <id>2</id>
    <description>NIF</description>
    <issueDate>2010-11-12T16:20:48.759Z</issueDate>
    <expireDate>2010-11-12T16:20:48.759Z</expireDate>
    <licenseNumber>9654477</licenseNumber>
    <vehicleCat>A</vehicleCat>
    </drivingLicense>


    and the correct would be:



    customer1
    Carlos
    EMPLOYEE
    premium
    active
    2010-11-12T16:26:09.891Z


    1
    BI
    2010-11-12T16:26:09.893Z
    2010-11-12T16:26:09.893Z
    Aveiro
    123131231


    2
    NIF
    2010-11-12T16:26:09.893Z
    2010-11-12T16:26:09.893Z
    9654477
    A




    Could you help me with this?

    Best regards,
    Carlos

    ReplyDelete
  4. Hi Carlos,

    When using XmlAdapter you are converting from an object that JAXB cannot map to one that it can. In your example you are converting to a String that contains XML markup. This is causing JAXB to escape some of the characters. Instead you should convert to an object that would produce the desired XML.

    Some of the details of your message were lost due to the XML escaping aspect of this blog. Feel free to message me from the blog with about this issue:

    - http://bdoughan.blogspot.com/p/contact_01.html

    -Blaise

    ReplyDelete
  5. Very nice article!
    I was wondering, if my JAXB annotated classes are generated based on a given XSD file, how can I specify my adapters, knowing that every time I changed the XSD file, all classes will also be regenerated?

    ReplyDelete
  6. Hi Bogdan,

    The XmlAdapter mechanism is used when starting with Java classes and you have an unmappable class. When you start from an XML schema, the JAXB schema compiler tool (XJC) generates compatible classes, no XmlAdapter is necessary.

    -Blaise

    ReplyDelete
  7. Hi Carlos,

    Thank you for sending me the sample code. I have just emailed you an example that demonstrates how XmlAdapter could be used.

    I do not recommend the approach that you are attempting where the adapted type is a String that contains XML markup. You may be able to make this work with streams, but it will not work when dealing with DOM/SAX/StAX inputs and outputs.

    -Blaise

    ReplyDelete
  8. Hi Blaise,

    I'm encoutering an issue, where the objects generated from JAXB (through Maven) having no no-arg constructors on Windows couldn't work when they're deployed in server on Linux during creation of JAXBContext - complaining of no no-arg public constructor. Is that something XmlAdapter could resolve?

    Thanks,
    - John

    ReplyDelete
  9. Hi John,

    It is common to use an XmlAdapter for classes that do not have a no-arg constructor. However, JAXB should not be creating classes without a no-arg constructor. Feel free to send me more details about your setup through the "Contact Me" page on this blog.

    -Blaise

    ReplyDelete
  10. The MyMapAdapter does not compile
    imcompatible types
    found : java.lang.Object
    required: java.util.Map.Entry
    for (Entry entry : arg0.entrySet()) {

    ReplyDelete
  11. The compilation issue should be fixed now. Looks like I forgot to escape the '<' characters in my code samples. Thanks for identifying the issue.

    ReplyDelete
  12. If you do *not* use an Adapter, this works:
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Simple {

    private Map map = new HashMap();

    }

    This does not:
    @XmlRootElement
    public class Simple {

    @XmlElement
    private Map map = new HashMap();

    }


    Why is this?

    ReplyDelete
  13. rmuller,

    That appears to be a bug in the JAXB reference implementation (Metro). This issue does not occur when you use EclipseLink JAXB (MOXy).

    -Blaise

    ReplyDelete
  14. Thank you. These blogs are the best tutorial for Moxy.

    Now what I'd really like to do is convert the map "directly", i.e., eliminate the key and value elements, by using the keys for the element names, and the values for the element contents. I've tried returning a DynamicEntity in the marshall methodd, but not successfully. And I don't know of an Annotation that lets me specify a field as providing the element name. Am I missing something obvious?

    ReplyDelete
  15. Class MyMapAdapter won't compile. Here is the corrected version:

    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;

    import javax.xml.bind.annotation.adapters.XmlAdapter;

    public final class MyMapAdapter extends

    XmlAdapter> {

    @Override
    public MyMapType marshal(Map arg0) throws Exception {
    MyMapType myMapType = new MyMapType();
    for (Entry entry : arg0.entrySet()) {
    MyMapEntryType myMapEntryType = new MyMapEntryType();
    myMapEntryType.key = entry.getKey();
    myMapEntryType.value = entry.getValue();
    myMapType.entry.add(myMapEntryType);
    }
    return myMapType;
    }

    @Override
    public Map unmarshal(MyMapType arg0) throws Exception {
    HashMap hashMap = new HashMap();
    for (MyMapEntryType myEntryType : arg0.entry) {
    hashMap.put(myEntryType.key, myEntryType.value);
    }
    return hashMap;
    }

    }


    runnable Demo:
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;

    public class Demo {

    public static void main(String[] args) {

    Foo foo = new Foo();

    foo.getMap().put(1, "one");
    foo.getMap().put(2, "two");
    foo.getMap().put(3, "three");

    try {
    JAXBContext ctx = JAXBContext.newInstance(Foo.class);
    Marshaller m = ctx.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    m.marshal(foo, System.out);
    } catch (JAXBException e) {
    e.printStackTrace();
    }
    }

    }

    Thanks, your article was helpful.

    ReplyDelete
  16. Hi

    Thank you for these wonderful tutorials.

    I have an issue, that is
    I'm trying to parse the XML response into POJO(may not be reversely).
    For this I'm using Jaxb2Marshaller with MarshallingHttpMessageConverter through Spring RestTemplate [postForObject].
    My setup is fine to map the child with its direct parent element using like @XmlElementWrapper.

    But I wanna to map elements like by its name, That is I need only some of the elements from the whole xml. Is this possible with xmladapter or by somthing else. pls let me know ASAP. I hope you understand my case.

    Thanks
    Prakash.

    ReplyDelete
  17. Hi Prakash,

    The following may be of help:
    - XPath Based Mapping - Geocode Example

    Feel free to contact me with additional details:
    - Contact Me

    -Blaise

    ReplyDelete
  18. Hi Blaise,

    Its an interesting pattern, thanks for sharing. I would like to ask you if jaxb can be used to map a hashmap like

    Element key=val key=val

    where Element would be root element and key,vals are attributes. Can names of XmlAttribute be dynamic? Even if you can point me in the right direction it would be of great help. Cheers!

    ReplyDelete
  19. Hi Carlo,

    Thank you for sending the corrected code. I apologize in the delay for posting it.

    -Blaise

    ReplyDelete
  20. Hi, Blaise,

    Nice article.

    I am facing an interesting problem. I need to unmarshall following into an ArrayList of Customer objects.






    The problem is that the top level object is ArrayList which is not mappable.

    I created a class extending ArrayList and annotate it like this.

    @XmlRootElement(name="collection")
    public class MyArrayList extends ArrayList {
    }

    But this does not help. Is there a way to use XmlAdapter to take care of this problem?

    ReplyDelete
  21. Hi, Blaise,

    I think I didn't ask this clear in my first comment.

    The problem is that the entities in the collection is of generic type. So, it could be Customer or it could be Vendor.











    Is there a way to achieve this?

    Thanks,
    Xianguan

    ReplyDelete
  22. I have the following collection class. Note the XmlElement(name="yes"), how can I not specify the element name and let the type decide on the name of the element?

    @XmlRootElement(name="collection")
    public class MyCollections {


    private List items;

    @XmlElement(name="yes")
    public List getItems() {
    return items;
    }

    public void setItems(List items) {
    this.items = items;
    }

    }

    ReplyDelete
  23. Hi Xianguan,

    If you know the types in advance I would recommend using the @XmlElements annotation. This corresponds to the choice concept in XML schema:

    - JAXB and XSD Choice: @XmlElements

    However if you don't know the types if advance you can leverage @XmlAnyElement(lax=true) for this:

    - Using @XmlAnyElement to Build a Generic Message

    -Blaise

    ReplyDelete
  24. @XmlAnyElement(lax=true) worked beautifully for me. Thank you so much!

    ReplyDelete
  25. From what I can tell, java.util.Calendar loses timezone information when it is marshalled/unmarshalled to XML. In particular, it loses timezone information because the timezone is expressed as an offset from GMT like this: "-07:00" rather than the more proper ID form "America/Los_Angeles". I can envision a solution to this problem using XMLAdapter and the creation of a MyCalendar class, but wanted to know if this is the best way to tackle this issue.

    ReplyDelete
  26. Below is the code I used to properly serialize a java.util.Calendar along with its timezone. This whole problem brings up an interesting question: Does a calendar represent an instant in time (i.e. millis since epoch in GMT), or does it represent that instant in time at a particular location (a timezone).


    @XmlAccessorType(XmlAccessType.NONE)
    public class SerializableCalendar {

    @XmlElement
    private Calendar calendar = null;
    @XmlElement
    private String tzID = null;

    public Calendar getCalendar() {
    return calendar;
    }

    public void setCalendar(Calendar calendar) {
    this.calendar = calendar;
    }

    public String getTzID() {
    return tzID;
    }

    public void setTzID(String tzID) {
    this.tzID = tzID;
    }
    }

    public final class SerializableCalendarAdapter extends XmlAdapter {

    @Override
    public Calendar unmarshal(SerializableCalendar sc) throws Exception {
    Calendar c = sc.getCalendar();
    c.setTimeZone(TimeZone.getTimeZone(sc.getTzID()));

    return c;
    }

    @Override
    public SerializableCalendar marshal(Calendar c) throws Exception {
    SerializableCalendar sc = new SerializableCalendar();
    sc.setCalendar(c);
    sc.setTzID(c.getTimeZone().getID());

    return sc;
    }
    }

    ReplyDelete
  27. Hi Ken,

    JAXB marshals time zone information based on the XML schema representation of 'Z' for UTC and '+hh:mm' or '-hh:mm' for offsets.

    xsd:time formats:
    hh:mm:ssZ
    hh:mm:ss+hh:mm
    hh:mm:ss-hh:mm

    An XmlAdapter is a reasonable way to provide alternate representations.

    -Blaise

    ReplyDelete
  28. Blaise and co: this was really helpful, thank you all (Blaise especially.)

    One quick note: it's interesting to see how JAXB treats annotations in the MyMapType wrapper class. Maybe say a word or two about that?)

    ReplyDelete
  29. Gr8 article blaise,
    I am having trouble to figure out how to tackle above issue?
    I want to create a class for xml file containing element with a pipe seperated data field with new line character to seperate multiple record.
    For eg:

    1234 |HERNANDEZ MICHEAL E | 9195672232 | 01/10/2011 08:00:00|Y|Y222|1|ETR|Lightning \n
    2345 |JONATHAN SILOH|9019876534| 01/10/2011 08:00:00|Y|Y297|2|ETR|Overload \n


    How could I track this element information efficiently using JAXB API?

    Thank You,
    Rushikey

    ReplyDelete
  30. Hi Rushikey,

    You could use an XmlAdapter for this use case. The bound type (unmappable object) will be whatever you will convert that value to, and the value type (mappable object) will be java.lang.String. Then in the adapter you will need to write the code to convert to/from the piped data.

    -Blaise

    ReplyDelete
  31. Blaise,

    Very good presentation and very easy to understand. Lot of thanks for spending your time to help us.

    ReplyDelete
  32. Thanks Blaise!!
    I was trying to unmarshal Clob since yesterday. This really helped.

    Thanks,
    Sid

    ReplyDelete
  33. Thank you Blaise as well.

    I am interested in the order of the items inside a list but I see that the marshalling/unmarshalling process does not respect the original order of the items.

    For example if I construct an object list with items a, b, c and I change the order to c, b, a the exported XML will have the original order.

    How I will make sure that the order of the items of my list in the exported XML will be the same with the order of the Java list object (and vice versa)?

    Do I have to use adapters for this?

    Thank you in advance.

    ===
    Apartment for rent in Litochoro --> www.litochoro.eu
    ===

    ReplyDelete
  34. Hi Klearchos,

    Assuming that you are representing your collection using the java.util.List type that maintains order, the marshalled XML should match this order.

    Could you send me more details via my "Contact Me" page?

    -Blaise

    ReplyDelete
  35. thank you !
    it'll be perfect if we could see the xsd file.
    Because I'm doin' all this, but something must be wrong in my xsd and I thought I could look at yours in the example

    ReplyDelete
    Replies
    1. Hi,

      I'm confused on why are you looking for the XML schema. Are you looking to generate this model? This example is specifically aimed at starting from a Java model.

      -Blaise

      Delete
    2. I thought as specified in javadoc http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/api/javax/xml/bind/annotation/adapters/XmlAdapter.html
      xmladapter only works with an xsd file, but I might have misunderstood..

      Delete
    3. It may be step 2 from that link (http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/api/javax/xml/bind/annotation/adapters/XmlAdapter.html) that is causing some confusion. What that step really means is you need to decide what you want the XML to look like, and then you need to create value objects that correspond to the desired XML format.

      -Blaise

      Delete
  36. Hi,
    Is there any way to declare required and nillable as if @XmlElementWrapper(required = true, nillable=true) Collection types;

    ReplyDelete
    Replies
    1. Hi Jin,

      Not sure I understand your question. @XmlElementWrapper does allow you to specify required and nillable for Collection types. The required property corresponds to schema generation. The nillable aspect in addition to affected schema generation will cause the wrapper element to be written with the xsi:nil="true" attribute for null collections. Without this setting the wrapper element is not marshalled.

      -Blaise

      Delete
  37. I want to implement JAXB for Test class,i find that if variables are final,is it not possible to inject JAXB? Will XmlAdapter help in this case?
    public class Test implements Serializable {
    private final int limit;
    private Map results;
    private final Sub sub;
    @XmlElementWrapper(name = "item") //tried with this also,but not successfull
    @XmlAnyElement
    private final List item;
    }
    public class Item implements Serializable {
    private Base base;// Interface
    public Item(final Base base) {
    this.base = base;
    }
    }

    ReplyDelete
    Replies
    1. The following may help:
      - JAXB and Immutable Objects

      I am also aware of this question on Stack Overflow. It is probably easiest to tackle in on that forum:
      - final property to bind JAXB

      -Blaise

      Delete
  38. Based off my (admittedly short) research into XMLAdapter, it seems the annotation used to identify the adapter cannot be parametrized. Is this truly the case? It seems onerous to define an adapter class for each type of parameter combinations used with the Map class. If this is the case, do you have any thoughts on why this limitation exists? I am an not well versed enough on the inner workings of Java to guess at the Apache folks' reasoning.

    ReplyDelete
    Replies
    1. Hi Matthew,

      One reason for the limitation is that the Java language does not allow you to specify a parameterized type as a value on an annotation.

      You may find the following post helpful:
      - Java Tip of the Day: Generic JAXB Map XmlAdapter

      BTW - Apache did not participate in the development of the JAXB (JSR-222) specification. There were representatives from: Sun, Oracle (myself), IBM, BEA, SAP, and quite a few other companies.

      -Blaise

      Delete
  39. Hi Blaise,

    Above you created XMLAdapter using HashMap can we do samething using ArrayList.

    Thanks in Advance

    ReplyDelete
    Replies
    1. Hi,

      You can use an XmlAdapter with an ArrayList property, but the XmlAdapter will be applied to each item in the collection instead of the collection as a whole.

      -Blaise

      Delete
  40. Hello Blaise,

    Can you please tell me what data type should I mention in my XSD file while using adapters.
    Will it be the user defined java/util/Map equivalent class or something else.

    Thanks

    ReplyDelete
    Replies
    1. Hello,

      XmlAdapters are mainly used when starting from Java objects. Below is an example that demonstrates how they can be applied when starting from an XML schema.
      - XML Schema to Java - Generating XmlAdapters

      -Blaise

      Delete
  41. Hi Blaise,

    can we use an Adapter Class for sql Connection interface ? As we know JAXB can not handle Interface.

    - Gopi

    ReplyDelete
    Replies
    1. Hi Gopi,

      Yes you can use this approach for handling interfaces. Below is another article you may find interesting about supporting interfaces in JAXB.
      - JAXB and Interface Fronted Models

      -Blaise

      Delete
  42. Hello Blaise,

    Thank you for your valuable blog posts !

    On the subject of XmlAdapter, I was wondering if you could have a look at my SO question ?

    http://stackoverflow.com/questions/19842179/how-to-ignore-disable-revert-override-jaxb-class-level-xmljavatypeadapter-in-ce

    I'd like to have an elegant implementation that is along the lines of JAXB's philosophy.

    Thank you in advance !

    -C

    ReplyDelete
    Replies
    1. I have posted an answer on your Stack Overflow question:
      - http://stackoverflow.com/a/19940091/383861

      You can find more information in the following link:
      - Mixing Nesting and References with JAXB's XmlAdapter

      Delete
  43. Hi Blaise,

    Is it possible to use an external value in the XmlAdapter? I have the following pojo

    class Task{

    int id;
    Timezone timezone;

    @XmlJavaTypeAdapter(type = DateTime.class, value = DateTimeAdapter.class)
    DateTime startDate;

    ....

    }

    And the XmlAdapter

    public class DateTimeAdapter extends XmlAdapter {

    private static final DateTimeFormatter dateFormat = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");

    public DateTime unmarshal(String dateString) throws Exception {

    return (StringUtils.isNotEmpty(dateString) ? dateFormat.withZoneUTC().parseDateTime(dateString) : null);
    }

    public String marshal(DateTime dateTime) throws Exception {

    return (dateTime != null ? dateFormat.print(dateTime) : null);
    }

    }

    I would like to use the timezone set in the same pojo when marshalling and unmarshalling the DateTime. Can I somehow pass the timezone to the marshaller?

    ReplyDelete
    Replies
    1. Hi Banu,

      By default a JAXB impl will create a new instance of the XmlAdapter each time it is used. If you want it to be stateful you can set a configured instance via the setAdapter methods on Marshaller/Unmarshaller.

      -Blaise

      Delete

Note: Only a member of this blog may post a comment.