Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The content of a JEST response can be is either XML or JSON.String-based representation of

XML Representation

JEST represents persistent Java object graphs in either XML or more succinct JSON form has to address the critical issue of circular reference. Because a query can result
in to an object graph that contains cycles. JSON, at this point of writing, does not address circular reference. Hence JEST introduces special semantics within JSON format to refer to
instances in a serialized graph.

XML Representation

JEST represents persistent Java object graph in a schema-compliant XML.

Example of a serialized object graph

The example shows a Person (primary key p1) who is her own partner.

graph in a schema-compliant XML. The schema is metamodel-driven and hence invariant to particular domain model.
The schema jest-instance.xsd is as follows:

Code Block
xml
xml
titleMetamodel-driven schema for JEST XML

<!-- ========================================================================= -->
<!-- Schema for serialized persistence instance graph      
Code Block
xmlxml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<instances>
  <instance id="Person-p1">
    <basic name="id" type="String">p1</basic>
    <basic name="dob" type="Date">Fri Sep 08 00:00:00 CDT 1989</basic>
    <basic name="firstName" type="String">Mary</basic>
    <basic name="gender" type="Gender">Female</basic>

    <basic name="lastName" type="String">Smith</basic>
    <singular name="address" type="Address">
      <instance id="Address-101">
        <basic name="id" type="long">101</basic>
        <basic name="country" type="String">C1</basic>
        <basic name="state" type="String">State1</basic>
        <basic name="street" type="String">Street1</basic>

        <basic name="zip" type="int">10001</basic>
      </instance>
    </singular>
    <singular name="partner" type="Person">
      <ref id="Person-p1"/>
    </singular>
  </instance>
</instances>

The above XML document is compliant to a XML schema.
The jest-instance.xsd schema is as follows:

Code Block
xmlxml

