3 Replies Latest reply on Feb 25, 2010 1:04 PM by nlugert

    Error creating content using FileSystemSource

      I am getting an error while attempting to add a new file via the Graph API.

       

      Using 1.0 Beta with Java6

       

      Here is my code:

       

      Graph graph = client.getEngine().getGraph("CSP");

       

              // Create the file node ...
              graph.create("/modeshape.txt").with("jcr:primaryType","nt:file").and();

       

              // Create the file's content node ...
              Binary bin = context.getValueFactories().getBinaryFactory().create(new File("/usr/local/sandbox/Desktop/modeshape.txt"));
              try {
                    bin.acquire();
                    graph.create("/modeshape.txt/jcr:content").with("jcr:primaryType","nt:resource").and("jcr:data",bin).and();
              } finally {
                    bin.release();
              }

       

      I also tried this way and got the same error:

      Graph graph = client.getEngine().getGraph("CSP");
              graph.batch()
                   .create("/modeshape.txt").with("jcr:primaryType","nt:file")
                   .and()
                   .create("/modeshape.txt/jcr:content").with("jcr:primaryType","nt:resource").and("jcr:data",bin)
                   .and();

       

      Here is the Error:

      org.modeshape.graph.request.InvalidRequestException: Repository source "CSP" does not allow same name siblings on nodes: jcr:content
          at org.modeshape.connector.filesystem.FileSystemRepository$FileSystemWorkspace.createNode(FileSystemRepository.java:289)
          at org.modeshape.graph.connector.path.PathRequestProcessor.process(PathRequestProcessor.java:283)
          at org.modeshape.graph.request.processor.RequestProcessor.process(RequestProcessor.java:227)
          at org.modeshape.graph.connector.path.PathRepositoryConnection.execute(PathRepositoryConnection.java:84)
          at org.modeshape.graph.connector.RepositoryConnectionPool$ConnectionWrapper.execute(RepositoryConnectionPool.java:996)
          at org.modeshape.graph.Graph.execute(Graph.java:267)
          at org.modeshape.graph.Graph$5.process(Graph.java:210)
          at org.modeshape.graph.request.RequestBuilder.createNode(RequestBuilder.java:289)
          at org.modeshape.graph.Graph$12.submit(Graph.java:1300)
          at org.modeshape.graph.Graph$12.submit(Graph.java:1293)
          at org.modeshape.graph.Graph$CreateAction.and(Graph.java:7703)

        • 1. Re: Error creating content using FileSystemSource
          rhauch

          There are several various behaviors for creating nodes using the Graph API that deal with the semantics if a node already exists with the same name. This is called the conflict behavior, and it specifies whether the new node:

          1. should be appended after any existing children with the same name;
          2. should replace any existing child with the same name;
          3. should be created only if there is not an existing child with the same name; or
          4. should update an existing child with the same name so it effectively looks like the new node.

           

          Although #1 is the default behavior, the Graph API actually lets you fully-specify what you want to use.  Here's an example that specifies the #2 behavior listed above:

           

              Graph graph = client.getEngine().getGraph("CSP");
              graph.batch()

                   .create("/modeshape.txt").with("jcr:primaryType","nt:file")

                   .orReplace()

                   .and()
                   .create("/modeshape.txt/jcr:content").with("jcr:primaryType","nt:resource").and("jcr:data",bin)

                   .orReplace()

                   .and();

          Alternatively, there is "byAppending()" for #1, "ifAbsent()" for #3, and "orUpdate()" for #4.  For details, see the JavaDoc for this part of the Graph API.

           

          So with the default conflict behavior, your code does successfully create the "modeshape.txt" node, but under the covers the file system connector is automatically creating the required "jcr:content" child node (i.e., equivalent to creating an empty file).  Thus, when the connector then processes the request to create the "jcr:content" node with the desired content, the default "append" behavior means that the "jcr:content" node should be appended to the existing child node, and this is not possible because the file system connector doesn't support same-name-siblings.

           

          To correct this, you need to specify the "orReplace()" behavior.  However, IMO, the "jcr:content" child node under an "nt:file" node is a little special, and the file system connector should be handling this better so that the default conflict behavior does indeed work.  Therefore, I've logged MODE-667 to get this fixed.

           

          In the meantime, I'd recommend adding the "orReplace()" behavior. It is really the behavior you want for files and directories, so it won't hurt to use, even after MODE-667 is fixed.

          • 2. Re: Error creating content using FileSystemSource
            rhauch

            MODE-667 has been fixed in trunk, which you can test locally if you want.  Note that the workaround that I mentioned still works and is perfectly fine to keep using.

            • 3. Re: Error creating content using FileSystemSource

              Randall,

               

              Thanks very much for your help. The work around you gave didn't give any errors but the file was empty once created on the FileSystem. I modified to this:

               

                   Graph graph = client.getEngine().getGraph("CSP");
                      graph.create("/modeshape.txt").with("jcr:primaryType","nt:file").and();
                      graph.create("/modeshape.txt/jcr:content").with("jcr:primaryType","nt:resource").and("jcr:data",bin)
                           .orReplace()
                           .and();

               

              And File created successfully. Everything is working great now.

               

              Thanks again,

               

              Nathan