Updates for in memory DB and links
diff --git a/JPA-RS Incubator/JPA-RS/.settings/org.eclipse.jdt.core.prefs b/JPA-RS Incubator/JPA-RS/.settings/org.eclipse.jdt.core.prefs
deleted file mode 100644
index c83400b..0000000
--- a/JPA-RS Incubator/JPA-RS/.settings/org.eclipse.jdt.core.prefs
+++ /dev/null
@@ -1,8 +0,0 @@
-#Fri Nov 04 08:55:45 EDT 2011

-eclipse.preferences.version=1

-org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled

-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6

-org.eclipse.jdt.core.compiler.compliance=1.6

-org.eclipse.jdt.core.compiler.problem.assertIdentifier=error

-org.eclipse.jdt.core.compiler.problem.enumIdentifier=error

-org.eclipse.jdt.core.compiler.source=1.6

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
index 1ad7e46..d9347c5 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/PersistenceContext.java
@@ -175,9 +175,9 @@
             if (isList(type)){

                 mergedEntity = newEntity(type);

                 List<Object> returnValues = new ArrayList<Object>();

-                mergedEntity.set("serializedData", returnValues);

+                mergedEntity.set("list", returnValues);

                 @SuppressWarnings("unchecked")

-                List<Object> values = (List<Object>)entity.get("serializedData");

+                List<Object> values = (List<Object>)entity.get("list");

                 for (Object value: values){

                     Object merged = em.merge(value);

                     returnValues.add(merged);

@@ -271,10 +271,14 @@
     }

 

     public DynamicEntity find(String tenantId, String entityName, Object id) {

+        return find(tenantId, entityName, id, null);

+    }

+    

+    public DynamicEntity find(String tenantId, String entityName, Object id, Map<String, Object> properties) {

         EntityManager em = getEmf().createEntityManager();

 

         try {

-            return (DynamicEntity) em.find(getClass(entityName), id);

+            return (DynamicEntity) em.find(getClass(entityName), id, properties);

         } finally {

             em.close();

         }

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java
index 249538d..a1d3fa2 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/Service.java
@@ -43,7 +43,6 @@
 import javax.ws.rs.core.Response.Status;

 import javax.ws.rs.core.StreamingOutput;

 import javax.ws.rs.core.UriInfo;

-import javax.xml.bind.JAXBContext;

 import javax.xml.bind.JAXBElement;

 import javax.xml.bind.JAXBException;

 import javax.xml.bind.Unmarshaller;

@@ -53,6 +52,7 @@
 import org.eclipse.persistence.dynamic.DynamicEntity;

 import org.eclipse.persistence.jpa.rs.metadata.DatabaseMetadataStore;

 import org.eclipse.persistence.jpa.rs.util.IdHelper;

+import org.eclipse.persistence.jpa.rs.util.LinkAdapter;

 import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;

 

 import com.sun.jersey.core.spi.factory.ResponseBuilderImpl;

@@ -140,7 +140,7 @@
             rb.status(Status.NOT_FOUND);

         } else {

             rb.status(Status.OK);

-            rb.entity(new StreamingOutputMarshaller(app.getJAXBContext(), entity, hh.getAcceptableMediaTypes()));

+            rb.entity(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes()));

         }

         return rb.build();

     }

@@ -155,7 +155,7 @@
 

         ResponseBuilder rb = new ResponseBuilderImpl();

         rb.status(Status.OK);

-        rb.entity(new StreamingOutputMarshaller(app.getJAXBContext(), entity, hh.getAcceptableMediaTypes()));

+        rb.entity(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes()));

         return rb.build();

     }

 

@@ -165,12 +165,10 @@
         PersistenceContext app = get(persistenceUnit);

         String tenantId = getTenantId(hh);

         MediaType contentType = mediaType(hh.getRequestHeader(HttpHeaders.CONTENT_TYPE)); 

-

         DynamicEntity entity = unmarshalEntity(app, type, tenantId, contentType, in);

         entity = app.merge(type, tenantId, entity);

 

-        JAXBContext context = app.getJAXBContext();

-        return new StreamingOutputMarshaller(context, entity, hh.getAcceptableMediaTypes());

+        return new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes());

     }

 

     @GET

@@ -178,8 +176,7 @@
     public StreamingOutput namedQuery(@PathParam("context") String persistenceUnit, @PathParam("name") String name, @Context HttpHeaders hh, @Context UriInfo ui) {

         PersistenceContext app = get(persistenceUnit);

         Object result = app.query(name, Service.getParameterMap(ui), false);

-        JAXBContext context = app.getJAXBContext();

-        return new StreamingOutputMarshaller(context, result, hh.getAcceptableMediaTypes());

+        return new StreamingOutputMarshaller(app, result, hh.getAcceptableMediaTypes());

     }

     

     @GET

