cxf-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Dobes Vandermeer (JIRA)" <j...@apache.org>
Subject [jira] Updated: (CXF-3148) CXF converts collections to arrays during serialization
Date Tue, 23 Nov 2010 23:34:14 GMT

     [ https://issues.apache.org/jira/browse/CXF-3148?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Dobes Vandermeer updated CXF-3148:
----------------------------------

    Description: 
In org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollection(Class<?>, Object,
Class<?>, Type, String, OutputStream, MediaType), it converts the resulting collection
into an array before serializing it.

Unfortunately, this prevents us from using a collection that lazily loads its contents from
the DB as it goes, since toArray() would require us to create and return all the results immediately.

Ideally this method would be changed to operate in a manner that is "friendly" to lazy collections,
by only using the collection's iterator (once).

This version iterates over the collection only once, which would be the most efficient for
collections that are backed by out of memory storage:

{code}
	protected void marshalCollection(Class<?> originalCls, Object actualObject, Class<?>
actualClass, Type genericType, String encoding,
			OutputStream os, MediaType m) throws Exception {

		Collection c = originalCls.isArray() ? Arrays.asList((Object[]) actualObject) : (Collection)
actualObject;
		
		Iterator it = c.iterator();
		
		boolean empty = false == it.hasNext();
		Object firstObj = empty?null:it.next();
		QName qname = null;
		if (firstObj instanceof JAXBElement) {
			JAXBElement el = (JAXBElement) firstObj;
			qname = el.getName();
			actualClass = el.getDeclaredType();
		} else {
			qname = getCollectionWrapperQName(actualClass, genericType, actualObject, true);
		}
		if (qname == null) {
			String message = new org.apache.cxf.common.i18n.Message("NO_COLLECTION_ROOT", BUNDLE).toString();
			throw new WebApplicationException(Response.serverError().entity(message).build());
		}

		String startTag = null;
		String endTag = null;
		if (qname.getNamespaceURI().length() > 0) {
			startTag = "<ns1:" + qname.getLocalPart() + " xmlns:ns1=\"" + qname.getNamespaceURI()
+ "\">";
			endTag = "</ns1:" + qname.getLocalPart() + ">";
		} else {
			startTag = "<" + qname.getLocalPart() + ">";
			endTag = "</" + qname.getLocalPart() + ">";
		}
		os.write(startTag.getBytes());
		if(!empty) {
			marshalCollectionMember(firstObj instanceof JAXBElement ? ((JAXBElement) firstObj).getValue()
: firstObj, actualClass, genericType, encoding, os, m, qname
					.getNamespaceURI());
			while (it.hasNext()) {
				Object o = it.next();
				marshalCollectionMember(o instanceof JAXBElement ? ((JAXBElement) o).getValue() : firstObj,
actualClass, genericType, encoding, os, m, qname
						.getNamespaceURI());
			}
		}
		os.write(endTag.getBytes());
	}
{code}


  was:
In org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollection(Class<?>, Object,
Class<?>, Type, String, OutputStream, MediaType), it converts the resulting collection
into an array before serializing it.

Unfortunately, this prevents us from using a collection that lazily loads its contents from
the DB as it goes, since toArray() would require us to create and return all the results immediately.

Ideally this method would be changed to operate in a manner that is "friendly" to lazy collections,
by only using the collection's iterator (once).

This version iterates over the collection only once, which would be the most efficient for
collections that are backed by out of memory storage:

{code}
	protected void marshalCollection(Class<?> originalCls, Object actualObject, Class<?>
actualClass, Type genericType, String encoding,
			OutputStream os, MediaType m) throws Exception {

		Collection c = originalCls.isArray() ? Arrays.asList((Object[]) actualObject) : (Collection)
actualObject;
		
		Iterator it = c.iterator();
		
		boolean empty = false == it.hasNext();
		Object firstObj = empty?null:it.next();
		QName qname = null;
		if (firstObj instanceof JAXBElement) {
			JAXBElement el = (JAXBElement) firstObj;
			qname = el.getName();
			actualClass = el.getDeclaredType();
		} else {
			qname = getCollectionWrapperQName(actualClass, genericType, actualObject, true);
		}
		if (qname == null) {
			String message = new org.apache.cxf.common.i18n.Message("NO_COLLECTION_ROOT", BUNDLE).toString();
			throw new WebApplicationException(Response.serverError().entity(message).build());
		}

		String startTag = null;
		String endTag = null;
		if (qname.getNamespaceURI().length() > 0) {
			startTag = "<ns1:" + qname.getLocalPart() + " xmlns:ns1=\"" + qname.getNamespaceURI()
+ "\">";
			endTag = "</ns1:" + qname.getLocalPart() + ">";
		} else {
			startTag = "<" + qname.getLocalPart() + ">";
			endTag = "</" + qname.getLocalPart() + ">";
		}
		os.write(startTag.getBytes());
		marshalCollectionMember(firstObj instanceof JAXBElement ? ((JAXBElement) firstObj).getValue()
: firstObj, actualClass, genericType, encoding, os, m, qname
				.getNamespaceURI());
		while (it.hasNext()) {
			Object o = it.next();
			marshalCollectionMember(o instanceof JAXBElement ? ((JAXBElement) o).getValue() : firstObj,
actualClass, genericType, encoding, os, m, qname
					.getNamespaceURI());
		}
		os.write(endTag.getBytes());
	}
{code}



> CXF converts collections to arrays during serialization
> -------------------------------------------------------
>
>                 Key: CXF-3148
>                 URL: https://issues.apache.org/jira/browse/CXF-3148
>             Project: CXF
>          Issue Type: Bug
>    Affects Versions: 2.3.0
>            Reporter: Dobes Vandermeer
>
> In org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshalCollection(Class<?>,
Object, Class<?>, Type, String, OutputStream, MediaType), it converts the resulting
collection into an array before serializing it.
> Unfortunately, this prevents us from using a collection that lazily loads its contents
from the DB as it goes, since toArray() would require us to create and return all the results
immediately.
> Ideally this method would be changed to operate in a manner that is "friendly" to lazy
collections, by only using the collection's iterator (once).
> This version iterates over the collection only once, which would be the most efficient
for collections that are backed by out of memory storage:
> {code}
> 	protected void marshalCollection(Class<?> originalCls, Object actualObject, Class<?>
actualClass, Type genericType, String encoding,
> 			OutputStream os, MediaType m) throws Exception {
> 		Collection c = originalCls.isArray() ? Arrays.asList((Object[]) actualObject) : (Collection)
actualObject;
> 		
> 		Iterator it = c.iterator();
> 		
> 		boolean empty = false == it.hasNext();
> 		Object firstObj = empty?null:it.next();
> 		QName qname = null;
> 		if (firstObj instanceof JAXBElement) {
> 			JAXBElement el = (JAXBElement) firstObj;
> 			qname = el.getName();
> 			actualClass = el.getDeclaredType();
> 		} else {
> 			qname = getCollectionWrapperQName(actualClass, genericType, actualObject, true);
> 		}
> 		if (qname == null) {
> 			String message = new org.apache.cxf.common.i18n.Message("NO_COLLECTION_ROOT", BUNDLE).toString();
> 			throw new WebApplicationException(Response.serverError().entity(message).build());
> 		}
> 		String startTag = null;
> 		String endTag = null;
> 		if (qname.getNamespaceURI().length() > 0) {
> 			startTag = "<ns1:" + qname.getLocalPart() + " xmlns:ns1=\"" + qname.getNamespaceURI()
+ "\">";
> 			endTag = "</ns1:" + qname.getLocalPart() + ">";
> 		} else {
> 			startTag = "<" + qname.getLocalPart() + ">";
> 			endTag = "</" + qname.getLocalPart() + ">";
> 		}
> 		os.write(startTag.getBytes());
> 		if(!empty) {
> 			marshalCollectionMember(firstObj instanceof JAXBElement ? ((JAXBElement) firstObj).getValue()
: firstObj, actualClass, genericType, encoding, os, m, qname
> 					.getNamespaceURI());
> 			while (it.hasNext()) {
> 				Object o = it.next();
> 				marshalCollectionMember(o instanceof JAXBElement ? ((JAXBElement) o).getValue() :
firstObj, actualClass, genericType, encoding, os, m, qname
> 						.getNamespaceURI());
> 			}
> 		}
> 		os.write(endTag.getBytes());
> 	}
> {code}

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Mime
View raw message