Announcement Announcement Module
Collapse

Spring Modules forum decommissioned in favor of Spring Extensions

As the Spring Modules project has been replaced by the Spring Extensions (http://www.springsource.org/extensions) project, this forum has been decommissioned in favour of Spring Extensions one at:
http://forum.springsource.org/forumdisplay.php?f=44

Please see the Spring Extensions home page for a complete list of current projects in Java, .NET and ActionScript. You can also propose one if you want.

Cheers,
Costin Leau
SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
http://twitter.com/costinl
See more
See less
JackRabbit and namespaces Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JackRabbit and namespaces

    I try to register a namespace, but I got and error when running the application a second time (name space already exists).

    I have seen a closed issue on jira: http://opensource.atlassian.com/proj...browse/MOD-102

    here is my code:
    Code:
    <bean id="jcrSessionFactory" class="org.springmodules.jcr.JcrSessionFactory">
      ...
     <property name="forceNamespacesRegistration" value="false"/>
     <property name="keepNamespaces" value="false"/>
     <property name="namespaces">
         <props>
            <prop key="foo">http://www.foobar.com/foo</prop>	
         </props>
      </property>
    </bean>
    I have tested with different combination for the two properties, but I
    didn't manage to get it work.
    when forceNamespacesRegistration is true I got 'unregistering namespaces is not supported.'

  • #2
    Jackrabbit doesn't fully support namespace registrations (hence, that's why the exception when you try to unregister). When the application runs the second time, the already registered namespace is found but since unregistration is not supported, the namespace cannot be registered the second time (note that JcrSF doesn't check the namespace values - it delegates all comparisons to the underlying JCR implementation).

    I would say that at this point, it is not possible to use namespaces with Jackrabbit in an easy fashion.

    Comment


    • #3
      Is this solved yet?

      Anyone knows whether this is solved yet in Jackrabbit v.1.1.1 & Spring-Modules 0.7?
      Wolf

      Comment


      • #4
        The issue will be there until the jcr provider actually allows re-write of the namespace. If you look at the sources, SM calls the generic API. If the implementation supports it, everything works, if not you'll get the exception (which is thrown by the implementation itself).

        Comment


        • #5
          Possible quick fix for this

          The issue will be there until the jcr provider actually allows re-write of the namespace. If you look at the sources, SM calls the generic API. If the implementation supports it, everything works, if not you'll get the exception (which is thrown by the implementation itself).
          croudet,
          It is possible to subclass the JcrSessionFactory, and simlply rewrite registerNamespaces such then it checks an "ignoreRegisteredNamespaces" flag. If the flag is set to true, then already registered namespaces are ignored iff the already registered namespace matches the new one (both prefix and uri) -- otherwise throw a namespace exception. I realize that this is not an ideal solution, but it can get namespaces useable with very few changes.

          Costin,
          I am not sure you want such a hack checked in, but you could build it such that the JcrSessionFactory's registerNamespaces() used the code that checked ignoreRegisteredNamespaces. the ignoreRegisteredNamespaces could be protected, then create a JackrabbitJcrSessionFactory would just set the flag to true on construction.

          This is what I put together for this. It could definitely use improvement, but it works:

          Code:
          package org.springmodules.jcr.jackrabbit.ext;
          
          import java.util.Arrays;
          import java.util.HashMap;
          import java.util.Iterator;
          import java.util.Map;
          
          import javax.jcr.NamespaceException;
          import javax.jcr.NamespaceRegistry;
          import javax.jcr.RepositoryException;
          
          import org.apache.commons.logging.Log;
          import org.apache.commons.logging.LogFactory;
          import org.springmodules.jcr.JcrSessionFactory;
          
          public class JackrabbitJcrSessionFactory extends JcrSessionFactory {
          
          	private static final Log log = LogFactory.getLog(JcrSessionFactory.class);
          	private boolean ignoreRegisteredNamespaces = true;
          	/**
          	 * Register the namespaces.
          	 * 
          	 * @param session
          	 * @throws RepositoryException
          	 */
          	protected void registerNamespaces() throws RepositoryException {
          
          		// this is a hack, because the superclass declares overwrittenNamespaces private, without accessors
          		Map overwrittenNamespaces = new HashMap();
          		
          		Map ignoredNamespaces = new HashMap();
          		if (getNamespaces() == null || getNamespaces().isEmpty())
          			return;
          
          		if (log.isDebugEnabled())
          			log.debug("registering custom namespaces " + getNamespaces());
          
          		NamespaceRegistry registry = getSession().getWorkspace()
          				.getNamespaceRegistry();
          
          		// unregister namespaces if told so
          		if (isForceNamespacesRegistration()) {
          
          			// save the old namespace only if it makes sense
          			if (!isKeepNamespaces())
          				overwrittenNamespaces = new HashMap(getNamespaces().size());
          			// do the lookup, so we avoid exceptions
          			String[] prefixes = registry.getPrefixes();
          			// sort the array
          			Arrays.sort(prefixes);
          
          			// search occurences
          			for (Iterator iter = getNamespaces().keySet().iterator(); iter.hasNext();) {
          				String prefix = (String) iter.next();
          				int position = Arrays.binarySearch(prefixes, prefix);
          				if (position >= 0) {
          					if (log.isDebugEnabled()) {
          						log.debug("prefix " + prefix
          								+ " was already registered; unregistering it");
          					}
          					if (!isKeepNamespaces()) {
          						// save old namespace
          						overwrittenNamespaces.put(prefix, registry
          								.getURI(prefix));
          					}
          					if (!ignoreRegisteredNamespaces) {
          						registry.unregisterNamespace(prefix);
          					} else {
          						String oldUri = registry.getURI(prefix);
          						String newUri = getNamespaces().getProperty(prefix);
          						if (!oldUri.equals(newUri)) {
          							throw new NamespaceException("prefix " + prefix + " was registered with uri " + oldUri + 
          									", but is trying to be reregistered with " + newUri);
          						}
          						ignoredNamespaces.put(prefix, oldUri);
          					}
          					// postpone registration for later
          				}
          			}
          		}
          
          		// do the registration
          		for (Iterator iter = getNamespaces().entrySet().iterator(); iter.hasNext();) {
          			Map.Entry namespace = (Map.Entry) iter.next();
          			if (!ignoredNamespaces.containsKey(namespace.getKey())) {
          				registry.registerNamespace((String) namespace.getKey(),
          						(String) namespace.getValue());
          			}
          		}
          	}
          	public boolean isIgnoreRegisteredNamespaces() {
          		return ignoreRegisteredNamespaces;
          	}
          	public void setIgnoreRegisteredNamespaces(boolean ignoreRegisteredNamespaces) {
          		this.ignoreRegisteredNamespaces = ignoreRegisteredNamespaces;
          	}
          	
          	
          }
          Just a thought.
          DW
          Last edited by dannwebster; Feb 13th, 2007, 12:50 PM.

          Comment


          • #6
            I'll probably add it in 0.8 since at least for the near future this feature will still be n/a in Jackrabbit and might cause some grief.
            It's a pity that after all this time, one can't get at least two, stable, fully featured, free to use, JCR implementations.

            Comment


            • #7
              +1. It's a basic feature, if not a cornerstone of a JCR and look at what the RI makes of it...
              It also suggests not too many people are using a CR otherwise it would have been fixed a long time ago.

              Btw what is the meaning/effect of these:
              <property name="forceNamespacesRegistration" value="false"/>
              <property name="keepNamespaces" value="false"/>

              The Javadoc is left blanc for these...

              & Most importantly:
              How does one get to register the nodes that come with these namespaces?
              Does it suffice to place the CND-file in the /respository/namepsaces directory, or should it be in the specific WS directory /workspaces/myWS/myProjectNamespaces/
              or....?
              Or do they really have to be digged up from where ever you put the cnd file and are these 2 locations mere preferred locations?

              + How best to do this with Spring? I'm having a "best place-when best" problem with this. Apparently a NS is registered from the WS, which you get from the Session. I find this strange. I rather see it as tied to a Repository. So I would have expected it in the bean for either repository, or sessionFactory. (you can declare it here, but cf. earlier question: if you need to dig the cnd file up where your custom nodes are defined, where and when do you do this best?)

              Last but not least: Costin, I read the 0.8 version of the Spring-modules were originally scheduled for February :-) I think you're in the best seat to unveil us how big the lag is? :-) (not meant to keep you even more awake - just for my info)

              Sorry or all the questions... (I hope everyone has these issues)
              Wolf

              Comment


              • #8
                I plan to update the Jackrabbit documentation also... so many ideas, so little time.

                As for registering the nodes, unfortunately I at least, couldn't find a nice, portable way of doing this across several implementations. In fact, besides Jackrabbit there isn't any JCR implementation out there which can be used - Jeceira seems to have died.
                The relationship between Repository/Session/Workspace is a bit awkward, I give you that. Please raise an issue on JIRA so I can take a look at this issue for 0.8.

                And speaking of, 0.8 is scheduled to be release this week unless something major occurs. I'd like to make the release right after Spring 2.0.3 gets released so we can make sure the modules are compatible.

                Comment


                • #9
                  Re:

                  I plan to update the Jackrabbit documentation also... so many ideas, so little time.
                  -- Make sure you write them down then... :-) (So that WHEN you have a sec, writer's block can't get the better of you!)

                  As for registering the nodes, unfortunately I at least, couldn't find a nice, portable way of doing this across several implementations. In fact, besides Jackrabbit there isn't any JCR implementation out there which can be used - Jeceira seems to have died.

                  -- Indeed. As also other Impl classes are tied to JR, and this remains the RI, and as also a lot other products are build on top of JR, I believe it makes much sense to solve this for JR, paving the way! It would be awesome to be able to add the CND file right in the Spring bean of the SessionFactory. You think this is possible? This seems to be the best place as also there the Namespaces are declared. (in fact doing both would bbe redundant as teh NSs are also declared in the top part of the CND file so just pointing to the CND file for registring the custom nodes should do)

                  The relationship between Repository/Session/Workspace is a bit awkward, I give you that. Please raise an issue on JIRA so I can take a look at this issue for 0.8.
                  -- What do you want me to put in it? What I typed in my previous paragraph just on top? (about registring the Custom Node Type Defs?)

                  And speaking of, 0.8 is scheduled to be release this week unless something major occurs. I'd like to make the release right after Spring 2.0.3 gets released so we can make sure the modules are compatible.

                  -- OK, I'll hurry with the JIRA issue then! :-) (just OK the above question)

                  Wolf

                  Comment


                  • #10
                    -- What do you want me to put in it? What I typed in my previous paragraph just on top? (about registring the Custom Node Type Defs?)
                    Yes, you can copy paste the content of the this conversation or just a conclusion. Basically, I want a reminder so I don't lose track of the problem.

                    Comment


                    • #11
                      JR &amp; Namespaces

                      Costin,
                      I had also posted the question to the JR mailing list. Thi sis the reply I got there, from Tobias ([email protected])
                      __________
                      "Namespaces are fully supported by jackrabbit since 1.0. and the
                      registration works exactly as specified in jsr170 (which is a bit
                      troublesome).

                      in your application you probably have a 'getRepositorySession' call,
                      and there i would setup/check the namespaces for your application, eg:

                      1. check if your namespace is already registered
                      2. if not, do so.
                      3. setup the namespace mapping for your session and application.

                      example:

                      try {
                      s.getNamespaceURI("http://your.com/ns/1");
                      } catch (RepositoryException e) {
                      // register namespace
                      s.getWorkspace().getNamespaceRegistry().registerNa mespace(
                      "myapp", "http://your.com/ns/1");
                      }
                      s.setNamespacePrefix("myapp", "http://your.com/ns/1");
                      [....]
                      s.getRootNode().getNode("myapp:someNode");
                      "
                      _____________
                      It seems a bit inefficient having to check this at every getSession() call; it seems to make more sense having a kinda Session init() method - which leads me to my earlier conclusion; SessionFactory seems to be the best place to do this.
                      Hope it helps,
                      Wolf

                      Comment


                      • #12
                        JIRA issue created

                        Ref: MOD-303

                        Wolf

                        Comment


                        • #13
                          I don't want to argue with the Day guys since they are the main authors behind JR but remapping an unregistration of the namespaces is not supported. Here is a snippet from Jackrabbit 1.2.2 (org.apache.jackrabbit.core.NamespaceRegistryImpl) :

                          Code:
                          /**
                               * {@inheritDoc}
                               */
                              public void unregisterNamespace(String prefix)
                                      throws NamespaceException, UnsupportedRepositoryOperationException,
                                      AccessDeniedException, RepositoryException {
                          ...
                                  /**
                                   * as we can't guarantee that there are no references to the specified
                                   * namespace (in names of nodes/properties/node types etc.) we simply
                                   * don't allow it.
                                   */
                                  throw new NamespaceException("unregistering namespaces is not supported.");

                          The same goes for remapping:
                          Code:
                           public void registerNamespace(String prefix, String uri) {
                          ...
                          
                               if (prefixToURI.containsKey(prefix)) {
                                      /**
                                       * prevent remapping of existing prefixes because this would in effect
                                       * remove the previously assigned namespace;
                                       * as we can't guarantee that there are no references to this namespace
                                       * (in names of nodes/properties/node types etc.) we simply don't allow it.
                                       */
                                      throw new NamespaceException("failed to register namespace "
                                              + prefix + " -> " + uri
                                              + ": remapping existing prefixes is not supported.");
                                  }
                          Maybe I'm missing something but the registration should be done through the Namespace registry which, as pointed about throws exceptions.

                          I'll take a look at the email but my understanding is that new registrations are allowed but modifications/removal of existing namespaces is forbidden.

                          Comment


                          • #14
                            Re: JC tampers with JSR-170 spec?

                            Hi Costin,
                            I posted yoru finding to the JC list (rest assured, to spare you the FUD, I stripped yr name :-)
                            I will post their feedback back here.

                            Wolf

                            Comment


                            • #15
                              any resolution

                              Has there been any resolution to this issue or do I have to implement my own JackrabbitSessionFactory? It seems like an important issue to resolve. Ideally I would either like to have a parameter that specifies to re-register the node types or a way to just ignore the namespace if it already exists. Anybody have any suggestions or fixes to this issue? I just want to be able to have the nodetypes registered at startup through spring w/o throwing an exception if the namespace already exists. Any help is appreciated.

                              Comment

                              Working...
                              X