12 Replies Latest reply on Jan 5, 2010 10:49 AM by John Ament

    XSD for dna namespace in configuration

    John Ament Master

      Just wondering...

       

      The XMLNS for the below tag

       

      <configuration xmlns="http://www.jboss.org/dna/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0">

      Mentions http://www.jboss.org/dna/1.0

      Is there an XSD somewhere?  I'm trying to determine where to add the dataSourceJndiName property in the config file.

        • 1. Re: XSD for dna namespace in configuration
          Brian Carothers Apprentice
          That's the namespace that we use internally for some of our names, particulary those related to internal node types.  I don't think that anyone's put together an XSD yet.  If you've got a problematic config though, just post it and I'll help debug it.
          • 2. Re: XSD for dna namespace in configuration
            John Ament Master

            well, as i mention, I'm looking to configure the JNDI name for a datasource, for the JPA Connector.

             

            I'm also wondering the proper way to configure new node types.

             

            This is for the DNA config file mind you, not anything else.

            • 3. Re: XSD for dna namespace in configuration
              Brian Carothers Apprentice

              Any properties that you set on a dna:source tag have the namespace truncated and the local name of the property treated as the property name on the source.  So doing this:

               

              <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource"

                          dna:dataSourceJndiName="..."
                          />

               

              Ends up calling setDataSourceJndiName("...") on the JpaSource instance for the repository.  As I understand it, you'd get the exact same outcome if you did this:

               

              <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource" jcr:dataSourceJndiName="..."  />

               

              Or this:

               

              <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource" dataSourceJndiName="..."  />

               

              But I have to admit that I never tried it.

               

              As far as loading JCR node types in through a configuration file, I'm not sure.  I tried that two weeks ago and could not get it working, but I came away unsure of whether it was a PEBCAK issue.  I'm sure Randall will chime in with the real answer.

              • 4. Re: XSD for dna namespace in configuration
                Randall Hauch Master

                Any properties that you set on a dna:source tag have the namespace truncated and the local name of the property treated as the property name on the source.  So doing this:

                 

                <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource"

                            dna:dataSourceJndiName="..."
                            />

                 

                Ends up calling setDataSourceJndiName("...") on the JpaSource instance for the repository. 

                Yes, this is correct.

                 

                As I understand it, you'd get the exact same outcome if you did this:

                 

                <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource" jcr:dataSourceJndiName="..."  />

                 

                Or this:

                 

                <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource" dataSourceJndiName="..."  />

                 

                But I have to admit that I never tried it.

                 

                This is correct.  When the XML elements and attributes are loaded/imported into the repository, they keep the namespace.  So while "jcr:dataSourceJndiName" is technically correct, it really is not appropriate to use the "jcr" namespace, as its reserved for use by the specification.

                 

                Now, when the JcrEngine instantiates the objects (such as a RepositorySource implementation), it uses reflection to call the setters on the object.  It is this code that will ignore the namespace, as it basically maps the property's local name to a JavaBean-style setter.  The code first attempts to match the name, and attempts to convert the value to the correct type based upon the type of the one parameter to the setter method.  So if there is a setter for a bean property that takes an "int", the string value stored as content (imported from XML) will be converted to an "integer" using DNA's value factories.

                 

                A single-valued property can be defined in the XML as an attribute or a child element, but multi-valued properties need to be set as multiple child elements (one for each value).  So, the following:

                 

                <dna:source jcr:name="Store" dna:classname="org.jboss.dna.connector.store.jpa.JpaSource" dataSourceJndiName="some:name:in:jndi"  />

                 

                is equivalent to:

                 

                <dna:source jcr:name="Store">

                    <dna:classname>org.jboss.dna.connector.store.jpa.JpaSource</dna:classname>

                    <dataSourceJndiName>some:name:in:jndi</dataSourceJndiName>

                </dna:source>

                Here's a snippet showing a multi-valued property (passed as an array of values to the setter):

                 

                <dna:source jcr:name="Store">

                    <dna:classname>org.jboss.dna.connector.store.jpa.JpaSource</dna:classname>

                    <dataSourceJndiName>some:name:in:jndi</dataSourceJndiName>

                    <multiValuedProperty>value1</multiValuedProperty>

                    <multiValuedProperty>value2</multiValuedProperty>

                    <multiValuedProperty>value3</multiValuedProperty>

                </dna:source>

                 

                So when you're trying to write the XML for the configuration, each setter would map to a property, and each property maps to an XML attribute or child element. For DNA components, use the DNA prefix (or none at all).  If the setter takes a non-string, then simply use the type mapping used by DNA's value factories (which, btw, is the same as defined in the JCR spec) to come up with the string value.

                 

                I agree it would be nice to have a DTD and/or XSD, and we should probably have that since we're far-enough along. They're very useful when you're trying to put together XML files.  It's just that when you get used to JCR and the ability to add to nodes any property and any child node (at least with "nt:unstructured" or similar node types), it's hard to go back to the XML world constrained by a DTD/XSD. :-)

                 

                Hope this helps.

                • 5. Re: XSD for dna namespace in configuration
                  John Ament Master

                  hey great, the site's back up.  any ideas why it keeps going down? :-(

                   

                  so, i think the only questions left are how to call addNodeTypes and registerNamespace via the XML config, rather than programmatically.

                  • 6. Re: XSD for dna namespace in configuration
                    Randall Hauch Master

                    hey great, the site's back up.  any ideas why it keeps going down? :-(

                    Unfortunately, I have no idea.  I do know that they are aware of the situation.

                    so, i think the only questions left are how to call addNodeTypes and registerNamespace via the XML config, rather than programmatically.

                    Registering namespaces and node types is straightforward:

                     

                    <configuration xmlns="http://www.jboss.org/dna/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0">

                      <!--

                      Define the sources for the content. These sources are directly accessible using the DNA-specific Graph API.

                      -->

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

                        ...

                      </dna:sources>

                      <!--

                      Define the JCR repositories

                      -->

                      <dna:repositories>

                        <dna:repository jcr:name="car repository" dna:source="Cars">

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

                            ...

                          </dna:options>

                          <dna:namespaces>

                            <myPrefix dna:uri="http://www.example.com"/>

                            <anotherPrefix dna:uri="http://www.acme.com"/>

                          </dna:namespaces>

                          <dna:nodeTypes>

                            <!--

                            The content here is exactly the same as if the CND file were imported into a repository.

                            -->

                          </dna:nodeTypes>

                        </dna:repository>

                         ...

                      </dna:repositories>

                      ...

                    </configuration>

                    Of course, hand-writing the content of the "dna:nodeTypes" node is probably fairly complex.  What we do is import CND files and place the content under the "dna:nodeTypes" node.  Unfortunately, we don't have a way to specify the CND file by URL (which is probably ideal), nor do we allow you to place the CND file content as CDATA. Both of these could be done, but just aren't implemented yet.

                     

                    Generally what we do is load the JcrConfiguration from a file, but then programmatically register the node types by pointing to the CND files. BTW, when you register node types via CND file, it does automatically register the namespaces used in the CND files.

                    • 7. Re: XSD for dna namespace in configuration
                      John Ament Master

                      Ok, do I need to register all namespaces or only custom?  Are the dna/jcr/nt namespaces already loaded?

                       

                      The only issue I see is that I have to repeat myself if I have multiple repositories.

                      • 8. Re: XSD for dna namespace in configuration
                        Randall Hauch Master

                        Ok, do I need to register all namespaces or only custom?  Are the dna/jcr/nt namespaces already loaded?

                        You do not need to register any of the namespaces defined by JCR (e.g., "jcr", "nt", "mix") or by DNA (e.g., "dna", "dnaint", ...).

                         

                        The only issue I see is that I have to repeat myself if I have multiple repositories.

                         

                        Yes, that is correct. That's why keeping the node types defined in CND files is nice - you do have to re-register the node types for each repository, but you can just point to the same CND file(s).

                         

                        I agree it would be nice to have a way to define defaults for all repositories. I actually had something like that at one put, but took it out because I kept burning myself by forgetting about the defaults and wondering why certain things were being loaded that I didn't configure.

                        • 9. Re: XSD for dna namespace in configuration
                          John Ament Master

                          actually, i think repository defaults would be a bad idea.  if two repositories are so similar, they should probably be the same repo or use the same source.

                          • 10. Re: XSD for dna namespace in configuration
                            Randall Hauch Master

                            actually, i think repository defaults would be a bad idea.  if two repositories are so similar, they should probably be the same repo or use the same source.

                            Thanks for the feedback.  It's good to hear we made the right decision. Plus, I think it helps keep things clear.

                             

                            As far as repositories using the same source, remember that the repositories are responsible for knowing the node types that apply to its content, so there will be some duplication here.  (The reason why this is the case may be less obvious for the case where a repository uses a single non-federating source. The federation case is more complicated: if the sources stored the node types, then federating multiple sources could mean a clash of node types, so our approach has been to simply make it the repository's responsibility to provide a consistent set of node types that work for all content.)

                             

                            (For readers' benefit, we started another thread on the topic of using the same source in multiple repository instances: http://community.jboss.org/message/518345#518345)

                            • 11. Re: XSD for dna namespace in configuration
                              Randall Hauch Master

                              I should also mention that we expect to be able to easily configure all of the processes that make up a cluster. We're trying to make it so that as long as each JcrEngine is configured in the same way (using sources that are configured the same, using the same node types and namespaces, and soon using the same JGroups channels), each JcrEngine will work together, regardless of the number of other JcrEngines in the cluster.

                               

                              While it certainly is possible for each JcrEngine to be configured by reading local files, it is probably easier to have each JcrEngine be configured using a central configuration repository. Simply create a repository that will be accessible by sources in multiple processes (e.g., using connectors for Infinispan, JPA, JBoss Cache, etc.), and populate it by with the configuration information. Then, create a JcrConfiguration by pointing it to that repository source and use the JcrConfiguration to load a configuration file, register node types, and perform all other configuration operations. Just remember to call 'save()' when you're finished.  At this point, you have a persistent repository with your configuration information, and you can create the JcrConfiguration in each of your processes by pointing to this persistent configuration repository and just building the engine.  Of course, updating the configuration information is easy, since any changes made by these (or other JcrConfiguration) objects will be reflected in the persistent repository.

                               

                              We think this is pretty slick. And the reason why this works is because JcrConfiguration always stores its information in a repository source, and JcrEngine always reads the configuration information from a repository source. (There is no object model for the configuration implemented by Java classes - it's just content.)  By default, JcrConfiguration uses a transient in-memory source, but it is just as easy to point it to a shared, persistent repository using a connector.

                               

                              For example, you could write an administration-like application that simply populates (or updates) a shared configuration repository, and then your application could just load its configuration from that shared configuration repository. To do this, the admin app would set up a JcrConfiguration to use the central database (via a manually-instantiated JPA connector instance configured with the JDBC connection information), use the JcrConfiguration methods to define the configuration, and then call 'save()'.  The application then simply has to create its JcrConfiguration and point it to the same central database (again, using the JPA connector), and can immediately build the JcrEngine instance.

                               

                              And to get fancy, it's possible to define and store multiple independent repository configurations within the same source - in effect, to have an "enterprise configuration repository".  Simply be sure to use the JcrConfiguration.load(RepositorySource,String,String) method, where the last parameter specifies the path to the top of the configuration graph that you want to use.  See the JavaDoc for more details.

                              • 12. Re: XSD for dna namespace in configuration
                                John Ament Master
                                To be perfectly honest, losing the ability to read the config from a file would be a big let down for me.  If you start near the top, at the deployment level, I think it would be necessary to assume that multiple deployments (different pieces of hardware, or different virtual machines) would rely on the fact that it has been deployed correctly, the same way.  I don't consider the DNA config to be a config file, more like a deployment descriptor - these are the repos and the sources that must be deployed.  I'm honestly looking to bank on this idea for CDI integration.