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

EclipseLink/Development/DBWS/MetadataSupport

< EclipseLink‎ | Development‎ | DBWS
Revision as of 13:46, 4 January 2013 by David.mccann.oracle.com (Talk | contribs) (Design document for adding JPA/JAXB metadata support to DBWS)

Design document for adding JPA/JAXB metadata support to DBWS

The purpose of this document is to outline what changes are to be made to the DBWS codebase to allow support for reading/writing JPA/JAXB metadata in place of EclipseLink deployment XML. This feature is required to resolve EclipseLink Bug 332227.

Overview

The DBWS builder constructs OR/OX projects, which are marshalled to a given output stream by the builder and placed in a generated .war archive for use by the DBWS runtime. The builder currently utilizes the legacy EclipseLink deployment XML format for this purpose, but is required to move to the modern JPA/JAXB metadata format.

Requirements

  • Support generation and marshal of JPA and JAXB metadata files in the DBWS builder
  • Support unmarshal of JPA and JAXB metadata files in the DBWS runtime
  • Support unmarshal of legacy OR/OX deployment XML for backward compatibility

JAXB Metadata support

The existing DBWS builder code utilizes the ObjectPersistenceWorkbenchXMLProject class to marshal the OX project at design time and unmarshal it at runtime. The code will be changed to instead use JAXB metadata for these operations. The following pages contain information pertaining to EclipseLink's support for JAXB annotations via XML metadata:

The DBWS builder creates an OX project; this project's descriptors - and each descriptor's mappings - will be used to generate one or more <xml-bindings> elements (one per package) that make up the JAXB metadata file. Two classes are needed to accomplish this task:

  • XmlBindingsModel - used to create a JAXB context that can be used to marshal/unmarshal the metadata file.
  • XmlBindingsGenerator - generates one or more <xml-bindings> elements (one per package) based on a list of Descriptor instances

The generated metadata file will have the format:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xml-bindings-list xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm">
  <xml-bindings package-name="simpletable">
    ...
  </xml-bindings>
  <xml-bindings package-name="complextable">
    ...
  </xml-bindings>
  ...
</xml-bindings-list>

org.eclipse.persistence.internal.xr.XmlBindingsModel

The XmlBindingsModel class will be used to create a JAXBContext instance that is able to marshal and unmarshal the generated JAXB metadata file.

/**
 * This class is responsible for holding a list of XmlBindings.
 *
 */
@XmlAccessorType(javax.xml.bind.annotation.XmlAccessType.FIELD)
@XmlRootElement(name="xml-bindings-list", namespace="http://www.eclipse.org/eclipselink/xsds/persistence/oxm")
public class XmlBindingsModel {
    @XmlElement(name="xml-bindings", namespace="http://www.eclipse.org/eclipselink/xsds/persistence/oxm")
    public List<XmlBindings> bindingsList;
 
    /**
     * Return the list of XmlBindings
     */
    public List<XmlBindings> getBindingsList() {
        return bindingsList;
    }
 
    /**
     * Set the list of XmlBindings.
     */
    public void setBindingsList(List<XmlBindings> bindingsList) {
        this.bindingsList = bindingsList;
    }
}

org.eclipse.persistence.tools.dbws.XmlBindingsGenerator

This class is responsible for generating a JAXB metadata file containing one or more <xml-bindings> elements (one per package) based on a given list of Descriptor instances. The following OX mappings must be supported:

  • XMLBinaryDataMapping
  • XMLCompositeCollectionMapping
  • XMLCompositeDirectCollectionMapping
  • XMLCompositeObjectMapping
  • XMLDirectMapping

The following API is required:

/**
 * Generate one or more XmlBindings based on a given list of
 * ClassDescriptor instances.
 * 
 */
public static List<XmlBindings> generateXmlBindings(List<ClassDescriptor> descriptors)
/**
 * Generate an XmlBindings instance based on a list of XML descriptors.
 * 
 * OXM metadata files are processed on a per package basis, hence it is
 * assumed that the given list of descriptors are from the same package.
 * 
 */
public static XmlBindings generateXmlBindings(String packageName, List<XMLDescriptor> descriptors)

Example XmlBindings list generation and marshal operation

The following example illustrates how the XmlBindingsGenerator can be used to generate a list of org.eclipse.persistence.jaxb.xmlmodel.XmlBindings instances, and how this list can be marshalled to a given output stream:

List<XmlBindings> xmlBindingsList = XmlBindingsGenerator.generateXmlBindings(oxProject.getOrderedDescriptors());
if (xmlBindingsList.size() > 0) {
    XmlBindingsModel model = new XmlBindingsModel();
    model.setBindingsList(xmlBindingsList);
    try {
        JAXBContext jc = JAXBContext.newInstance(XmlBindingsModel.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(model, dbwsOxStream);
    } catch (JAXBException jaxbEx) {
        throw new DBWSException(OXM_MARSHAL_EX_MSG, jaxbEx);
    }
}

Note that the existing marshal code in BaseDBWSBuilderHelper.writeOrOxProjects should be removed and the above code (or similar) should be used.

Example XmlBindings list generation and marshal operation

The following example illustrates how the XmlBindingsGenerator can be used to generate a list of org.eclipse.persistence.jaxb.xmlmodel.XmlBindings instances, and how this list can be marshalled to a given output stream:

Map<String, DBWSMetadataSource> metadataMap = new HashMap<String, DBWSMetadataSource>();
StreamSource xml = new StreamSource(inStream);
try {
    JAXBContext jc = JAXBContext.newInstance(XmlBindingsModel.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
 
    JAXBElement<XmlBindingsModel> jaxbElt = unmarshaller.unmarshal(xml, XmlBindingsModel.class);
    XmlBindingsModel model = jaxbElt.getValue();
    for (XmlBindings xmlBindings : model.getBindingsList()) {
        metadataMap.put(xmlBindings.getPackageName(), new DBWSMetadataSource(xmlBindings));
    }
} catch (JAXBException jaxbex) {
    throw new DBWSException(OXM_PROCESSING_EX, jaxbex);
}
 
Map<String, Map<String, DBWSMetadataSource>> properties = new HashMap<String, Map<String, DBWSMetadataSource>>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataMap);
try {
    DynamicJAXBContext jCtx = DynamicJAXBContextFactory.createContextFromOXM(xrdecl, properties);
    oxProject = jCtx.getXMLContext().getSession(0).getProject();
 
} catch (JAXBException e) {
    throw new DBWSException(OXM_PROCESSING_EX, e);
}

Note that the existing unmarshal code in XRServiceFactory.buildSessions should be removed and the above code (or similar) should be used.

Back to the top