<!--  -->
<!-- =========================================================================================================== -->
<!-- Schema for serialized persistence instance graph         -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	attributeFormDefault="unqualified" elementFormDefault="qualified"
	version="1.0">

	<xsd:annotation>
		<xsd:documentation><![CDATA[
         Describes closure of managed persistence instance.
         Each instance is described by all its loaded persistent -->
<!-- ========================================================================= -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	attributeFormDefault="unqualified" elementFormDefault="qualified"
	version="1.0">

	<xsd:annotation>
		<xsd:documentation><![CDATA[
         Describes closure of managed persistence instance.
   attribute.
         The related instances are resolved within the document root.
         Document root represents zero or more instances. 
      Each instance is described by all its loaded persistent attribute.
         The relatedfile instancesmust arebe resolved within the document rootnamed "jest-instance.xsd".
         Document root represents zero or more instances. 
          
         The file must be named "jest-instance.xsd".
]]>
		</xsd:documentation>
	</xsd:annotation>

    <!-- The root element of the document contains zero or more instances -->
	<xsd:element name="instances">
		<xsd:complexType>
			<xsd:sequence>
			    <xsd:element name="uri"         ]]>
		</xsd:documentation>
	</xsd:annotation>

    <!-- The root element of the document contains zero or more instances -->
	minOccurs="1" maxOccurs="1" type="xsd:anyURI"/>
			    <xsd:element name="description"instances">
		<xsd:complexType> minOccurs="0" maxOccurs="1" type="xsd:string"/>
			<xsd:sequence>
				<xsd:element name="instance"    minOccurs="0" maxOccurs="unbounded" type="instance-type" />
			</xsd:sequence>
			<xsd:attribute name="version" type="xsd:string" />
		</xsd:complexType>
	</xsd:element>

	<!-- The root element for a single instance. Children of this element are persistent attribute -->
	<xsd:complexType name="instance-type">
		<xsd:sequence>
			<xsd:element name="basic" type="basic-attr-type"  minOccurs="0" maxOccurs="unbounded" />
			<xsd:element name="lob" type="lob-attr-type"      minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="embedded" type="instance-type" minOccurs="0" maxOccurs="unbounded" />
			<xsd:element name="singular" type="singular-attr-type"  	minOccurs="0" maxOccurs="unbounded" />
			<xsd:element name="collection" type="collection-attr-type"	minOccurs="0" maxOccurs="unbounded" />
			<xsd:element name="map" type="map-attr-type"<!-- Persistent Attributes occur in order. The order is determined by the attribute category.  -->
	<!-- Attribute category is determined by the enumerated PersistentAttributeType defined in     -->
	<!-- javax.persistence.metamodel and then further refined by id, version, lob and enum.        -->
	<!-- See org.apache.openjpa.persistence.jest.MetamodelHelper for further details.                minOccurs="0" maxOccurs="unbounded" /-->
	<xsd:complexType name="instance-type">
		</xsd<xsd:sequence>
			<xsd:attributeelement name="id"           type="xsd:ID" use="required" basic-attr-type"      minOccurs="0" maxOccurs="unbounded"/>
	</xsd:complexType>

	<!-- A reference to another instance within the same(?) document -->
	<xsd:complexType name="ref-type">
		<xsd:attribute name="id" type="xsd:IDREF" />
	</xsd:complexType>
	
	<!-- A null reference   		<xsd:element name="version"      type="basic-attr-type"      minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="basic"        type="basic-attr-type"           minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="enum"         type="basic-attr-type"      minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="embedded"     type="instance-type"        --minOccurs="0" maxOccurs="unbounded"/>
			<xsd:complexTypeelement name="ref-null">
	</xsd:complexType>

	<!-- Basic Attribute has a name and its runtime type   -->
	<!-- non-null value appears as text content.           -->
	<!-- null value appears as attribute with empty text . -->
	<xsd:complexType name="basic-attr-type">
		<xsd:simpleContent>
			<xsd:extension base="xsd:string">
				<xsd:attribute name="name" type="xsd:string" use="required" />
				<xsd:attribute name="type" type="xsd:string" use="required" />
				<xsd:attribute name="null" type="xsd:boolean" />
			</xsd:extension>
		</xsd:simpleContent>lob"          type="lob-attr-type"        minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="one-to-one"   type="singular-attr-type"   minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="many-to-one"  type="singular-attr-type"	 minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="element-collection" type="collection-attr-type" minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="one-to-many"  type="collection-attr-type" minOccurs="0" maxOccurs="unbounded"/>
			<xsd:element name="many-to-many" type="map-attr-type"        minOccurs="0" maxOccurs="unbounded"/>
		</xsd:sequence>
		<xsd:attribute name="id" type="xsd:ID" use="required" />
	</xsd:complexType>
	
	<!-- LargeA reference Binaryto Objectsanother (LOB)instance representedwithin as hex arraythe same(?) document -->
	<xsd:complexType name="lobref-attr-type">
		<xsd:simpleContent>
			<xsd:extension base="xsd:hexBinarystring">
				<xsd:attribute name="nameid" type="xsd:stringIDREF" use="required" />/>
				<xsd:attribute name="type" type="xsd:string" use="required" />
				<xsd:attribute name="null" type="xsd:boolean" /></xsd:extension>
			</xsd:extension>
		</xsd:simpleContent>
	</xsd:complexType>
	
	<!-- Singular attribute can be a reference or another instance. A null reference                                            -->
	<xsd:complexType name="singularref-attr-typenull">
		<xsd:choice>simpleContent>
			<xsd:elementextension namebase="null" type="ref-null" /xsd:string">
			<xsd:element name="ref" type="ref-type" /></xsd:extension>
			<xsd:element name="instance" type="instance-type" />
		</xsd:choice>
		<xsd:attribute name="name" type="xsd:string" use="required" />
		<xsd:attribute name="type" type="xsd:string" use="required" />
	</xsd:complexType>

	<!-- Collection attributes list their members with their runtime type -->
	<!-- Members can be basic or other managed instance                   -->
	<xsd:complexType name="collection-attr-type">
		<xsd:sequence>
			<xsd:element name="member" type="member-type" minOccurs="0"
				maxOccurs="unbounded</xsd:simpleContent>
	</xsd:complexType>

	<!-- Basic Attribute has a name and its runtime type   -->
	<!-- non-null value appears as text content.           -->
	<!-- null value appears as attribute with empty text . -->
	<xsd:complexType name="basic-attr-type">
		<xsd:simpleContent>
			<xsd:extension base="xsd:string">
				<xsd:attribute name="name" type="xsd:string" use="required" />
		</xsd:sequence>
		<xsd:attribute name="nametype" type="xsd:string" use="required" />
				<xsd:attribute name="typenull" type="xsd:string" use="requiredboolean" />
		<xsd:attribute name="member-type" type="xsd:string" use="required" />	</xsd:extension>
		</xsd:simpleContent>
	</xsd:complexType>
	
	<!-- MapLarge attributesBinary listObjects their(LOB) entriesrepresented withas runtime type of key and value    hex array -->
	<!-- Both key and value can be independently basic or other managed instance -->
	<xsd:complexType name="map-attr-type<xsd:complexType name="lob-attr-type">
		<xsd:simpleContent>
			<xsd:extension base="xsd:hexBinary">
		<xsd:sequence>
			<xsd:elementattribute name="entryname" type="entry-type" />
		</xsd:sequence>
		<xsd:attribute name="name" type="xsd:xsd:string" use="required" />
				<xsd:attribute name="type" type="xsd:string" use="required" />
				<xsd:attribute name="key-typenull" type="xsd:stringboolean" use="required" />
			<xsd:attribute name="value-type" type="xsd:string" use="required" /></xsd:extension>
		</xsd:simpleContent>
	</xsd:complexType>

	<!-- Singular Valueattribute ofis a member of basic typereference to another instance or a null reference. -->
	<xsd:complexType name="basicsingular-valueattr-type">
		<xsd:simpleContent>choice>
			<xsd:extensionelement basename="xsd:string"null" type="ref-null" />
				<xsd:attributeelement name="nullref" type="xsd:booleanref-type" />
			</xsd:extension>choice>
		</xsd:simpleContent>
	</xsd:complexType>

	<!-- Value of a member of a collection/map<xsd:attribute name="name" type="xsd:string" use="required" />
		<xsd:attribute name="type" type="xsd:string" use="required" />
	</xsd:complexType>

	<!-- Collection attributes list their members with their runtime type -->
	<xsd:complexType name="member<!-- Members can be basic or other managed instance                   -->
	<xsd:complexType name="collection-attr-type">
		<xsd:choice>sequence>
			<xsd:element name="basicmember" type="basic-valuemember-type" />
	minOccurs="0"
				maxOccurs="unbounded" />
		</xsd:sequence>
		<xsd:elementattribute name="instancename" type="instance-typexsd:string" use="required" />
			<xsd:elementattribute name="nulltype" type="ref-nullxsd:string" use="required" />
			<xsd:elementattribute name="refmember-type" type="ref-type"xsd:string" use="required" />
		</xsd:choice>
	</xsd:complexType>

	<!-- Denotes entry of a map element Map attributes list their entries with runtime type of key and value    -->
	<xsd:complexType name="entry<!-- Both key and value can be independently basic or other managed instance -->
	<xsd:complexType name="map-attr-type">
		<xsd:sequence>
			<xsd:element name="keyentry"   type="memberentry-type" minOccurs="1" maxOccurs="1" />
			</xsd:sequence>
		<xsd:elementattribute name="valuename" type="xsd:string" use="member-"required" />
		<xsd:attribute name="type" minOccurstype="1xsd:string" maxOccursuse="1required"  />
		</xsd:sequence>
	</xsd:complexType>
	
