3 Replies Latest reply on Jul 26, 2011 6:31 PM by Randall Hauch

    Creating custom NodeTypes not persisting

    Hammad Afridi Newbie

      Hi there,

      I am using modeshape 2.6.0 beta and trying to create a new NodeType programatically. Following is java and configuration.When I try a new nodetype and then try to fetch it it works fine.But if I try only to fetch I am getting NoSuchNodeTypeException.

       

      Please can you help me out what I am missing in the following code:

       

      package com.olive.jcr.api;

       

       

      import java.io.IOException;

       

       

      import javax.jcr.PropertyType;

      import javax.jcr.Repository;

      import javax.jcr.RepositoryException;

      import javax.jcr.Session;

      import javax.jcr.Workspace;

      import javax.jcr.nodetype.NodeType;

      import javax.jcr.nodetype.NodeTypeManager;

      import javax.jcr.nodetype.NodeTypeTemplate;

      import javax.jcr.nodetype.PropertyDefinitionTemplate;

       

       

      import org.modeshape.common.collection.Problem;

      import org.modeshape.graph.Graph;

      import org.modeshape.jcr.JcrConfiguration;

      import org.modeshape.jcr.JcrEngine;

      import org.xml.sax.SAXException;

       

       

      public class JCRTest {

      private static JcrEngine engine;

       

       

                public static void main(String[] args){

              if (engine != null) return; // already started

       

       

                          try {

       

                                    JcrConfiguration config = new JcrConfiguration().loadFrom("src/main/java/com/olive/jcr/api/jpaConfig.xml");

       

                        engine = config.build();

                        engine.start();

       

       

       

                        if (engine.getProblems().hasProblems()) {

                            for (Problem problem : engine.getProblems()) {

                                System.err.println(problem.getMessageString());

                            }

                            throw new RuntimeException("Could not start due to problems");

                        }

       

       

                        Repository repository = (Repository) engine.getRepository("olive repository");

                        Session session = repository.login();  // Logs in with a guest session - works by default.

       

       

                        Workspace workspace = session.getWorkspace();

                        //createNodeType(workspace);

                        getNodeType(workspace);

                        session.save();

                          } catch (IOException e) {

                                              System.out.print("exception"+e);

                          } catch (SAXException e) {

                                    // TODO Auto-generated catch block

                                    System.out.print("exception"+e);                    } catch (RepositoryException e) {

                                    // TODO Auto-generated catch block

                                              System.out.print("exception"+e);

                          }

       

       

                }

       

                /**

                 * Example to add nodetype

                 */

                private static void getNodeType(Workspace workspace){

                          NodeTypeManager mgr;

                          try {

                                    mgr = workspace.getNodeTypeManager();

                                    mgr.getAllNodeTypes();

                                    NodeType nodeType = mgr.getNodeType("StandardArticle");

                                    System.out.println(nodeType.getName());

       

                          } catch (RepositoryException e) {

                                    // TODO Auto-generated catch block

                                    e.printStackTrace();

                          }

                }

       

                /**

                 * Example to create a node type Article

                 * @param workspace

                 */

                //TODO method to create node type

                private static void createNodeType(Workspace workspace){

                          // Obtain the ModeShape-specific node type manager ...

                          NodeTypeManager nodeTypeManager;

                          try {

                                    nodeTypeManager = workspace.getNodeTypeManager();

       

       

                          // Declare a mixin node type named "searchable" (with no namespace)

                          NodeTypeTemplate nodeType = nodeTypeManager.createNodeTypeTemplate();

                          nodeType.setName("StandardArticle");

                          //nodeType.setMixin(true);

       

       

                          // Add a property named "headline"

                          PropertyDefinitionTemplate headline = nodeTypeManager.createPropertyDefinitionTemplate();

                          headline.setName("headline");

                          headline.setMandatory(true);

                          headline.setRequiredType(PropertyType.STRING);

                          nodeType.getPropertyDefinitionTemplates().add(headline);

       

       

                          // Add a property named "teaser"

                          PropertyDefinitionTemplate teaser = nodeTypeManager.createPropertyDefinitionTemplate();

                          teaser.setName("teaser");

                          teaser.setMandatory(true);

                          teaser.setRequiredType(PropertyType.STRING);

                          nodeType.getPropertyDefinitionTemplates().add(teaser);

       

       

                          // Add a property named "body"

                          PropertyDefinitionTemplate body = nodeTypeManager.createPropertyDefinitionTemplate();

                          body.setName("body");

                          body.setMandatory(true);

                          body.setRequiredType(PropertyType.STRING);

       

       

                          // Register the custom node type

                          NodeType createdNodeType = nodeTypeManager.registerNodeType(nodeType,true);

                          System.out.println("node type name:"+createdNodeType.getName());

                          } catch (RepositoryException e) {

                                    // TODO Auto-generated catch block

                                    e.printStackTrace();

                          }

       

       

                }

       

      }

       

       

       

      -------------------------------------------------------------------------------------------------------Configuration

      <?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">

       

       

          <!--

          Define the sources for the content.  These sources are directly accessible using the

          ModeShape-specific Graph API.  In fact, this is how the ModeShape JCR implementation works.  You

          can think of these as being similar to JDBC' DataSource objects, except that they expose

          graph content via the Graph API instead of records via SQL or JDBC.

          -->

       

       

        <mode:repositories>

          <mode:repository jcr:name="olive repository" mode:source="applicationStore">

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

              <!-- Explicitly specify the "system" workspace in the "Cars" source. -->

              <systemSourceName jcr:primaryType="mode:option" mode:value="system@applicationStore"/>

            </mode:options>     

          </mode:repository>

        </mode:repositories>

       

       

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

             <!--

              The 'JPA Store' repository is an JPA source with a single default workspace (though

              others could be created, too).

              -->

          <!-- One source for the "/jcr:system" content ... -->

       

       

              <mode:source jcr:name="applicationStore" mode:classname="org.modeshape.connector.store.jpa.JpaSource"

                          mode:description="The database store for our content"

                                mode:dialect="org.hibernate.dialect.MySQLDialect"

                          mode:driverClassName="com.mysql.jdbc.Driver"

                          mode:url="jdbc:mysql://localhost:3306/cms"

                          mode:username="root"

                          mode:password="root"

                          mode:defaultWorkspaceName="workspace1"

                          mode:autoGenerateSchema="disable"/>

             <mode:predefinedWorkspaceNames>workspace1</mode:predefinedWorkspaceNames>

             <mode:predefinedWorkspaceNames>system</mode:predefinedWorkspaceNames>   

       

                   </mode:sources>

       

       

          <!-- MIME type detectors and JCR repositories would be defined below -->

      </configuration>

        • 1. Re: Creating custom NodeTypes not persisting
          Randall Hauch Master

          I tried running ModeShape with your configuration (or at least something very close to it), and I ended up modifying your code just a bit (see my modifications here). BTW, any changes using the Workspace (e.g., registering node types) happen immediately and do not require saving the session. Also, be sure to shut down the engine - otherwise the thread pools created by the engine won't stop and the VM won't terminate.

           

          A couple of things:

           

          First, the 'autoGenerateSchema' value of 'update' may very well modify (e.g., update) the schema, dropping the tables. When using HSQLDB, this is exactly what happened with my tests. For your testing purposes, the easiest thing is to set the 'autoGenerateSchema' value to 'create' for only the first run and then 'update' (or 'disable') for all subsequent tests when you want the database to exist.

           

          The 'autoGenerateSchema' is actually something that can be very easily misused. For all production purposes, we advocate using our DDL generation tool to produce DDL for your DBMS, having a good DBA optimize that DDL for your DBMS installation and environment, manually configuring the database, and then set the 'autoGenerateSchema' property to 'disable'. This is really the only good way to set up the database.

           

          Secondly, once I did this I periodically ran into MODE-1190. Now that I have an environment in which this bug is occurring, I can work out a fix for that issue and get it committed into our 'master' branch. I'm anticipating releasing Beta2 this week or early next, but if you didn't want to wait you could also get the latest code and build locally once the fix is committed.

           

          Third, as we discussed on IRC, you could try using ModeShape 2.5.0.Final. MODE-1190 is clearly a regression, but I'm not sure when it was introduced. Give it a whirl and let us know.

           

          I hope this helps, and thanks for working with us!

           

          Best regards,

           

          Randall

          • 2. Re: Creating custom NodeTypes not persisting
            Hammad Afridi Newbie

            Hi Randall,

            Thank you so very much for your help.

             

            I have tried version 2.5.0 with the code and the configuration you have provided. In your code the engine starts, node type is created and then getting the node type works fine but when again if I to start the engine, get the node type and change the config to mode:autoGenerateSchema="disable" I am getting the following error that you have also mentioned above MODE-1190 :

             

            ERROR org.modeshape.jcr.RepositoryNodeTypeManager - Node types were read from the system content, and appear to be inconsistent or invalid: org.modeshape.jcr.nodetype.InvalidNodeTypeDefinitionException: Supertype 'nt:base' from type 'StandardArticle' does not exist

             

            Is this something wrong with 2.5.0 version as well ? Looks like there is some issue with the 2.5.0 as well. Which version of modeshape is stable enough to be used?

             

            If I try creating nodetype using CND file by reading them programitically, is that going to work?

             

             

            Btw, 2.5.0 download link is broken

             

            Thanks,

            Hammad.

            • 3. Re: Creating custom NodeTypes not persisting
              Randall Hauch Master

              Hammad Afridi wrote:

               

              Hi Randall,

              Thank you so very much for your help.

               

              I have tried version 2.5.0 with the code and the configuration you have provided. In your code the engine starts, node type is created and then getting the node type works fine but when again if I to start the engine, get the node type and change the config to mode:autoGenerateSchema="disable" I am getting the following error that you have also mentioned above MODE-1190 :

               

              ERROR org.modeshape.jcr.RepositoryNodeTypeManager - Node types were read from the system content, and appear to be inconsistent or invalid: org.modeshape.jcr.nodetype.InvalidNodeTypeDefinitionException: Supertype 'nt:base' from type 'StandardArticle' does not exist

               

              Is this something wrong with 2.5.0 version as well ? Looks like there is some issue with the 2.5.0 as well.

              Yes, apparently the issue is also in 2.5.0.Final.

               

              As a workaround, I would recommend defining your node type definitions in a CND file and referencing the CND file within your ModeShape configuration file (see the "jcr:nodeTypes" element in the first configuration example file in Chapter 6.1.1 of the Reference Guide). This is safe to do even on restarts, doesn't take much time at all, and is actually how most users do this in ModeShape (which I think is why MODE-1190 hasn't been a big problem so far).

               

              If you need to programmatically define your node type definitions (because they change or depend on data), then go ahead and re-register them even upon restarts. Again, it is safe to re-register them and doesn't take much time at all.

               

              I already have a local fix for MODE-1190, but I'm working on another issue at the moment. Regardless, it will definitely make it into the upcoming 2.6.0.Beta2 release.

               

              Thanks for your patience and help in identifying this issue.

               

              Btw, 2.5.0 download link is broken

               

              Grrr... Thanks, this is now fixed.