Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "EclipseLink/Release/2.4.0/JAXB RI Extensions/ID Resolver"
Line 86: | Line 86: | ||
</div> | </div> | ||
+ | '''Note:''' EclipseLink also supports Sun's IDResolver property names: | ||
+ | |||
+ | <div style="width:850px"> | ||
+ | <source lang="java"> | ||
+ | m.setProperty("com.sun.xml.bind.IDResolver", new MyResolver()); | ||
+ | m.setProperty("com.sun.xml.internal.bind.IDResolver", new MyResolver()); | ||
+ | </source> | ||
+ | </div> | ||
+ | |||
+ | Also note that if you are using a Sun IDResolver with EclipseLink, it will be unable to support EclipseLink's multiple XML IDs feature. In this case, you should re-implement your IDResolver as a subclass of org.eclipse.persistence.jaxb.IDResolver. | ||
== XML Bindings == | == XML Bindings == |
Revision as of 16:24, 28 February 2012
Design Documentation: IDResolver
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).
The abstract class IDResolver provided in the Sun JAXB implementation allows users to override the ID/IDREF processing of the JAXB runtime.
This document will outline the design for an EclipseLink equivalent to this extension.
Requirements
- Deliver an abstract IDResolver class in the EclipseLink library that will provide the same functionality as the Sun extension:
- Given a String id and Object obj, allow the user to perform custom bind code
- Given a String id and Class type, allow the user to perform custom resolve code
- Provide the user a hook into startDocument() and endDocument() events
- Unlike Sun's JAXB implementation, EclipseLink MOXy is not restricted to String-only IDs. Therefore, we will include additional functionality to support complex IDs.
- Given a Map of ID names/values and Object obj, allow the user to perform custom bind code
- Given a Map of ID names/values and Class type, allow the user to perform custom resolve code
- Provide drop-in-replacement support, so that users already using the Sun implementation will not need to change their code when switching to EclipseLink.
Behaviour
If an IDResolver has been set on the Unmarshaller (via properties), then the following things must happen during unmarshal:
- The IDResolver's startDocument() method must be called when unmarshalling starts.
- When an ID value is encountered during unmarshal, the IDResolver's bind method must be called, to bind the object to the ID.
- When an IDREF value is encountered during unmarshal, the IDResolver's resolve method must be used to obtain the object for the IDREF.
- The IDResolver's endDocument() method must be called when unmarshalling completes.
Configuration
The user must extend the following abstract class:
package org.eclipse.persistence.jaxb; import java.util.concurrent.Callable; import javax.xml.bind.ValidationEventHandler; import org.xml.sax.SAXException; /** * IDResolver can be subclassed to allow customization of the ID/IDREF processing of * JAXBUnmarshaller. * * @see JAXBUnmarshaller */ public abstract class IDResolver { public abstract Callable<?> resolve(Object id, Class type) throws SAXException; public abstract Callable<?> resolve(Map<String, Object> id, Class type) throws SAXException; public abstract void bind(Object id, Object obj) throws SAXException; public abstract void bind(Map<String, Object> id, Object obj) throws SAXException; public void startDocument(ErrorHandler errorHandler) throws SAXException {} public void endDocument() throws SAXException {} }
The user's IDResolver class can then be passed to the Unmarshaller through the setProperty() method:
... JAXBContext ctx = ... Unmarshaller u = ctx.createUnmarshaller(); u.setProperty(org.eclipse.persistence.jaxb.JAXBContext.ID_RESOLVER, new MyIDResolver()); ...
Note: EclipseLink also supports Sun's IDResolver property names:
m.setProperty("com.sun.xml.bind.IDResolver", new MyResolver()); m.setProperty("com.sun.xml.internal.bind.IDResolver", new MyResolver());
Also note that if you are using a Sun IDResolver with EclipseLink, it will be unable to support EclipseLink's multiple XML IDs feature. In this case, you should re-implement your IDResolver as a subclass of org.eclipse.persistence.jaxb.IDResolver.
XML Bindings
Because IDResolver is an Unmarshaller property, there is no configuration in XML Bindings.
Examples
Design
Appendix A - Example IDResolver
From Pluggable ID/IDREF handling in JAXB 2.0
import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import com.sun.xml.bind.IDResolver; class MyIDResolver extends IDResolver { Map<String, Apple> apples = new HashMap<String, Apple>(); Map<String, Orange> oranges = new HashMap<String, Orange>(); void startDocument() { apples.clear(); oranges.clear(); } public void bind(String id, Object obj) { if (obj instanceof Apple) apples.put(id, (Apple) obj); else oranges.put(id, (Orange) obj); } public Callable resolve(final String id, final Class targetType) { return new Callable() { public Object call() { if (targetType == Apple.class) return apples.get(id); else return oranges.get(id); } }; } }
Document History
Date | Author | Version Description & Notes |
---|---|---|
111007 | Rick Barkhouse | 1.00 : First draft |
111017 | Rick Barkhouse | 1.01 : Considering possibility of supporting complex IDs |
111020 | Rick Barkhouse | 1.02 : Revising design to support complex (non-String, composite) IDs |