<xsd:attribute name="key-type" type="xsd:string" use="required" />
		<xsd:attribute name="value-type" type="xsd:string" use="required" />
	</xsd:schema>
complexType>

	<!-- Value of a member of basic type. -->
	<xsd:complexType name="basic-value-type">
		<xsd:simpleContent>
			<xsd:extension base="xsd:string">
				<xsd:attribute name="null" type="xsd:boolean" />
			</xsd:extension>
		</xsd:simpleContent>
	</xsd:complexType>

	<!-- Value of a member of a collection/map -->
	<xsd:complexType name="member-type">
		<xsd:choice>
			<xsd:element name="basic" type="basic-value-type" />
			<xsd:element name="null" type="ref-null" />
			<xsd:element name="ref" type="ref-type" />
		</xsd:choice>
	</xsd:complexType>

	<!-- Denotes entry of a map element -->
	<xsd:complexType name="entry-type">
		<xsd:sequence>
			<xsd:element name="key"   type="member-type" minOccurs="1" maxOccurs="1" />
			<xsd:element name="value" type="member-type" minOccurs="1" maxOccurs="1"  />
		</xsd:sequence>
	</xsd:complexType>
	
</xsd:schema>

Example of a serialized object graph

The example shows a Person (primary key p1) who is her own partner.

Code Block
xml
xml
titleExample of Object Graph with Circular Reference

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<instances>
  <instance id="Person-p1">
    <basic name="id" type="String">p1</basic>
    <basic name="dob" type="Date">Fri Sep 08 00:00:00 CDT 1989</basic>
    <basic name="firstName" type="String">Mary</basic>
    <basic name="gender" type="Gender">Female</basic>

    <basic name="lastName" type="String">Smith</basic>
    <singular name="address" type="Address">
      <instance id="Address-101">
        <basic name="id" type="long">101</basic>
        <basic name="country" type="String">C1</basic>
        <basic name="state" type="String">State1</basic>
        <basic name="street" type="String">Street1</basic>

        <basic name="zip" type="int">10001</basic>
      </instance>
    </singular>
    <singular name="partner" type="Person">
      <ref id="Person-p1"/>
    </singular>
  </instance>
</instances>

JSON Representation

String-based representation of persistent Java object graphs in either XML or more succinct JSON form has to address the critical issue of circular reference, because persistent object graphs
often contains circular reference. JSON, at this point of writing, does not address circular reference. Hence JEST introduces special semantics within JSON format to refer to
instances in a serialized graph. However, the enhanced JSON can be parsed by standard JSON parsers.

Enhanced JSON representation in JEST introduces two special fields named $id and $ref to address circular reference. Each JSON object carries a $id field whose value is the persistent identity of the corresponding entity. When JSON serialization encounters a circular reference a