cancel
Showing results for 
Search instead for 
Did you mean: 

How to add an attachment using OpenCMIS with d:content

johnpneal
Champ in-the-making
Champ in-the-making
HiL

I have my content XML as follows:


<model name="hs:HotelSolution">
<!– Optional meta-data about the model –>
<description>Hotel Solution Content Model</description>
<author>Kingsly Rajamani</author>
<version>1.0</version>

<imports>
<!– Import Alfresco Dictionary Definitions –>
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
<!– Import Alfresco Content Domain Model Definitions –>
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
</imports>

<namespaces>
<namespace uri="http://www.ihgmerlin.com/hotelSolution" prefix="hs"/>
</namespaces>

<types>
<!– Definition of new Content Type: Idea Content –>

<type name="hs:IdeaContent">
<title>Hotel Solution Idea Content</title>
<parent>cm:content</parent>

<properties>

  <property name="hs:name">
    <type>d:text</type>
  </property>
  <property name="hs:hotel">
    <type>d:text</type>
  </property>
  <property name="hs:title">
    <type>d:text</type>
  </property>
</properties>
<associations/>
</type>
<!– Definition of new Content Type: Idea Attachment –>

<type name="hs:IdeaAttachment">
<title>Hotel Solution Idea Attachment</title>
<parent>cm:content</parent>
<properties>

  <property name="hs:NameValue">
    <type>d:text</type>
  </property>
  <property name="hs:HotelValue">
    <type>d:text</type>
  </property>
  <property name="hs:TitleValue">
    <type>d:text</type>
  </property>
  <property name="hs:Attachment">
    <type>d:content</type>
  </property>
</properties>
<associations/>
</type>
</types>
<aspects/>
</model>

I can successfully add the IdeaContent.  I was trying to add the second type using OpenCMIS.  My current code up to this point is as follows:


                        CmisObject currentObject ,,,

                        ContentStream contentStream = new ContentStreamImpl("Test Content", null,
         "plain/text", new ByteArrayInputStream(contentString.getBytes()));         

         Map<String, Object> properties = new HashMap<String, Object>();
         properties.put(PropertyIds.NAME, "Test Idea");
         properties.put(PropertyIds.OBJECT_TYPE_ID, "D:hs:IdeaContent");
         properties.put("hs:name", "A name");      
         properties.put("hs:hotel", "A hotel");
         properties.put("hs:title", "A title");
         
         List<Ace> addAces = new LinkedList<Ace>();
         List<Ace> removeAces = new LinkedList<Ace>();
         List<Policy> policies = new LinkedList<Policy>();

         ObjectId newId = session.createDocument(properties, objectId,
               contentStream, VersioningState.MAJOR, policies, addAces,
               removeAces);

This works just fine.  Any help is appreciated on how to add the second type and its attachment would be appreciated.
6 REPLIES 6

fmui
Champ in-the-making
Champ in-the-making
An object can only have one object type.  You can attach multiple aspects types, though. Is that what you want to do?  You haven't defined an aspect type in your XML.

johnpneal
Champ in-the-making
Champ in-the-making
I appreciate your help since I am new to all this and am struggling with the whole concept.  What I am trying to do is attach multiple files to a content type and I am not sure if I am doing the XML correctly, here is my last attempt.  I have modified the XML but probably need a little help there along with a code hint.  Here is my new XML:


<type name="hs:IdeaContent">
  <title>Hotel Solution Idea Content</title>
  <parent>cm:content</parent>
  <properties>

  <property name="hs:name">
    <type>d:text</type>
  </property>

  <property name="hs:hotel">
    <type>d:text</type>
  </property>

  <property name="hs:title">
    <type>d:text</type>
  </property>

  <property name="hs:attach1">
    <type>d:content</type>
  </property>

  <property name="hs:attach2">
    <type>d:content</type>
  </property>
</properties>
<associations/>
</type>

So I am probably doing something wrong with the XML but I just want to attach say in attach1 a word document and attach2 a pdf document, etc.  There will be a maximum of 5 attachments.  I understand that Alfresco does not allow multiple attachments.  The original XML was trying to set up a second <type> that would allow me to have some attributes around an attachment but I seem to be failing in both respects.  I am able to create the content or create a document but my trouble is adding attachments to the content.  Maybe I am crazy trying to do this but that's what the business wants :-).  I really like the OpenCMIS API but am struggling a little bit since I am new to Alfresco and CMS in general and definitely OpenCMIS.

