cancel
Showing results for 
Search instead for 
Did you mean: 

Multi-Value property not being set correctly on read

rvoliva
Champ in-the-making
Champ in-the-making
I'm either missing something or found a bug in 3.0b relating to multi-value properties.

I set a property as multi-value by creating the NamedValue object, setting the "isMultiValue" field to true, and provide an array of Strings.  I save that document.  I check the repository through the UI using the node browser, and I can see the property for this document.  In the UI, in the "value" column, above the three values I have set for this property, in red it says "–collection–".

I'm assuming up to this point everything is kosher.

So now I read in this document through my web service code.  I then iterate over the Node's properties (node.getProperties()) - and when I come across my multi-value property, it's "isMultiValue" field is set to false.  Also, the "values" field is null and instead the "value" field is set to a String of my three values, separated by comma.  The String looks like this:

[some_value, some_other_value, yet_another_value]

I can provide some code samples if that would be helpful.  Hopefully this is something someone out there has encountered before….

TIA,
Bobby
2 REPLIES 2

derek
Star Contributor
Star Contributor
Hi,
It looks as if you have uncovered a bug in the WebServices handling of multi-valued properties.  If you have a specific use-case, it'll help if you posted that.
Regards

rvoliva
Champ in-the-making
Champ in-the-making
Here's the code I'm using to read/load a document:


@Override
   public Document loadDocument(String documentId) throws DocumentNotFoundException {
      try {
         Predicate predicate = buildPredicate(buildReference(documentId));
         Content content = WebServiceFactory.getContentService().read(predicate, Constants.PROP_CONTENT)[0];
         if (content == null) {
            throw new DocumentNotFoundException("The document's content was empty");
         }
         InputStream contentStream = ContentUtils.getContentAsInputStream(content);
         DocumentType contentType = DocumentType.getDocumentTypeForMimeType(content.getFormat().getMimetype());
         Node documentNode = WebServiceFactory.getRepositoryService().get(predicate)[0];
         String name = null;
         String createdBy = null;
         Map<UserDefinedDocumentProperty, String[]> userDefinedProperties = new HashMap<UserDefinedDocumentProperty, String[]>();
         for (NamedValue namedValue : documentNode.getProperties()) {
            String value = namedValue.getValue();
            String valueName = namedValue.getName();
            String strippedValueName = namedValue.getName().substring(namedValue.getName().lastIndexOf("}") + 1);
            if (valueName.equals(Constants.PROP_NAME)) {
               name = value;
            } else if (valueName.equals(Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, PreDefinedDocumentProperty.CREATED_BY.getPropertyName()))) {
               createdBy = value;
            }
            try {
               UserDefinedDocumentProperty property = UserDefinedDocumentProperty.getUserDefinedDocumentPropertyByPropertyName(strippedValueName);
               userDefinedProperties.put(property, namedValue.getValues());
            } catch (EnumConstantNotPresentException e) {
               // nothing to do, there are many Alfresco properties that we don't care about
            }
         }
         Folder parent = getParentFolder(documentId);
         return new Document(documentId, contentStream, name, contentType, createdBy, isVersionable(documentNode), parent, userDefinedProperties);
      } catch (ContentFault e) {
         logger.info(e.getMessage(), e);
         throw new DocumentNotFoundException(e);
      } catch (RemoteException e) {
         logger.info(e.getMessage(), e);
         throw new DocumentNotFoundException(e);
      }
   }

It's this line that exposes the problem:

userDefinedProperties.put(property, namedValue.getValues());

namedValue.getValues() returns null - instead, namedValue.getValue() contains the comma separated String of my values and isMultiValue is set to false.

Here's the code I'm using to create the document initially:


@Override
   public String saveDocument(Document document, String revisionNote) throws DocumentManagementException {
      if (document.getContent() == null) {
         throw new DocumentManagementException("The document must contain some content");
      }

      ContentFormat format = new ContentFormat(document.getType().getMimeType(), ENCODING);
      List<NamedValue> properties = new ArrayList<NamedValue>();

      for (UserDefinedDocumentProperty property : document.getUserDefinedProperties().keySet()) {
         NamedValue newValue = new NamedValue();
         newValue.setName(Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, property.getPropertyName()));
         newValue.setIsMultiValue(true);
         newValue.setValues(document.getUserDefinedProperties().get(property));
         properties.add(newValue);
      }

      if (document.getDocumentId() == null || document.getDocumentId().isEmpty()) {
         if (document.getName() == null || document.getName().isEmpty()) {
            throw new DocumentManagementException("The document's name must be supplied");
         }
         ParentReference parentReference = getParentReferenceById(document.getName(), document.getContainingFolder().getUuid());

         properties.add(Utils.createNamedValue(Constants.PROP_NAME, document.getName()));
         properties.add(Utils.createNamedValue(Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, PreDefinedDocumentProperty.CREATED_BY.getPropertyName()), activeEmployee.getEmployeeId().toString()));

         CML cml = buildCMLForCreate(parentReference, properties.toArray(new NamedValue[0]), Constants.TYPE_CONTENT);

         try {
            UpdateResult[] result = WebServiceFactory.getRepositoryService().update(cml);
            Reference newContentNode = result[0].getDestination();
            Content content = WebServiceFactory.getContentService().write(newContentNode, Constants.PROP_CONTENT, ContentUtils.convertToByteArray(document.getContent()), format);
            if (document.isVersionable()) {
               makeVersionable(content.getNode());
            }
            return content.getNode().getUuid();
         } catch (Exception e) {
            logger.info(e.getMessage(), e);
            throw new IllegalStateException(e);
         }
      }

      try {
         // checkout a working copy
         Predicate itemsToCheckOut = buildPredicate(buildReference(document.getDocumentId()));
         CheckoutResult checkOutResult = WebServiceFactory.getAuthoringService().checkout(itemsToCheckOut, null);
         Reference workingCopyReference = checkOutResult.getWorkingCopies()[0];
         // write the new content
         Predicate predicate = buildPredicate(workingCopyReference);
         WebServiceFactory.getContentService().write(workingCopyReference, Constants.PROP_CONTENT, ContentUtils.convertToByteArray(document.getContent()), format);
         // update properties
         CML cml = buildCMLForUpdate(properties.toArray(new NamedValue[0]), predicate, document.getDocumentId());
         WebServiceFactory.getRepositoryService().update(cml);
         // check it back in
         NamedValue[] comments = new NamedValue[] {
               Utils.createNamedValue(Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, PreDefinedDocumentProperty.REVISION_NOTE.getPropertyName()), revisionNote),
               Utils.createNamedValue(Constants.createQNameString(Constants.NAMESPACE_CONTENT_MODEL, PreDefinedDocumentProperty.UPDATED_BY.getPropertyName()), activeEmployee.getEmployeeId().toString())
         };
         WebServiceFactory.getAuthoringService().checkin(predicate, comments, false);
         return document.getDocumentId();
      } catch (Exception e) {
         logger.info(e.getMessage(), e);
         throw new DocumentManagementException(e);
      }

   }

The first for loop in the write document code shows that i'm setting up the multi-value property correctly.

I know my example code contains a lot of structures and objects that we created, but hopefully you can sift through it and get a valid test case out of it.

What's your recommended solution/workaround in the meantime?

Thanks,
Bobby