Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-3148

CXF converts collections to arrays during serialization

Attach filesAttach ScreenshotVotersWatch issueWatchersCreate sub-taskLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.3
    • 2.2.12, 2.3.1, 2.4
    • JAX-RS
    • None

    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());
      	}
      

      Attachments

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            sergey_beryozkin Sergey Beryozkin
            dobes_vandermeer Dobes Vandermeer
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Issue deployment