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:
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() : o, actualClass, genericType, encoding, os, m, qname .getNamespaceURI()); } } os.write(endTag.getBytes()); }