@@ -188,8 +185,7 @@
     public StreamingOutput namedQuerySingleResult(@PathParam("context") String persistenceUnit, @PathParam("name") String name, @Context HttpHeaders hh, @Context UriInfo ui) {

         PersistenceContext app = get(persistenceUnit);

         Object result = app.query(name, Service.getParameterMap(ui), true);

-        JAXBContext context = app.getJAXBContext();

-        return new StreamingOutputMarshaller(context, result, hh.getAcceptableMediaTypes());

+        return new StreamingOutputMarshaller(app, result, hh.getAcceptableMediaTypes());

     }

 

     /**

@@ -240,6 +236,7 @@
         try {

             unmarshaller = app.getJAXBContext().createUnmarshaller();

             unmarshaller.setProperty(MEDIA_TYPE, acceptedMedia.toString());

+            unmarshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", app));

             JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), app.getClass(type));

             return (DynamicEntity) element.getValue();

         } catch (JAXBException e) {

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/qcn/JPARSDatabaseChangeListener.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/qcn/JPARSDatabaseChangeListener.java
index 089682b..72ef625 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/qcn/JPARSDatabaseChangeListener.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/qcn/JPARSDatabaseChangeListener.java
@@ -70,7 +70,7 @@
                                 ExpressionBuilder builder = new ExpressionBuilder();

                                 Expression expression = builder.getField(OracleChangeNotificationListener.ROWID).equal(rowChange.getRowid());

                                 ReadObjectQuery query = new ReadObjectQuery(descriptor.getJavaClass(), expression);

-

+                                query.refreshIdentityMapResult();

                                 updatedObject = session.executeQuery(query);

                            } else {

                                updatedObject = key.getObject();

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/CustomSerializationMetadataSource.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/CustomSerializationMetadataSource.java
index a2453ee..79cb3af 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/CustomSerializationMetadataSource.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/CustomSerializationMetadataSource.java
@@ -20,7 +20,6 @@
 import org.eclipse.persistence.jaxb.xmlmodel.ObjectFactory;

 import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;

 import org.eclipse.persistence.jaxb.xmlmodel.XmlElement;

-import org.eclipse.persistence.jaxb.xmlmodel.XmlElements;

 import org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes;

 import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes;

 import org.eclipse.persistence.sessions.server.Server;

@@ -50,27 +49,34 @@
         JavaTypes javaTypes = new JavaTypes();

         xmlBindings.setJavaTypes(javaTypes);

   

-        addSerializationType(persistenceUnitName, session, objectFactory, javaTypes);

+        addSerializationTypes(persistenceUnitName, session, objectFactory, javaTypes);

     }

     

-    private void addSerializationType(String persistenceUnitName, Server session, ObjectFactory objectFactory, JavaTypes javaTypes){

-        JavaType serializationType = new JavaType();

-        serializationType.setName(persistenceUnitName + "SerializedData");

-        serializationType.setJavaAttributes(new JavaAttributes());

-        

-        XmlElements xmlElements = new XmlElements(); 

-        xmlElements.setJavaAttribute("serializedData");

-        

-        xmlElements.setContainerType("java.util.List");

+    private void addSerializationTypes(String persistenceUnitName, Server session, ObjectFactory objectFactory, JavaTypes javaTypes){

+

         for (ClassDescriptor ormDescriptor : session.getProject().getOrderedDescriptors()) {

-            XmlElement childElement = new XmlElement(); 

-            childElement.setType(ormDescriptor.getJavaClassName());

-            childElement.setName(ormDescriptor.getAlias());

-            xmlElements.getXmlElement().add(childElement);

-        }

-        serializationType.getJavaAttributes().getJavaAttribute().add(objectFactory.createXmlElements(xmlElements));

-        serializationType.setXmlRootElement(new org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement());

-        javaTypes.getJavaType().add(serializationType);

+        

+            JavaType serializationType = new JavaType();

+            serializationType.setName(ormDescriptor.getAlias() + "ListWrapper");

+            serializationType.setJavaAttributes(new JavaAttributes());

+        

+            XmlElement xmlElement = new XmlElement(); 

+            xmlElement.setJavaAttribute("list");

+        

+            xmlElement.setContainerType("java.util.List");

+

+            xmlElement.setType(ormDescriptor.getJavaClassName());

+

+            serializationType.getJavaAttributes().getJavaAttribute().add(objectFactory.createXmlElement(xmlElement));

+            

+           // serializationType.getJavaAttributes().getJavaAttribute().add(DynamicXMLMetadataSource.createSelfProperty(ormDescriptor.getAlias() + "ListWrapper", objectFactory));

+            

+            org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement root = new org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement();

+            root.setName(ormDescriptor.getAlias() + "ListWrapper");

+

+            serializationType.setXmlRootElement(root);

+            javaTypes.getJavaType().add(serializationType);

+        }        

     }

     

     @Override

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/DynamicXMLMetadataSource.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/DynamicXMLMetadataSource.java
index 9e14af0..c141294 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/DynamicXMLMetadataSource.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/DynamicXMLMetadataSource.java
@@ -23,7 +23,10 @@
 import org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes;

 import org.eclipse.persistence.jaxb.xmlmodel.ObjectFactory;

 import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;

+import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter;

+import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema;

 import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes;

+import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema.XmlNs;

 import org.eclipse.persistence.jaxb.xmlmodel.XmlElement;

 import org.eclipse.persistence.jpa.rs.PersistenceFactory;

 import org.eclipse.persistence.mappings.CollectionMapping;

@@ -40,6 +43,10 @@
  */

 public class DynamicXMLMetadataSource implements MetadataSource {

 

+    private static final String LINK_NAMESPACE_URI = "http://www.w3.org/2005/Atom";

+    private static final String LINK_PREFIX = "atom";

+    private static final String LINK_LOCAL_NAME = "link";

+    

     private XmlBindings xmlBindings;

 

     public DynamicXMLMetadataSource(String persistenceUnitName, Server session, String packageName) {

@@ -49,7 +56,14 @@
 

         JavaTypes javaTypes = new JavaTypes();

         xmlBindings.setJavaTypes(javaTypes);

-  

+

+        XmlSchema xmlSchema = new XmlSchema();

+        XmlNs atomNs = new XmlNs();

+        atomNs.setPrefix(LINK_PREFIX);

+        atomNs.setNamespaceUri(LINK_NAMESPACE_URI);

+        xmlSchema.getXmlNs().add(atomNs);

+        xmlBindings.setXmlSchema(xmlSchema);

+        

         for (ClassDescriptor ormDescriptor : session.getProject().getOrderedDescriptors()) {

             javaTypes.getJavaType().add(createJAXBType(ormDescriptor, objectFactory));

         }

@@ -62,6 +76,7 @@
         for (DatabaseMapping ormMapping : classDescriptor.getMappings()) {

             javaType.getJavaAttributes().getJavaAttribute().add(createJAXBProperty(ormMapping, objectFactory));

         }

+    //    javaType.getJavaAttributes().getJavaAttribute().add(createSelfProperty(classDescriptor.getJavaClassName(), objectFactory));

         // Make them all root elements for now

         javaType.setXmlRootElement(new org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement());

 

@@ -73,14 +88,38 @@
         xmlElement.setJavaAttribute(mapping.getAttributeName());

         if (mapping.isObjectReferenceMapping()){

             xmlElement.setType(((ObjectReferenceMapping)mapping).getReferenceClassName());

+            if (!mapping.isPrivateOwned()){

+                addXmlAdapter(xmlElement);

+            }

         } else if (mapping.isCollectionMapping()){

             xmlElement.setType(((CollectionMapping)mapping).getReferenceClassName());

+            if (!mapping.isPrivateOwned()){

+                addXmlAdapter(xmlElement);

+            }

         } else {

             xmlElement.setType(mapping.getAttributeClassification().getName());

         }

         return objectFactory.createXmlElement(xmlElement);

     }

 

+    public static JAXBElement<XmlElement> createSelfProperty(String ownerClassName, ObjectFactory objectFactory){

+        XmlElement xmlElement = new XmlElement();

+        xmlElement.setJavaAttribute("self");

+        xmlElement.setType(ownerClassName);

+        addXmlAdapter(xmlElement);

+        return objectFactory.createXmlElement(xmlElement);

+    }

+    

+    public static void addXmlAdapter(XmlElement xmlElement) {

+        xmlElement.setXmlPath(LINK_PREFIX + ":" + LINK_LOCAL_NAME + "[@rel='" + xmlElement.getJavaAttribute() + "']/@href");

+

+        XmlJavaTypeAdapter adapter = new XmlJavaTypeAdapter();

+        adapter.setValue(LinkAdapter.class.getName());

+        adapter.setValueType(String.class.getName());

+        adapter.setType(xmlElement.getType());

+        xmlElement.setXmlJavaTypeAdapter(adapter);

+    }

+    

     @Override

     public XmlBindings getXmlBindings(Map<String, ?> properties, ClassLoader classLoader) {

         return this.xmlBindings;

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java
new file mode 100644
index 0000000..80dac13
--- /dev/null
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/LinkAdapter.java
@@ -0,0 +1,99 @@
+/*******************************************************************************

+ * Copyright (c) 2011 Oracle. All rights reserved.

+ * This program and the accompanying materials are made available under the 

+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 

+ * which accompanies this distribution. 

+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html

+ * and the Eclipse Distribution License is available at 

+ * http://www.eclipse.org/org/documents/edl-v10.php.

+ *

+ * Contributors:

+ *      bdoughan - initial implementation 

+ *      tware - initial unmarshall method

+ ******************************************************************************/

+package org.eclipse.persistence.jpa.rs.util;

+

+import java.util.HashMap;

+import java.util.Iterator;

+import java.util.Map;

+

+import javax.xml.bind.annotation.adapters.XmlAdapter;

+

+import org.eclipse.persistence.config.CacheUsage;

+import org.eclipse.persistence.config.QueryHints;

+import org.eclipse.persistence.descriptors.ClassDescriptor;

+import org.eclipse.persistence.dynamic.DynamicEntity;

+import org.eclipse.persistence.internal.dynamic.DynamicEntityImpl;

+import org.eclipse.persistence.internal.helper.ConversionManager;

+import org.eclipse.persistence.internal.queries.EntityFetchGroup;

+import org.eclipse.persistence.jpa.JpaHelper;

+import org.eclipse.persistence.jpa.rs.PersistenceContext;

+import org.eclipse.persistence.mappings.DatabaseMapping;

+import org.eclipse.persistence.queries.FetchGroup;

+

+public class LinkAdapter extends XmlAdapter<String, Object> {

+

+    private String baseURI = "http://example.com/DEFAULT/";

+    protected PersistenceContext context;

+

+    public LinkAdapter() {

+    }

+

+    public LinkAdapter(String baseURI, PersistenceContext context) {

+        this.baseURI = baseURI;

+        this.context = context;

+    }

+

+    @Override

+    @SuppressWarnings("rawtypes")

+    // TODO Composite keys

+    public Object unmarshal(String v) throws Exception {  

+        int lastSlash = v.lastIndexOf('/');

+        String entityType = v.substring(baseURI.length(), lastSlash);

+        String entityId = v.substring(lastSlash + 1);

+        ClassDescriptor descriptor = context.getDescriptor(entityType);

+        Iterator<DatabaseMapping> i = descriptor.getMappings().iterator();

+        String idField = null;

+        Class idType = null;

+        while (i.hasNext()){

+            DatabaseMapping mapping = i.next();

+            if (mapping.isPrimaryKeyMapping()){

+                idField = mapping.getAttributeName();

+                idType = mapping.getAttributeClassification();

+                break;

+            }

+        }

+        Object id = ConversionManager.getDefaultManager().convertObject(entityId, idType);

+        return constructObjectForId(entityType, idField, id);

+    }

+

+    protected Object constructObjectForId(String entityType, String entityIdField, Object id){

+        FetchGroup fetchGroup = new FetchGroup();

+        fetchGroup.addAttribute(entityIdField);

+        Map<String, Object> properties = new HashMap<String, Object>();

+        properties.put(QueryHints.FETCH_GROUP, fetchGroup);

+        properties.put(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheOnly);

+        DynamicEntityImpl entity = (DynamicEntityImpl)context.find(null, entityType, id, properties);

+        if (entity == null){

+            entity = (DynamicEntityImpl)context.newEntity(entityType);

+            entity.set(entityIdField, id);

+            EntityFetchGroup group = new EntityFetchGroup(entityIdField);

+            entity._persistence_setFetchGroup(group);

+            entity._persistence_setId(id);

+            entity._persistence_setSession(JpaHelper.getDatabaseSession(context.getEmf()));

+        }

+        return entity;

+    }

+    

+    @Override

+    public String marshal(Object v) throws Exception {

+        if (null == v) {

+            return null;

+        }

+        DynamicEntity de = (DynamicEntity) v;

+        String href = baseURI + v.getClass().getSimpleName() + "/"

+                + de.get("id");

+        return href;

+    }

+

+}
\ No newline at end of file
diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
index f332f6c..dfd5fee 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/util/StreamingOutputMarshaller.java
@@ -20,6 +20,7 @@
 import java.io.ObjectOutputStream;

 import java.io.OutputStream;

 import java.io.OutputStreamWriter;

+import java.io.StringWriter;

 import java.util.Collection;

 import java.util.Iterator;

 import java.util.List;

@@ -31,6 +32,8 @@
 import javax.xml.bind.JAXBException;

 import javax.xml.bind.Marshaller;

 

+import org.eclipse.persistence.jpa.rs.PersistenceContext;

+

 /**

  * Simple {@link StreamingOutput} implementation that uses the provided

  * {@link JAXBContext} to marshal the result when requested to either XML or

@@ -40,28 +43,29 @@
  * @since EclipseLink 2.4.0

  */

 public class StreamingOutputMarshaller implements StreamingOutput {

-    private JAXBContext jaxbContext;

+    private PersistenceContext context;

     private Object result;

     private MediaType mediaType;

 

     private static final String COLLECTION_ELEMENT_NAME = "collection";

 

-    public StreamingOutputMarshaller(JAXBContext jaxbContext, Object result, MediaType acceptedType) {

-        this.jaxbContext = jaxbContext;

+    public StreamingOutputMarshaller(PersistenceContext context, Object result, MediaType acceptedType) {

+        this.context = context;

         this.result = result;

         this.mediaType = acceptedType;

     }

 

-    public StreamingOutputMarshaller(JAXBContext jaxbContext, Object result, List<MediaType> acceptedTypes) {

-        this(jaxbContext, result, mediaType(acceptedTypes));

+    public StreamingOutputMarshaller(PersistenceContext context, Object result, List<MediaType> acceptedTypes) {

+        this(context, result, mediaType(acceptedTypes));

     }

 

     public void write(OutputStream output) throws IOException, WebApplicationException {

-        if (this.jaxbContext != null && this.result != null && !this.mediaType.equals(MediaType.WILDCARD_TYPE)) {

+        if (this.context.getJAXBContext() != null && this.result != null && !this.mediaType.equals(MediaType.WILDCARD_TYPE)) {

             try {

-                Marshaller marshaller = jaxbContext.createMarshaller();

+                Marshaller marshaller = this.context.getJAXBContext().createMarshaller();

                 marshaller.setProperty(MEDIA_TYPE, this.mediaType.toString());

                 marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBContext.INCLUDE_ROOT, false);

+                marshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", context));

                 if (result instanceof Collection) {

                     @SuppressWarnings("unchecked")

                     Collection<Object> objs = (Collection<Object>) result;

diff --git a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java
index f92b53d..214f562 100644
--- a/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java
+++ b/JPA-RS Incubator/JPA-RS/src/org/eclipse/persistence/jpa/rs/websockets/JPARSWebSocket.java
@@ -24,6 +24,7 @@
 import org.eclipse.persistence.internal.helper.Helper;

 

 import org.eclipse.persistence.jpa.rs.PersistenceContext;

+import org.eclipse.persistence.jpa.rs.util.LinkAdapter;

 

 import com.sun.grizzly.websockets.DataFrame;

 import com.sun.grizzly.websockets.DefaultWebSocket;

@@ -100,8 +101,10 @@
 			Marshaller marshaller = jaxbContext.createMarshaller();

 			marshaller.setProperty(MEDIA_TYPE, MediaType.APPLICATION_JSON);

 			marshaller.setProperty(org.eclipse.persistence.jaxb.JAXBContext.INCLUDE_ROOT, false);

+            marshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", context));

 			StringWriter stringWriter = new StringWriter();

 			marshaller.marshal(entity, stringWriter);

+

 			String jsonString = stringWriter.toString();

 			return jsonString;

 		} catch (Exception e) {

diff --git a/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/bootstrap/TestBootstrap.java b/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/bootstrap/TestBootstrap.java
index 580c84d..214cc08 100644
--- a/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/bootstrap/TestBootstrap.java
+++ b/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/bootstrap/TestBootstrap.java
@@ -62,6 +62,9 @@
         assertTrue("JAXB Session did not contain Auction.", session.getProject().getAliasDescriptors().containsKey("Auction"));

         assertTrue("JAXB Session did not contain Bid.", session.getProject().getAliasDescriptors().containsKey("Bid"));

         assertTrue("JAXB Session did not contain User.", session.getProject().getAliasDescriptors().containsKey("User"));

+        assertTrue("JAXB Session did not contain Auction.", session.getProject().getAliasDescriptors().containsKey("AuctionListWrapper"));

+        assertTrue("JAXB Session did not contain Bid.", session.getProject().getAliasDescriptors().containsKey("BidListWrapper"));

+        assertTrue("JAXB Session did not contain User.", session.getProject().getAliasDescriptors().containsKey("UserListWrapper"));

 	

 	}

 

diff --git a/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java b/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java
index 9536195..c786f0d 100644
--- a/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java
+++ b/JPA-RS Incubator/tests/JPA-RS Tests/src/jpars/test/service/TestService.java
@@ -34,6 +34,7 @@
 import javax.ws.rs.core.Response.Status;

 import javax.xml.bind.JAXBElement;

 import javax.xml.bind.JAXBException;

+import javax.xml.bind.Marshaller;

 import javax.xml.bind.Unmarshaller;

 import javax.xml.transform.stream.StreamSource;

 

@@ -44,13 +45,19 @@
 import org.eclipse.persistence.dynamic.DynamicEntity;

 import org.eclipse.persistence.jaxb.JAXBContext;

 import org.eclipse.persistence.jaxb.JAXBMarshaller;

+import org.eclipse.persistence.jpa.JpaHelper;

 import org.eclipse.persistence.jpa.rs.PersistenceContext;

 import org.eclipse.persistence.jpa.rs.PersistenceFactory;

 import org.eclipse.persistence.jpa.rs.Service;

 import org.eclipse.persistence.jpa.rs.metadata.DatabaseMetadataStore;

+import org.eclipse.persistence.jpa.rs.util.LinkAdapter;

+import org.eclipse.persistence.sessions.server.ServerSession;

 import org.junit.AfterClass;

 import org.junit.BeforeClass;

 import org.junit.Test;

+

+import com.sun.xml.bind.marshaller.MarshallerImpl;

+

 import static org.junit.Assert.*;

 

 /**

@@ -73,6 +80,8 @@
             factory.getMetadataStore().setProperties(properties);

             factory.getMetadataStore().clearMetadata();

             factory.bootstrapPersistenceContext("auction", new URL("file:///C:/EclipseLinkView2/incubator/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-persistence.xml"), properties, true);

+            factory.bootstrapPersistenceContext("phonebook", new URL("file:///C:/EclipseLinkView2/incubator/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-persistence.xml"), properties, true);

+

             clearData();

         } catch (Exception e){

             fail(e.toString());

@@ -91,11 +100,16 @@
         em.createQuery("delete from Bid b").executeUpdate();

         em.createQuery("delete from Auction a").executeUpdate();

         em.createQuery("delete from User u").executeUpdate();

+

+        em.getTransaction().commit();

+        em = factory.getPersistenceContext("phonebook").getEmf().createEntityManager();

+        em.getTransaction().begin();

+        em.createQuery("delete from Person p").executeUpdate();

         em.getTransaction().commit();

     }

     

     @Test

-    public void testUpdateList(){

+    public void testUpdateUserList(){

         Service service = new Service();

         service.setPersistenceFactory(factory);

         PersistenceContext context = factory.getPersistenceContext("auction");

@@ -112,20 +126,13 @@
         

         entity2.set("name", "Gillian");    

         

-        DynamicEntity entity3 = context.newEntity("Auction");

-        entity3.set("name", "Computer");

-        context.create(null, entity3);

-        

-        entity3.set("name", "Tablet");

-        

-        DynamicEntity serializedData = context.newEntity("auctionSerializedData");

+        DynamicEntity serializedData = context.newEntity("UserListWrapper");

         List<DynamicEntity> entities = new ArrayList<DynamicEntity>();

         entities.add(entity);

         entities.add(entity2);

-        entities.add(entity3);

-        serializedData.set("serializedData", entities);

+        serializedData.set("list", entities);

 

-        StreamingOutput output = service.update("auction", "auctionSerializedData", generateHTTPHeader(MediaType.APPLICATION_XML_TYPE, MediaType.APPLICATION_XML), serializeToSteam(serializedData, context, MediaType.APPLICATION_XML));

+        StreamingOutput output = service.update("auction", "UserListWrapper", generateHTTPHeader(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON), serializeToSteam(serializedData, context, MediaType.APPLICATION_JSON));

 

         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

         try{

@@ -134,18 +141,17 @@
             fail(ex.toString());

         }

         InputStream stream = new ByteArrayInputStream(outputStream.toByteArray());

-        serializedData = unmarshalEntity(context, "auctionSerializedData", null, MediaType.APPLICATION_XML, stream);

+        serializedData = unmarshalEntity(context, "UserListWrapper", null, MediaType.APPLICATION_JSON, stream);

         

         assertNotNull("returned data was null", serializedData);

-        entities = serializedData.get("serializedData");

+        entities = serializedData.get("list");

         assertNotNull("returned data had null list", entities);

-        assertTrue("returned data had wrong list size", entities.size() == 3);

+        assertTrue("returned data had wrong list size", entities.size() == 2);

         List<String> values = new ArrayList<String>();

         values.add("James");

         values.add("Gillian");

-        values.add("Tablet");

         for (DynamicEntity value: entities){

-            assertTrue("Incorrect name returned", value.get("name").equals("Tablet") || value.get("name").equals("James") || value.get("name").equals("Gillian"));

+            assertTrue("Incorrect name returned", value.get("name").equals("James") || value.get("name").equals("Gillian"));

             values.remove(value.get("name"));

         }

         assertTrue("Incorrent set of names.", values.isEmpty());

@@ -154,6 +160,60 @@
     }

     

     @Test

+    public void testUpdatePhoneNumberList(){

+        Service service = new Service();

+        service.setPersistenceFactory(factory);

+        PersistenceContext context = factory.getPersistenceContext("phonebook");

+        

+        DynamicEntity entity = context.newEntity("Person");

+        entity.set("firstName", "Jim");

+        entity.set("lastName", "Jones");

+        entity.set("phoneNumber", "1234567");

+        context.create(null, entity);

+        

+        entity.set("firstName", "James");

+        

+        DynamicEntity entity2 = context.newEntity("Person");

+        entity2.set("firstName", "Jill");

+        entity2.set("lastName", "Jones");

+        context.create(null, entity2);

+        

+        entity2.set("firstName", "Gillian");    

+        

+        DynamicEntity serializedData = context.newEntity("PersonListWrapper");

+        List<DynamicEntity> entities = new ArrayList<DynamicEntity>();

+        entities.add(entity);

+        entities.add(entity2);

+        serializedData.set("list", entities);

+

+        StreamingOutput output = service.update("phonebook", "PersonListWrapper", generateHTTPHeader(MediaType.APPLICATION_JSON_TYPE, MediaType.APPLICATION_JSON), serializeToSteam(serializedData, context, MediaType.APPLICATION_JSON));

+

+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

+        try{

+            output.write(outputStream);

+        } catch (IOException ex){

+            fail(ex.toString());

+        }

+        InputStream stream = new ByteArrayInputStream(outputStream.toByteArray());

+        serializedData = unmarshalEntity(context, "PersonListWrapper", null, MediaType.APPLICATION_JSON, stream);

+        

+        assertNotNull("returned data was null", serializedData);

+        entities = serializedData.get("list");

+        assertNotNull("returned data had null list", entities);

+        assertTrue("returned data had wrong list size", entities.size() == 2);

+        List<String> values = new ArrayList<String>();

+        values.add("James");

+        values.add("Gillian");

+        for (DynamicEntity value: entities){

+            assertTrue("Incorrect firstName returned", value.get("firstName").equals("James") || value.get("firstName").equals("Gillian"));

+            values.remove(value.get("firstName"));

+        }

+        assertTrue("Incorrent set of names.", values.isEmpty());

+        

+        clearData();

+    }

+    

+    @Test

     public void testRestart(){

         factory.close();

         Map<String, Object> properties = new HashMap<String, Object>();

@@ -170,6 +230,42 @@
         assertTrue("factory was not recreated at boot time.", factory.getPersistenceContext("auction") != null);

     }

     

+    @Test 

+    public void testMarshallBid(){

+        Service service = new Service();

+        service.setPersistenceFactory(factory);

+        PersistenceContext context = factory.getPersistenceContext("auction");

+        

+        DynamicEntity entity1 = context.newEntity("Auction");

+        entity1.set("name", "Computer");

+        context.create(null, entity1);

+        

+        DynamicEntity entity2 = context.newEntity("User");

+        entity2.set("name", "Bob");

+        context.create(null, entity2);

+        

+        DynamicEntity entity3 = context.newEntity("Bid");

+        entity3.set("bid", 200d);

+        entity3.set("user", entity2);

+        entity3.set("auction", entity1);

+        context.create(null, entity3);

+        

+        InputStream stream = serializeToSteam(entity3, context, MediaType.APPLICATION_JSON);

+        

+        entity3 = unmarshalEntity(context, "Bid", null, MediaType.APPLICATION_JSON, stream);

+        

+        System.out.println(entity3);

+        entity2 = entity3.get("auction");

+

+        assertNotNull("Name of auction is null.", entity2.get("name"));

+        assertTrue("Name of auction is incorrect.", entity2.get("name").equals("Computer"));

+        

+        entity1 = entity3.get("user");

+        

+        assertNotNull("Name of user is null.", entity1.get("name"));

+        assertTrue("Name of user is incorrect.", entity1.get("name").equals("Bob"));

+    }

+    

     @Test

     public void testNamedQuery(){

         Service service = new Service();

@@ -261,6 +357,7 @@
         try {

             unmarshaller = app.getJAXBContext().createUnmarshaller();

             unmarshaller.setProperty(MEDIA_TYPE, acceptedMedia);

+            unmarshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", app));

             JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), app.getClass(type));

             return (DynamicEntity) element.getValue();

         } catch (JAXBException e) {

@@ -283,7 +380,15 @@
         JAXBMarshaller marshaller = null;

         try{

             marshaller = (JAXBMarshaller)context.getJAXBContext().createMarshaller();

+          /*  marshaller.setListener(new Marshaller.Listener() {

+                    @Override

+                    public void beforeMarshal(Object source) {

+                        ((DynamicEntity)source).set("self", source);

+                    }

+                }

+            );*/

             marshaller.setProperty("eclipselink.media-type", mediaType);

+            marshaller.setAdapter(new LinkAdapter("http://localhost:8080/JPA-RS/auction/entity/", context));

             marshaller.setProperty(JAXBContext.INCLUDE_ROOT, Boolean.FALSE);

             marshaller.marshal(object, writer);

         } catch (Exception e){

diff --git a/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-orm.xml b/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-orm.xml
index 358505e..1390bc5 100644
--- a/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-orm.xml
+++ b/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/auction-orm.xml
@@ -9,6 +9,10 @@
         <query>SELECT a FROM Auction a</query>

     </named-query>

     

+    <named-query name="Auction.forName">

+        <query>SELECT a FROM Auction a WHERE a.name = :name</query>

+    </named-query>

+    

     <named-query name="Auction.open">

         <query>SELECT a FROM Auction a where a.sold = false</query>

     </named-query>

@@ -77,9 +81,11 @@
             <basic name="time" attribute-type="Long"/>        

             <one-to-one name="user" fetch="EAGER" target-entity="User">

                 <join-column name="USER_ID" />

+                <private-owned/>

             </one-to-one>

             <one-to-one name="auction" fetch="EAGER" target-entity="Auction">

                 <join-column name="AUCTION_ID" />

+                <private-owned/>

             </one-to-one>

         </attributes>

     </entity>

diff --git a/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-orm.xml b/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-orm.xml
new file mode 100644
index 0000000..37d4f73
--- /dev/null
+++ b/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-orm.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>

+<entity-mappings version="2.3"

+    xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/orm"

+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

+ 

+    <package>jpars.app.phonebook.model</package>

+  

+    <named-query name="Person.all">

+        <query>SELECT p FROM Person p</query>

+    </named-query>

+    

+    <named-query name="Person.likeName">

+        <query>SELECT p FROM Person p WHERE p.lastName LIKE :lastName</query>

+    </named-query>

+ 

+    <entity class="Person" access="VIRTUAL">

+        <table name="PHONEBOOK_PERSON" />

+        <attributes>

+            <id name="id" attribute-type="Integer">

+                <column name="ID" />

+                <generated-value/>

+            </id>

+            <basic name="firstName" attribute-type="String" />

+            <basic name="lastName" attribute-type="String" />

+            <basic name="phoneNumber" attribute-type="String" />

+        </attributes>

+    </entity>

+        

+</entity-mappings>
\ No newline at end of file
diff --git a/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-persistence.xml b/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-persistence.xml
new file mode 100644
index 0000000..75f433a
--- /dev/null
+++ b/JPA-RS Incubator/tests/JPA-RS Tests/src/xmldocs/phonebook-persistence.xml
@@ -0,0 +1,17 @@
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"

+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

+    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd"

+    version="2.0">

+    <persistence-unit name="phonebook" transaction-type="RESOURCE_LOCAL">

+

+        <provider>

+            org.eclipse.persistence.jpa.PersistenceProvider

+        </provider>

+        

+        <class>jpars.app.phonebook.model.Person</class>

+        <properties>

+            <property name="eclipselink.metadata-source" value="XML"/>

+            <property name="eclipselink.metadata-source.xml.file" value="xmldocs/phonebook-orm.xml"/>

+        </properties>

+    </persistence-unit>

+</persistence>
\ No newline at end of file