cancel
Showing results for 
Search instead for 
Did you mean: 

Adding custom aspects during an upload using Java

yuhuayang
Champ in-the-making
Champ in-the-making
Hi All

I really would appreciate some help on this.

I am currently trying to create my own Inbound email handler similar to this tutorial: http://www.whiteboardcoder.com/2012/11/alfresco-4-customize-inbound-email.html

The difference is that I am also attempting to extract information from the body of the email and use that data as values for custom aspect properties. Because the custom aspects are not attached to the document yet, I need the custom email handler to also add aspects to the document and then set the values to be the ones I extracted from the body of the email.

I have created my custom aspects and properties and have verified it working. I can add the custom aspects to my documents in Alfresco. Here is model xml just for reference:

<?xml version="1.0" encoding="UTF-8"?>
<model name="contracts:contractsModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
    <description>Contract Metadata</description>
    <author>yangy</author>
    <version>1.0</version>
    <imports>
        <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
        <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
    </imports>
    <namespaces>
        <namespace uri="contracts.model" prefix="contracts"/>
    </namespaces>
    <aspects>
        <aspect name="contracts:metadata">
            <title>Contracts Metadata</title>
            <properties>
                <property name="contracts:masterID">
                    <title>Master ID</title>
                    <type>d:text</type>
                </property>
                <property name="contracts:companyName">
                    <title>Company Name</title>
                    <type>d:text</type>
                </property>
            </properties>
        </aspect>
    </aspects>
</model>


However my problem is in the Java code. I am getting this error:
Caused by: org.alfresco.service.cmr.dictionary.InvalidAspectException: 07260056 The aspect is invalid: {contracts.model.}metadata 


Even though I followed the NodeRef cookbook to add aspects (http://wiki.alfresco.com/wiki/NodeRef_cookbook#Adding_an_aspect_to_a_node) Is this wiki completely outdated and wrong to follow? It did mislead me about the services I needed to start which I don't think were right. I don't understand why official wiki from Alfresco leads people down the wrong path sometimes.

The following is my Java code, specifically the parts attempting to add aspects:

package com._10x13.alfresco.email;

import org.alfresco.email.server.handler.FolderEmailMessageHandler;
import org.apache.log4j.Logger;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.email.EmailMessage;
import org.alfresco.service.cmr.email.EmailMessagePart;
import org.alfresco.service.cmr.repository.MimetypeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.ListableBeanFactory;

import javax.xml.parsers.*;
import org.xml.sax.InputSource;
import org.w3c.dom.*;
import java.io.*;
import java.util.*;

public class CustomFolderEmailMessageHandler
                                            extends FolderEmailMessageHandler {
    private Logger log = Logger.getLogger("com._10x13");
    private ListableBeanFactory beanFactory;
   
    private NodeService nodeService;
  
    public void setNodeService(NodeService nodeService)
    {
        //  System.out.println(" dist ");
        this.nodeService = nodeService;
    }

    public void processMessage(NodeRef folderNodeRef, EmailMessage message){
       
        //ServiceRegistry serviceRegistry = (ServiceRegistry) beanFactory.getBean(ServiceRegistry.SERVICE_REGISTRY);
        //NodeService nodeService = serviceRegistry.getNodeService();
       
        String toAddress = message.getTo();
        String fromAddress = message.getFrom();
        String subject = message.getSubject();
        MimetypeService mimetypeService = getMimetypeService();
        InputStream contentIs;
        InputStream bodyContent;
        NodeRef contentNodeRef;
        String mimeType;

        log.info("An Email was sent to: " + toAddress);
        log.info("An Email was sent from: " + fromAddress);
        log.info("An Email was sent with the subject line of: " + subject);
       
        //here we extract the body of the email and the meta data
        EmailMessagePart mailBody = message.getBody();
        bodyContent = mailBody.getContent();
       
        String metaData = fromStream(bodyContent);
       
        //get the metadata
        String masterID = parseXMLString(metaData, "MasterID");
        String companyName = parseXMLString(metaData, "CompanyName");
       

        for(EmailMessagePart attachment: message.getAttachments()) {
            //Skip saving the email as an html file
            if(!attachment.getFileName().startsWith(subject)){
                log.info("attached file is named: " + attachment.getFileName()
                           + "And Has a size of: " + attachment.getSize() + " Bytes");

                contentIs = attachment.getContent();
                mimeType = mimetypeService.guessMimetype(attachment.getFileName());
               
                //here the document is added as a node, returned nodeRef
                contentNodeRef = addContentNode(nodeService,
                                                folderNodeRef, attachment.getFileName(), true);

                writeContent(contentNodeRef, contentIs, mimeType, attachment.getEncoding());
               
                log.info("the file has been written to node: " + contentNodeRef.toString());
               
                //add the metadata
                Map<QName,Serializable> aspectValues = new HashMap<QName,Serializable>();
               
                QName CUSTOM_ASPECT_QNAME = QName.createQName("contracts.model", "metadata");
                QName PROP_QNAME_MY_PROPERTY = QName.createQName("contracts.model", "masterID");
                aspectValues.put(PROP_QNAME_MY_PROPERTY, masterID);
                nodeService.addAspect(contentNodeRef, CUSTOM_ASPECT_QNAME, aspectValues);
               
                //clear aspectValues
                aspectValues.clear();
               
                PROP_QNAME_MY_PROPERTY = QName.createQName("contracts.model", "companyName");
                aspectValues.put(PROP_QNAME_MY_PROPERTY, companyName);
                nodeService.addAspect(contentNodeRef, CUSTOM_ASPECT_QNAME, aspectValues);
               
            }
        }
    }
    public static String parseXMLString(String s, String tag) {
       
        String result = "";
       
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(s));
           
            Document doc = db.parse(is);
            NodeList node = doc.getElementsByTagName(tag);
            Element line = (Element) node.item(0);
           
            result = getCharacterDataFromElement(line);
           
        }
        catch (Exception e) {
            e.printStackTrace();
        }
       
        return result;
    }
    public static String getCharacterDataFromElement(Element e) {
        Node child = e.getFirstChild();
        if (child instanceof CharacterData) {
            CharacterData cd = (CharacterData) child;
            return cd.getData();
        }
        return "?";
    }
    public static String fromStream(InputStream is) {
       
        BufferedReader br = null;
        StringBuilder sb = new StringBuilder();
       
        String line;
        try {
           
            br = new BufferedReader(new InputStreamReader(is));
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
           
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
       
        return sb.toString();
       
    }
                           
}
5 REPLIES 5