Regards,

John

fmui
Champ in-the-making
Champ in-the-making
CMIS only supports one content stream per document object. (It supports multiple renditions per document, but that's a different story.)
So you have to create multiple objects.

Since I don't know your application I can't tell you what would be the best way to set up your model. Here are a few ideas:

  • Create a folder, add your properties to that folder object and put all related documents into this folder.

  • Create a relationship type and connect all related documents with relationships.

  • Find a common key and add it all documents. Then you can find all related documents with a query.

tusharpatel88
Champ in-the-making
Champ in-the-making
Hi I want to attach file during my workflow. I add two parent for it. Due to it is not working. Is there any solution for atach file.

<parent>bpm:workflowTask</parent>
<parent>cm:cmobject</parent>

I'm not very clear about your requirement .
You can try to attach a foder to your workflow,and add your attached files to this folder.

johnpneal
Champ in-the-making
Champ in-the-making
Thanks for the suggestion.  I am trying that now but getting an internal server error when I create the relationship between the Custom Content Type and any document.  My code is as follows:


      Document document1 = null;
      Document document2 = null;
      ContentStream content = null;
      String path = null;
      Folder folder1 = null;
      Folder folder2 = null;
      
      try {
         //First get the folders we are working with
         session = createSession();
         
         path = "/User Homes/Ideas/";
         folder1 = (Folder) session.getObjectByPath(path);
         assertNotNull(folder1);
         String id = folder1.getId();
         assertNotNull(id);
         System.out.println("ID = " + id);
         
         path = "/User Homes/Ideas/Idea Documents";
         folder2 = (Folder) session.getObjectByPath(path);
         assertNotNull(folder2);
         id = folder2.getId();
         assertNotNull(id);
         System.out.println("ID = " + id);
         
         //Next create the content type
         String name = "Test Idea - " + System.currentTimeMillis();         
         String contentString = "This is a test idea!!!";
         
         ContentStream contentStream = new ContentStreamImpl("Test Content", null,
         "plain/text", new ByteArrayInputStream(contentString.getBytes()));         

         Map<String, Object> properties = new HashMap<String, Object>();
         properties.put(PropertyIds.NAME, name);
         properties.put(PropertyIds.OBJECT_TYPE_ID, "D:hs:IdeaContent");
         properties.put("hs:name", "A name");      
         properties.put("hs:hotel", "A hotel");
         properties.put("hs:title", "A title");
         properties.put("hs:role", "A role");
         properties.put("hs:summary", "A summary");
         properties.put("hs:results", "A resutls");
         properties.put("hs:steps", "A steps");
         properties.put("hs:cost", "A cost");
         properties.put("hs:time", "A time");
         
         List<String> hotelBrands = new ArrayList<String>();

         hotelBrands.add("Hotel Brand 1");
         hotelBrands.add("Hotel Brand 2");
         properties.put("hs:hotelBrands", hotelBrands);


         List<String> hotelTypes = new ArrayList<String>();

         hotelTypes.add("Hotel Type 1");
         hotelTypes.add("Hotel Type 2");
         properties.put("hs:hotelTypes", hotelTypes);
         
         List<String> hotelRegions = new ArrayList<String>();

         hotelRegions.add("Hotel Region 1");
         hotelRegions.add("Hotel Region 2");
         properties.put("hs:hotelRegions", hotelRegions);
         
         List<String> keywords = new ArrayList<String>();

         keywords.add("Keyword 1");
         keywords.add("Keyword 2");
         properties.put("hs:keywords", keywords);   
         
      
         List<Ace> addAces = new LinkedList<Ace>();
         List<Ace> removeAces = new LinkedList<Ace>();
         List<Policy> policies = new LinkedList<Policy>();


         document1 = folder1.createDocument(properties, contentStream, VersioningState.MAJOR, policies, addAces, removeAces, session.getDefaultContext());
         assertNotNull(document1);
         assertTrue(document1 instanceof Document);
         System.out.println("New ID = " + document1.getId());
         
         
         //Create the document to use
         name = "JEHA Overview.doc";
         String saveName = "JEHA Overview - "  + System.currentTimeMillis() + ".doc";
         String pathName = "c:\\" + name;
      
                   Map<String,String> newDocProps = new HashMap<String, String>();
                   newDocProps.put(PropertyIds.OBJECT_TYPE_ID, "D:cmiscustom:document");
                   newDocProps.put(PropertyIds.NAME, saveName);
          
         contentStream = new ContentStreamImpl(name + System.currentTimeMillis(), null,
               "application/msword", new ByteArrayInputStream(
                     createFile(pathName)));
         
         document2 = folder2.createDocument(newDocProps, contentStream, VersioningState.MAJOR, policies, addAces, removeAces, session.getDefaultContext());
         assertTrue(document2 instanceof Document);
         assertNotNull(document2);
         assertEquals(document2.getContentStreamMimeType(), "application/msword");         
         
                   Map<String, Serializable> relProps = new HashMap<String, Serializable>();
                   relProps.put("cmis:sourceId", document1.getId());
                   relProps.put("cmis:targetId", document2.getId());
                   relProps.put("cmis:objectTypeId", "R:cmiscustom:assoc");
                   session.createRelationship(relProps, policies, addAces, removeAces);            
      } catch (Exception e) {
         System.out.println("Exception" + e);
         e.printStackTrace();
         fail("Unexpected Exception");
      }

Exception as follows:


Exceptionorg.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException: Internal Server Error
org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException: Internal Server Error
   at org.apache.chemistry.opencmis.client.bindings.spi.atompub.AbstractAtomPubService.convertStatusCode(AbstractAtomPubService.java:411)
   at org.apache.chemistry.opencmis.client.bindings.spi.atompub.AbstractAtomPubService.post(AbstractAtomPubService.java:499)
   at org.apache.chemistry.opencmis.client.bindings.spi.atompub.ObjectServiceImpl.createRelationship(ObjectServiceImpl.java:290)
   at org.apache.chemistry.opencmis.client.runtime.PersistentSessionImpl.createRelationship(PersistentSessionImpl.java:655)
   at com.ihg.test.TestAlfresco.testCreateRelationship(TestAlfresco.java:214)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
   at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
   at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
   at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
   at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
   at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
   at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
   at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
   at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
   at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
   at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
   at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
   at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
   at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
   at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
   at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
   at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

When I run this code extrapolated from the OpenCMIS test suite it works fine:


         String path = "/User Homes/Ideas/Idea Documents";
         Folder folder = (Folder) session.getObjectByPath(path);
         assertNotNull(folder);
         String id = folder.getId();
         assertNotNull(id);
         System.out.println("ID = " + id);
   
           Map<String,String> newDocProps1 = new HashMap<String, String>();
           newDocProps1.put(PropertyIds.OBJECT_TYPE_ID, "D:cmiscustom:document");
           newDocProps1.put(PropertyIds.NAME, "Test Doc 1");
           ContentStream contentStream1 = new ContentStreamImpl("xyz.txt", null, "plain/text", new ByteArrayInputStream("some content".getBytes()));
           Document doc1 = folder.createDocument(newDocProps1, contentStream1, VersioningState.MAJOR, null, null, null, session.getDefaultContext());
   
           Map<String,String> newDocProps2 = new HashMap<String, String>();
           newDocProps2.put(PropertyIds.OBJECT_TYPE_ID, "D:cmiscustom:document");
           newDocProps2.put(PropertyIds.NAME, "Test Doc 2");
           ContentStream contentStream2 = new ContentStreamImpl("xyz.txt", null, "plain/text", new ByteArrayInputStream("some content".getBytes()));
           Document doc2 = folder.createDocument(newDocProps2, contentStream2, VersioningState.MAJOR, null, null, null, session.getDefaultContext());
          
           Map<String, Serializable> relProps = new HashMap<String, Serializable>();
           relProps.put("cmis:sourceId", doc1.getId());
           relProps.put("cmis:targetId", doc2.getId());
           relProps.put("cmis:objectTypeId", "R:cmiscustom:assoc");
           session.createRelationship(relProps, null, null, null);   

Is there an issue with the custom content type having a relationship to a document?  It seems to work when I use 2 documents.  I have learned allot by tinkering with your replies and am getting closer to my goal each time.  I can now create the custom content, documents, folders, etc. with no problem.  Your help has been appreciated :-).

John