7 Replies Latest reply on Sep 9, 2010 6:26 PM by rhauch

    Problem with custom node types

    craigching

      Hi!

       

      First, I'm very new to JCR and ModeShape in particular, I've dabbled a bit in Jackrabbit, but I'd still consider myself pretty new to the subject.

       

      I'm sure I'm missing something fundamental, but I just can't figure out what it is.  I've got the following code working with Jackrabbit, but I want to use ModeShape (in particular the Infinispan connector).  Here's my code:

       

       

      public class JcrTest {
          static public void main(String [] args) throws Exception {
              Repository repo = null;
              Map<String, String> parameters = new HashMap<String, String>();
              parameters.put("org.modeshape.jcr.URL", "file:cars-repository-config.xml?repositoryName=Cars");
              for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {
                  repo = factory.getRepository(parameters);
                  if (repo != null) {
                      break;
                  }
              }
              if (repo != null) {
                  Session session = repo.login();
                  String [] prefixes = session.getNamespacePrefixes();
                  for (String prefix : prefixes) {
                      System.out.println("Prefix: " + prefix);
                  }
                  Workspace ws = session.getWorkspace();
                  System.out.println("WS Name: " + ws.getName());
                  Node root = session.getRootNode();
                  Node type = root.addNode("Hybrid", "nt:unstructured");
                  for(int i=0;i<10;i++) {
                      Node car = type.addNode("car_" + i, "car:Car");
                      car.setProperty("car:maker", "Volkswagen");
                      car.setProperty("car:model", "Passat");
                      car.setProperty("car:year", "2010");
                      car.setProperty("car:msrp", "$32,000");
                  }
                  session.save();
              }
          }

      public class JcrTest {

       

          static public void main(String [] args) throws Exception {

              Repository repo = null;

       

              Map<String, String> parameters = new HashMap<String, String>();

       

              parameters.put("org.modeshape.jcr.URL", "file:cars-repository-config.xml?repositoryName=Cars");

       

              for (RepositoryFactory factory : ServiceLoader.load(RepositoryFactory.class)) {

                  repo = factory.getRepository(parameters);

                  if (repo != null) {

                      break;

                  }

              }

              if (repo != null) {

                  Session session = repo.login();

                  String [] prefixes = session.getNamespacePrefixes();

                  for (String prefix : prefixes) {

                      System.out.println("Prefix: " + prefix);

                  }

                  Workspace ws = session.getWorkspace();

                  System.out.println("WS Name: " + ws.getName());

                  Node root = session.getRootNode();

                  Node type = root.addNode("Hybrid", "nt:unstructured");

                  for(int i=0;i<10;i++) {

                      Node car = type.addNode("car_" + i, "car:Car");

                      car.setProperty("car:maker", "Volkswagen");

                      car.setProperty("car:model", "Passat");

                      car.setProperty("car:year", "2010");

                      car.setProperty("car:msrp", "$32,000");

                  }

       

                  session.save();

              }

          }

       

       

      and here is my repository configuration (basically a bastardization of the repository example):

       

       

      <?xml version="1.0" encoding="UTF-8"?>

      <configuration xmlns:mode="http://www.modeshape.org/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0">

          <mode:sources jcr:primaryType="nt:unstructured">

              <mode:source jcr:name="Cars" mode:classname="org.modeshape.graph.connector.inmemory.InMemoryRepositorySource" mode:retryLimit="3" mode:defaultWorkspaceName="cars-workspace" mode:updatesAllowed="true"/>

          </mode:sources>

          <mode:repositories>

              <mode:repository jcr:name="Cars">

                  <!-- Specify the source that should be used for the repository -->

                  <mode:source>Cars</mode:source>

                  <!-- Define the options for the JCR repository, using camelcase version of JcrRepository.Option names -->

                  <mode:options jcr:primaryType="mode:options">

                      <jaasLoginConfigName jcr:primaryType="mode:option" mode:value="modeshape-jcr"/>

                  </mode:options>

                  <!-- Define any custom node types. Importing CND files via JcrConfiguration is equivalent to specifying here. -->

                  <jcr:nodeTypes mode:resource="file:cars.cnd" />

                  <!-- Define any namespaces for this repository, other than those already defined by JCR or ModeShape -->

                  <namespaces jcr:primaryType="mode:namespaces">

                      <car jcr:primaryType="mode:namespace" mode:uri="http://www.modeshape.org/examples/cars/1.0"/>

                  </namespaces>

              </mode:repository>

          </mode:repositories>

      </configuration>

      and cars.cnd is from the repositories example unchanged.
      The error I'm getting is this:
      Exception in thread "main" javax.jcr.RepositoryException: The "primaryNodeTypeName" parameter value "car:Car" was not a valid node type name
      at org.modeshape.jcr.AbstractJcrNode.addNode(AbstractJcrNode.java:1453)
      at org.modeshape.jcr.AbstractJcrNode.addNode(AbstractJcrNode.java:1356)
      at com.bmc.jcr.JcrTest.main(JcrTest.java:39)
      I've tried everything I can to get it to recognize the custom node type defined in the repository configuration, but I can't see anything that indicates it's being used.  Anyone know what I'm doing wrong?  Thanks!
        • 1. Re: Problem with custom node types
          craigching

          I did a little debugging and I can't see that:

           

          <jcr:nodeTypes mode:resource="file:cars.cnd" />

           

          has any effect.  I don't see that JcrConfiguration.RepositoryDefinition.addNodeTypes is ever called.

           

          So I changed to adding the node types through code.  One note, I would suggest that CndNodeTypeReader.read(String) thrown an exception when the .cnd file is not found (on the classpath).  I mistakenly thought it would work for a file on the file system

           

          Anyway, looking for confirmation that specifying a .cnd in the repository configuration is or isn't a defect.  I'll open one if someone tells me it is one.

          • 2. Re: Problem with custom node types
            rhauch

            The following line in your configuration file is not correct:

            <jcr:nodeTypes mode:resource="file:cars.cnd" />

             

            The parameter value should not be a URL, but should be the name of a resource on the classpath (or a comma separate list of names of resources on the classpath). IOW, this particular line tells the engine to find the resource on the classpath named "file:cars.cnd", which of course does not work.

             

            This should work:

             

            <jcr:nodeTypes mode:resource="cars.cnd" />

             

            So I changed to adding the node types through code.  One note, I would suggest that CndNodeTypeReader.read(String) thrown an exception when the .cnd file is not found (on the classpath).  I mistakenly thought it would work for a file on the file system

             

            There are several methods on CndNodeTypeReader that accept various types, including a URL, InputStream, java.io.File, and String. The method that takes a String specifying the name of a classpath resource does not currently throw an exception if the classpath resource cannot be found. This is definitely a bug. The documentation should give several examples, and the code should be more tolerant of leading '/' character (unfortunately, Class.getResourceAsStream() and ClassLoader.getResourceAsStream() have different requirements for the leading '/').

             

            If you would, could you log a new issue in JIRA to correct & improve the CndNodeTypeReader.read(String) method?

            • 3. Re: Problem with custom node types
              craigching

              Ah, ok, I didn't know the .cnd file had to be on the classpath, thanks for the information!

               

              About the lack of error indication when the resource isn't found by CndNodeTypeReader.read(String), I've opened an issue for that:

               

              https://jira.jboss.org/browse/MODE-892

               

              Thanks for the help Randall!

              • 4. Re: Problem with custom node types
                rhauch

                Actually, I should have said to try this line (with a leading "/" in the attribute value):

                 

                <jcr:nodeTypes mode:resource="/cars.cnd" />

                 

                Feel free to log an issue about the configuration should be more tolerant about a leading slash, too.

                • 5. Re: Problem with custom node types
                  rhauch

                  Ah, ok, I didn't know the .cnd file had to be on the classpath, thanks for the information!

                   

                  That's what we're used to, but it doesn't always makes sense in all applications (especially those that are stand-alone.) Feel free to log an enhancement request to handle files and URLs for CND references in ModeShape configurations. I think we could pretty easily try to load the CND files first as classpath resources, but if that fails we could try to parse into a resolvable URL, and (if that fails) finally look for an existing java.io.File with that path.

                   

                  We should make this as easy as possible, so your feedback is very much appreciated!

                  • 6. Re: Problem with custom node types
                    craigching

                    I think having it on the classpath more fits my actual needs, I was just prototyping and having it on the file system made sense for that, but node types, in my application, are more tightly coupled with my code so the classpath makes more sense.  I'll bear it in mind and log an issue if my needs change.  Thanks!

                    • 7. Re: Problem with custom node types
                      rhauch

                      About the lack of error indication when the resource isn't found by CndNodeTypeReader.read(String), I've opened an issue for that:

                       

                      https://jira.jboss.org/browse/MODE-892

                       

                      This issue has been fixed (on trunk), and will be in the next release (e.g., 2.3).