Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "EclipseLink/UserGuide/MOXy/Mapping the Unmappable/Converters"

Line 11: Line 11:
 
= XmlAdapter =
 
= XmlAdapter =
  
JAXB's '''XmlAdapter''' can be used to map classes that would normally be considered "unmappable" - such as classes that do not have a default no-arg constructor, or classes for which an XML representation cannot be automatically determined.  In a custom subclass of '''XmlAdapter''', you can define define custom code to convert the unmappable class into something that JAXB can handle.  Then, you can use the '''XmlJavaTypeAdapter''' annotation to indicate that your adapter should be used when working with the unmappable class.
+
Some Java classes are not well suited for use with JAXB and at first glance may seem "unmappable" - for example, classes that do not have a default no-arg constructor, or classes for which an XML representation cannot be automatically determined.  Using JAXB's '''XmlAdapter''', you can define define custom code to convert the unmappable class into something that JAXB can handle.  Then, you can use the '''@XmlJavaTypeAdapter''' annotation to indicate that your adapter should be used when working with the unmappable class.
  
== Example ==
+
 
 +
== Example - java.util.Currency ==
  
 
Our first example will use the following domain class:
 
Our first example will use the following domain class:
Line 55: Line 56:
 
   public Currency unmarshal(String val) throws Exception {
 
   public Currency unmarshal(String val) throws Exception {
 
       return Currency.getInstance(val);
 
       return Currency.getInstance(val);
 +
  }
 +
 +
}
 +
</source>
 +
 +
To indicate that our adapter should be used for the '''Currency''' property, we annotate it with '''@XmlJavaTypeAdapter''' and provide the class name of our adapter:
 +
 +
<source lang="java">
 +
package example;
 +
 +
import java.util.Currency;
 +
 +
@XmlRootElement
 +
@XmlAccessorType(XmlAccessType.FIELD)
 +
public class PurchaseOrder {
 +
 +
  private Double amount;
 +
 +
  @XmlJavaTypeAdapter(CurrencyAdapter.class)
 +
  private Currency currency;
 +
 +
  ...
 +
}
 +
</source>
 +
 +
 +
== Example - java.awt.Point ==
 +
 +
Sometimes the best way to handle an unmappable class is to write a "stand-in" class which ''can'' be mapped with JAXB, and convert between the two classes in the '''XmlAdapter'''.  In this example, we want to use the '''Point''' class.  Because of that class' '''getLocation()''' method (which JAXB will pickup automatically and map), an infinite loop will occurr during marshalling.  Because we cannot change the '''Point''' class, we will write a new class, '''MyPoint''':
 +
 +
<source lang="java">
 +
package example;
 +
 +
import java.awt.Point;
 +
 +
@XmlRootElement
 +
@XmlAccessorType(XmlAccessType.FIELD)
 +
public class Zone {
 +
 +
  private String name;
 +
 +
  @XmlJavaTypeAdapter(MyPointAdapter.class)
 +
  private Point startCoord;
 +
 +
  @XmlJavaTypeAdapter(MyPointAdapter.class)
 +
  private Point startCoord;
 +
 +
  ...
 +
}
 +
</source>
 +
 +
<source lang="java">
 +
package example;
 +
 +
public class MyPointAdapter extends XmlAdapter<MyPoint, Point> {
 +
 +
  /*
 +
    * Object => XML
 +
    * Given the unmappable Java object, return the desired XML representation.
 +
    */
 +
  public MyPoint marshal(Point val) throws Exception {
 +
      return new MyPoint(val.getX(), val.getY());
 +
  }
 +
 +
  /*
 +
    * XML => Object
 +
    * Given an XML string, use it to build an instance of the unmappable class.
 +
    */
 +
  public Point unmarshal(MyPoint val) throws Exception {
 +
      return new Point(val.getX(), val.getY());
 
   }
 
   }
  
 
}
 
}
 
</source>
 
</source>

Revision as of 13:15, 7 June 2011

EclipseLink MOXy

Eclipselink-logo.gif
EclipseLink
Website
Download
Community
Mailing ListForumsIRCmattermost
Issues
OpenHelp WantedBug Day
Contribute
Browse Source

XmlAdapter

Some Java classes are not well suited for use with JAXB and at first glance may seem "unmappable" - for example, classes that do not have a default no-arg constructor, or classes for which an XML representation cannot be automatically determined. Using JAXB's XmlAdapter, you can define define custom code to convert the unmappable class into something that JAXB can handle. Then, you can use the @XmlJavaTypeAdapter annotation to indicate that your adapter should be used when working with the unmappable class.


Example - java.util.Currency

Our first example will use the following domain class:

package example;
 
import java.util.Currency;
 
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PurchaseOrder {
 
   private Double amount;
 
   private Currency currency;
 
   ...
}

Here, the Currency cannot be automatically mapped with JAXB because it does not contain a no-argument constructor. However, we can write an adapter that will convert the Currency into something that JAXB does know how to handle - a simple String. Luckily, in this case the Currency's toString() method returns the currency code, which can also be used to create a new Currency:

package example;
 
public class CurrencyAdapter extends XmlAdapter<String, Currency> {
 
   /*
    * Object => XML
    * Given the unmappable Java object, return the desired XML representation.
    */
   public String marshal(Currency val) throws Exception {
      return val.toString();
   }
 
   /*
    * XML => Object
    * Given an XML string, use it to build an instance of the unmappable class.
    */
   public Currency unmarshal(String val) throws Exception {
      return Currency.getInstance(val);
   }
 
}

To indicate that our adapter should be used for the Currency property, we annotate it with @XmlJavaTypeAdapter and provide the class name of our adapter:

package example;
 
import java.util.Currency;
 
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class PurchaseOrder {
 
   private Double amount;
 
   @XmlJavaTypeAdapter(CurrencyAdapter.class)
   private Currency currency;
 
   ...
}


Example - java.awt.Point

Sometimes the best way to handle an unmappable class is to write a "stand-in" class which can be mapped with JAXB, and convert between the two classes in the XmlAdapter. In this example, we want to use the Point class. Because of that class' getLocation() method (which JAXB will pickup automatically and map), an infinite loop will occurr during marshalling. Because we cannot change the Point class, we will write a new class, MyPoint:

package example;
 
import java.awt.Point;
 
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Zone {
 
   private String name;
 
   @XmlJavaTypeAdapter(MyPointAdapter.class)
   private Point startCoord;
 
   @XmlJavaTypeAdapter(MyPointAdapter.class)
   private Point startCoord;
 
   ...
}
package example;
 
public class MyPointAdapter extends XmlAdapter<MyPoint, Point> {
 
   /*
    * Object => XML
    * Given the unmappable Java object, return the desired XML representation.
    */
   public MyPoint marshal(Point val) throws Exception {
      return new MyPoint(val.getX(), val.getY());
   }
 
   /*
    * XML => Object
    * Given an XML string, use it to build an instance of the unmappable class.
    */
   public Point unmarshal(MyPoint val) throws Exception {
      return new Point(val.getX(), val.getY());
   }
 
}

Back to the top