yuhuayang
Champ in-the-making
Champ in-the-making
I mainly don't understand how to call this function:
QName.createQName("contracts.model", "metadata");


It seems on documentation that I need
createQName(java.lang.String prefix, java.lang.String localName, NamespacePrefixResolver prefixResolver)


but if I do this:
QName CUSTOM_ASPECT_QNAME = QName.createQName("contracts", "metadata", namespacePrefixResolver);


I get this error:
Caused by: java.lang.IllegalArgumentException: A Prefix Resolver must be specified

How do I use NamespacePrefixResolver??

any help?

kaynezhang
World-Class Innovator
World-Class Innovator
You don't need to provider a namespacePrefixResolver.you got asked to provide a namespacePrefixResolver is because there is something wrong in your aspect namespace defintion .
You should define you aspect like this:

<?xml version="1.0" encoding="UTF-8"?>
<model name="contracts:contractsModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
   <description>Contract Metadata</description>
   <author>yangy</author>
   <version>1.0</version>
   <imports>
      <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
      <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
   </imports>
   <namespaces>
      <namespace uri="http://www.yourorganization.org/model/content/1.0" prefix="contracts"/>
   </namespaces>
   <aspects>
      <aspect name="contracts:metadata">
         <title>Contracts Metadata</title>
         <properties>
            <property name="contracts:masterID">
               <title>Master ID</title>
               <type>d:text</type>
            </property>
            <property name="contracts:companyName">
               <title>Company Name</title>
               <type>d:text</type>
            </property>
         </properties>
      </aspect>
   </aspects>
</model>

yuhuayang
Champ in-the-making
Champ in-the-making
thanks but if I change the namespace URI, how would I reference contracts.model?

According to official Alfresco wiki here (http://wiki.alfresco.com/wiki/Data_Dictionary_Guide#Step_by_Step_Model_Definition) it is supposed to be just modelname.model?

Is the official Alfresco documentation wrong again?

yuhuayang
Champ in-the-making
Champ in-the-making
Hi

I tried the suggested solution of changing the
<namespace uri="http://www.yourorganization.org/model/content/1.0"> 
and this is now the error:

Caused by: org.alfresco.service.namespace.NamespaceException: A namespace prefix is not registered for uri contracts.model
   at org.alfresco.service.namespace.QName.toPrefixString(QName.java:414)
   at org.alfresco.repo.template.BaseContentNode.hasAspect(BaseContentNode.java:345)
   at sun.reflect.GeneratedMethodAccessor626.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:597)
   at freemarker.ext.beans.BeansWrapper.invokeMethod(BeansWrapper.java:870)
   at freemarker.ext.beans.SimpleMethodModel.exec(SimpleMethodModel.java:106)

yuhuayang
Champ in-the-making
Champ in-the-making
Ok, so I have figured it out

This is the right URI for anyone having the same problem in the future:
 <namespace uri="http://www.yourorganization.org/model/yourmodelname/1.0" prefix="contracts"/> 
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.