Jump to: navigation, search

Difference between revisions of "EclipseLink/Release/2.4.0/JAXB RI Extensions/XML Accessor Factory"

 
(22 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>
 
<div style="margin:5px;float:right;border:1px solid #000000;padding:5px">__TOC__</div>
  
= Design Documentation: XML Accessor Factory =
+
= XML Accessor Factory =
  
[http://bugs.eclipse.org/372403 ER 372403]
+
In the current JAXB RI, developed by Sun, there is a series of "proprietary" JAXB extensions which provide advanced functionality outside of the JAXB specification (these extension classes and properties reside in the '''com.sun.xml.bind''' package).
  
In the current JAXB RI, developed by Sun, there are a series of "proprietary" JAXB extensions that are available to provide advanced JAXB functionality outside of the JAXB spec (these extension classes reside in the '''com.sun.xml.bind''' package).
+
By providing implementations of '''Accessor''' and '''AccessorFactory''' classes, the user can provide their own logic for getting and setting property values, at both the Class and Package level.
 
+
By providing implementations of '''Accessor''' and '''AccessorFactory''' classes, the user can provide their own logic for getting and setting property values, both at the Class and Package level.
+
 
+
This document will outline EclipseLink MOXY's support to this extension.
+
  
  
 
= Behaviour =
 
= Behaviour =
  
Classes (or packages) annotated with '''XmlAccessorFactory''' will use the supplied '''AccessorFactory''' subclass to create '''Accessors''' to set and get the values of JAXB properties.  By implementing custom '''Accessor''' classes, the user will have complete control over the setting and getting of property values.  This could be used, for example, to implement a custom lazy-loading strategy.
+
Classes (or packages) annotated with '''XmlAccessorFactory''' will use the supplied '''AccessorFactory''' subclass to create '''Accessors''' responsible for setting and getting the values of JAXB properties.  By implementing custom '''Accessor''' classes, the user will have complete control over the setting and getting of property values.  This could be used, for example, to co-exist with a custom lazy-loading strategy.
  
  
Line 34: Line 30:
  
 
     public Accessor createFieldAccessor(Class type, Field field, boolean isReadOnly) throws JAXBException {
 
     public Accessor createFieldAccessor(Class type, Field field, boolean isReadOnly) throws JAXBException {
         return new MyFieldAccessor(type, field);
+
         return new MyFieldAccessor(type, field, isReadOnly);
 
     }
 
     }
  
 
     public Accessor createPropertyAccessor(Class type, Method getMethod, Method setMethod) throws JAXBException {
 
     public Accessor createPropertyAccessor(Class type, Method getMethod, Method setMethod) throws JAXBException {
         return new MyPropertyAccessor(type);
+
         return new MyPropertyAccessor(type, getMethod, setMethod);
 
     }
 
     }
  
Line 45: Line 41:
 
</div>
 
</div>
  
Next, define one or more subclasses of '''com.sun.xml.bind.v2.runtime.reflect.Accessor''', to be returned from the '''AccessorFactory'''.
+
Next, define one or more subclasses of '''com.sun.xml.bind.v2.runtime.reflect.Accessor''', to be returned from the '''AccessorFactory''':
  
<div style="width:950px">
+
<div style="width:700px">
 
<source lang="java">
 
<source lang="java">
 
import java.lang.reflect.Field;
 
import java.lang.reflect.Field;
Line 57: Line 53:
  
 
     private Field field;
 
     private Field field;
 
+
    private boolean readOnly;   
     protected MyFieldAccessor(Class type, Field f) {
+
 +
     protected MyFieldAccessor(Class type, Field field, boolean isReadOnly) {
 
         super(type);
 
         super(type);
         this.field = f;
+
         this.field = field;
 +
        this.readOnly = isReadOnly;
 
     }
 
     }
  
     public Object get(Object arg0) throws AccessorException {
+
     public Object get(Object obj) throws AccessorException {
         if (MyLazyInitUtil.isInitialized(this.field)) {
+
         if (MyLazyInitUtil.isInitialized(obj, field)) {
 
             try {
 
             try {
 
                 return field.get(obj);
 
                 return field.get(obj);
Line 77: Line 75:
  
 
     public void set(Object obj, Object value) throws AccessorException {
 
     public void set(Object obj, Object value) throws AccessorException {
 +
        if (!readOnly) {
 +
            try {
 +
                field.set(obj, value);
 +
            } catch (Exception e) {
 +
                throw new AccessorException(e);
 +
            }
 +
        }
 
     }
 
     }
  
Line 83: Line 88:
 
</div>
 
</div>
  
= Examples =
+
Finally, add '''com.sun.xml.bind.XmlAccessorFactory''' annotations to your JAXB classes or package-info to enable the '''AccessorFactory''':
 +
 
 +
<code>Employee.java</code>
 +
<div style="width:700px">
 +
<source lang="java">
 +
import javax.xml.bind.annotation.XmlAccessType;
 +
import javax.xml.bind.annotation.XmlAccessorType;
 +
import javax.xml.bind.annotation.XmlRootElement;
 +
 
 +
import com.sun.xml.bind.XmlAccessorFactory;
 +
 
 +
@XmlRootElement
 +
@XmlAccessorType(XmlAccessType.NONE)
 +
@XmlAccessorFactory(MyAccessorFactory.class)
 +
public class Employee {
 +
 
 +
  ...
 +
 
 +
}
 +
</source>
 +
</div>
 +
 
 +
<code>package-info.java</code>
 +
<div style="width:700px">
 +
<source lang="java">
 +
@XmlAccessorFactory(MyAccessorFactory.class)
 +
package org.mypackage;
 +
 
 +
import com.sun.xml.bind.AccessorFactory;
 +
 
 +
</source>
 +
</div>

Latest revision as of 11:35, 18 June 2012

XML Accessor Factory

In the current JAXB RI, developed by Sun, there is a series of "proprietary" JAXB extensions which provide advanced functionality outside of the JAXB specification (these extension classes and properties reside in the com.sun.xml.bind package).

By providing implementations of Accessor and AccessorFactory classes, the user can provide their own logic for getting and setting property values, at both the Class and Package level.


Behaviour

Classes (or packages) annotated with XmlAccessorFactory will use the supplied AccessorFactory subclass to create Accessors responsible for setting and getting the values of JAXB properties. By implementing custom Accessor classes, the user will have complete control over the setting and getting of property values. This could be used, for example, to co-exist with a custom lazy-loading strategy.


Configuration

First, define an implementation of the com.sun.xml.bind.AccessorFactory interface, which specifies two methods: createFieldAccessor() and createPropertyAccessor(). This allows you to provide different functionality for Field access and Property access by defining separate Accessor classes.

import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
import javax.xml.bind.JAXBException;
 
import com.sun.xml.bind.AccessorFactory;
import com.sun.xml.bind.v2.runtime.reflect.Accessor;
 
public class MyAccessorFactory implements AccessorFactory {
 
    public Accessor createFieldAccessor(Class type, Field field, boolean isReadOnly) throws JAXBException {
        return new MyFieldAccessor(type, field, isReadOnly);
    }
 
    public Accessor createPropertyAccessor(Class type, Method getMethod, Method setMethod) throws JAXBException {
        return new MyPropertyAccessor(type, getMethod, setMethod);
    }
 
}

Next, define one or more subclasses of com.sun.xml.bind.v2.runtime.reflect.Accessor, to be returned from the AccessorFactory:

import java.lang.reflect.Field;
 
import com.sun.xml.bind.api.AccessorException;
import com.sun.xml.bind.v2.runtime.reflect.Accessor;
 
public class MyFieldAccessor extends Accessor {
 
    private Field field;
    private boolean readOnly;    
 
    protected MyFieldAccessor(Class type, Field field, boolean isReadOnly) {
        super(type);
        this.field = field;
        this.readOnly = isReadOnly;
    }
 
    public Object get(Object obj) throws AccessorException {
        if (MyLazyInitUtil.isInitialized(obj, field)) {
            try {
                return field.get(obj);
            } catch (Exception e) {
                throw new AccessorException(e);
            }
        } else {
            return null;
        }
    }
 
 
    public void set(Object obj, Object value) throws AccessorException {
        if (!readOnly) {
            try {
                field.set(obj, value);
            } catch (Exception e) {
                throw new AccessorException(e);
            }
        }
    }
 
}

Finally, add com.sun.xml.bind.XmlAccessorFactory annotations to your JAXB classes or package-info to enable the AccessorFactory:

Employee.java

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
 
import com.sun.xml.bind.XmlAccessorFactory;
 
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
@XmlAccessorFactory(MyAccessorFactory.class)
public class Employee {
 
   ...
 
}

package-info.java

@XmlAccessorFactory(MyAccessorFactory.class)
package org.mypackage;
 
import com.sun.xml.bind.AccessorFactory;