jackrabbit-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Peter Darton" <pet...@intrinsica.co.uk>
Subject JCR, RMI & WebDAV - draft HOWTO - revison 0.2
Date Fri, 09 Dec 2005 16:20:34 GMT
Ok, my previous post on this subject triggered a number of responses,
including a fair few corrections.
So, in order to try and salvage what's left of my dignity, I thought I
should attempt to collate all those corrections into one place so we end
up with a single "correct" document instead of a long thread of
I even managed to get a few more bits running, reducing my "whinge list"
a lot :-)

Obviously, if there are further errors in this "corrected" message,
please say so.

"HOWTO get JCR-RMI-WebDAV working" - version 0.2
Note: This was "current" as of commit#355090.

This takes you through getting a JCR up and running, making it remotely
accessible via RMI, and by WebDAV, using the Jackrabbit core code, the
jcr-rmi contrib code, and the jcr-server contrib code.

The following instructions are based on the assumption that you're using
Linux, and you've got the "svn" command-line command installed, and
you've got Tomcat running somewhere, but you don't have anything in the
way of existing installed Java development stuff.

1) Java:
 You'll need a JDK.  Personally, I downloaded Java 1.5.0_05 by
downloading the "Netbeans 4.1 with Java 1.5" bundle, HOWEVER you'll run
into fewer issues if you limit yourself to just Java 1.4.2.
 I installed the JDK into /opt/jdk1.5.0_05/  and Netbeans into
 - Easy mistake: You're going to need Tomcat later, but if you're
intending to use an existing Tomcat installation that uses Java 1.4.x
then you MUST NOT use Java 1.5.x to build everything - if you use Java
1.5 to build things, they'll only be usable on a Java 1.5 target, hence
you'll have to ensure your Tomcat uses 1.5 as well.
 - Easy mistake#2: The assumption that the latest Java is the best to go
for is an easy assumption to make, but not always correct.  If you
really want to use Generics in your code (and any other Java 5
features), by all means use Java 1.5.x.  If you just want to take the
easy option, use Java 1.4.2, as using Java 5 with this code introduces
some avoidable complications.

2) Maven:
 Download Maven 1.  Note: That's "Maven 1", not 2.
 Unpack it somewhere.
 (I unpacked to /opt/maven-1.0.2/)
 - Easy mistake: The Maven website has moved onto Maven 2.  Maven 2 is
NOT what you want.  You'll have to locate the link to Maven 1 and
download that instead.  You can guess what I did first time around...

If you're using Java 5 (you can skip this step if you're using Java
3) Download Xalan:
 If you're using Java 1.5.x, there's a build bug you'll need to work
around - under Java 5 Jackrabbit needs a couple of JAR files that the
build doesn't get automatically:
 Download Xalan from http://xml.apache.org/xalan-j/downloads.html
 Unpack it somewhere nearby to Maven (I unpacked to /opt/xalan-j_2_7_0/)

If you're using Java 5 (you can skip this step if you're using Java
4) Workaround build bug:
 cd to maven's "lib/endorsed" directory
 create symbolic links to (or copy) xalan.jar and serializer.jar (which
are in the xalan directory).
 I did
   ln -s ../../../xalan-j_2_7_0/serializer.jar
   ln -s ../../../xalan-j_2_7_0/xalan.jar

5) Download & Build Jackrabbit:
 cd to whereever you want a jackrabbit directory created, then do
 svn co http://svn.apache.org/repos/asf/incubator/jackrabbit/trunk
 (that'll download the jackrabbit source)
 cd jackrabbit/jackrabbit
 export PATH=/opt/maven-1.0.2/bin:${PATH}
 export JAVA_HOME=/opt/jdk1.5.0_05
 maven clean jar:install dist copy_deps
This will take some time, firstly because it'll download some other jar
files that are needed, and secondly because the unit-tests aren't
instant (you should have time to make tea/coffee - it took 15 minutes on
my setup).
 cd ../..
 - Easy mistake: Just running maven with no arguments will build the jar
file, but maven doesn't then make the jar file available to other maven
builds, resulting in the error "unsatisfied dependency:
jackrabbit-commons-1.0-SNAPSHOT.jar" on those other builds.  You need to
specify "jar:install" to 'install' the jar file into maven's stash of
jar files so that when we build other projects, they can find the jar
file we've just built.
 - Note: Although not necessary to run WebDAV, I found it useful to
build "dist" and "copy_deps" as well.  The first creates the JavaDocs
and annotated source code, the second copies all the libraries (jar
files) that Jackrabbit needs into the target/lib subdirectory - useful
when using Jackrabbit directly.

6) Build jackrabbit RMI:
 cd jackrabbit/contrib/jcr-rmi
 maven clean jar:install dist
 cd ../../..
 - Easy mistake: Just running maven with no arguments builds nothing at
all, but builds it successfully.  You need to tell it to build "jar:jar"
to build the jar file, and "jar:install" to make it available to the
jcr-server build.  Fortunately "jar:install" triggers a "jar:jar" so we
only need to tell it to do the install.
 - Note: Although not necessary to run WebDAV, I found it useful to
build "dist" as well (copy-deps isn't available on this project), as the
JavaDocs are the only documentation you'll get.

7) Build jackrabbit WebDAV:
 cd jackrabbit/contrib/jcr-server
 maven clean jar:install dist
 cd ../../..
 - Note: Although not necessary to run WebDAV, I found it useful to
build "dist" as well (copy-deps isn't available on this project), as the
JavaDocs are the only documentation you'll get.

8) Installing WebDAV on Tomcat
 I'm going to assume you've already got Apache Tomcat up and running.
Big assumption, I know, but there are existing tutorials for that
(google is your friend).
 I'm going to assume that Tomcat is running on your localhost on port
 Goto http://localhost:8080/manager/html/list (Note: If you're using a
web-browser with a braindead proxy facility, you may need to add
"localhost" to the list of 'do not proxy this' addresses)
 Scroll down to the bottom to find "Select WAR file to upload" and click
"Browse".  Locate, in jackrabbit/contrib/jcr-server/webapp/target, the
file "jackrabbit-server.war".
 Press "deploy".

 Now, if you're using Java 5, that build bug (see steps 3 & 4) will
strike again and the application will fail to start properly with the
following error:
SEVERE: StandardWrapper.Throwable
javax.xml.transform.TransformerFactoryConfigurationError: Provider
org.apache.xalan.processor.TransformerFactoryImpl not found
So now scroll up to the top of page
http://localhost:8080/manager/html/list, find "jackrabbit-server" and
click "stop" (NOT undeploy!).
 Now copy xalan.jar and serializer.jar into tomcat's subdirectory
 Note: It only seems to blow up like this when attempting to create a
fresh repository for the first time - as long as you leave the
repository directory present, you won't hit this issue a second time,
even if you accidentally redeploy the WAR file (and thus remove these
two JAR files).
 Note2: As an alternative to putting the JAR files into
jackrabbit-server's lib directory, you could just dump them in one of
Tomcat's shared areas.  This has the advantage & disadvantage that they
don't get deleted when you "undeploy" the webapp, and they'll also be
available to every other webapp you've got.  For trivial demo purposes
it probably doesn't make much difference though.

Now, if you don't have a login security policy already defined for your
tomcat environment, you're going to have to tell the servlet what to use
instead, which means the SimpleLoginModule, which doesn't actually do
any authentication (it's on the "to do" list) but will let you in
So you'll need to edit
.../webapps/jackrabbit-server/WEB_INF/repository/repository.xml, find
the AccessManager section and appended (immediately after

  <param name="anonymousId" value="anonymous" />

I'm reliably informed that Jackrabbit can use any JAAS LoginModule you
like (and investigating this is next on my list of things to do),
however I don't understand how to drive this functionality at present
and this "SimpleLoginModule" hack will get you going to begin with.
Just be aware that SimpleLoginModule is totally insecure - no validation
takes place.

 Once that's done, you can go back to
http://localhost:8080/manager/html/list and press "start" on
"jackrabbit-server" again.
 The servlet should start up with few complaints - there should be no

 - Easy mistake: Beware of using the browser "back" and "forward"
buttons on the .../manager/... Tomcat pages - the browser is unlikely to
warn you about needing to re-send form data, but it will still cause
Tomcat to perform whatever operation you used to take you to that page,
which can be quite embarrasing if you started by "undeploying" an old
copy of "jackrabbit-server", as it'll "undeploy" every time you click
"back" to that page.
 - Easy mistake#2: Undeploying the WAR will destroy the alterations
you've just made.  Re-deploying will over-write any existing files
resulting in data-loss.
 - Easy mistake#3: Re-trying to start the web application doesn't
necessarily cope with the mess previous attempts may have left.  If it
failed to start up due to the missing xalan libraries, it leaves the
filesystem in a mess that it can't cope with, meaning that even if you
_do_ fix the missing jar files, it'll still fail to start, throwing up
the following error: 
SEVERE: Servlet /jackrabbit-server threw load() exception
javax.servlet.ServletException: Error while creating repository
This seems to be because it creates part of the directory hierarchy it
needs before hitting the exception, leaves those directories behind when
it throws the exception, but subsequent runs don't find a repository,
try to create a new one but fail because there's part of an existing
directory hierarchy in the way...
So you'll need to locate where it's put the partially-initialised
repository directory (Tomcat's "bin" directory by default - in my case
it was located at C:\Program
Files\netbeans-4.1\enterprise1\jakarta-tomcat-5.5.7\bin\jackrabbit as my
"tomcat" was the Tomcat bundled with Netbeans4.1 which I was running on
WindowsXP).  So you locate that directory and you delete it (not the
"bin" directory, just the "jackrabbit" directory).  Note that deleting
this directory (and its content) will destroy any data you had in the
respository, but will also allow you to start over.
 - Easy mistake#4: If you're using a braindead operating system that
doesn't know when to let go (I was using Windows XP), you'll probably be
told that the directory "jackrabbit" is in use, even after Tomcat has
stopped the web-app.  However, you don't need to reboot, you just need
to close Tomcat (at which point the OS will let you delete your files).
Note: Restarting Tomcat will restart all web-apps that were previously
deployed - it doesn't seem to remember that you'd "stopped" a web-app,
so it's best to ensure everything is ready to restart before restarting

8) Browsing the repository using a web-browser
 Point your browser at http://localhost:8080/jackrabbit-server/
 If the servlet is working, you'll get a nice web-page telling you how
to access things (which I'm sure wasn't there when I first did all this,
but I've updated the code since).
If you click on the link "Browser View", it'll take you to a simple view
of the respository, which won't contain anything (except "..").

9) Browsing the repository using WebDAV client
 Point your WebDAV client at
e.g. On "DAV Explorer":
 - enter in the above URL.
 - It'll prompt for a username and password - tell it anything you like
(except "anonymous").
 - You're in.
 - Note: There was a bug whereby the server returned an invalid HTTP
header which DAV Explorer refused to accept.  See
http://issues.apache.org/jira/browse/JCR-286?page=all for details.
e.g. On MS Windows XP-SP2:
 - If you're using "XP Style", open up "My Network Places" on the start
menu.  If you're using "Classic Style", open up Explorer, go "up" to the
desktop and you'll find "My Network Places" there instead.
 - Within "My Network Places", find "Add Network Place" and (double)
click on it.
 - That'll open an "Add Network Place Wizard".  Click "Next".
 - That'll claim to download things from the internet (it's actually
calling home to microsoft) then it gives you a list (with only one
option).  Highlight "Choose another network location" and click "Next".
 - That'll ask for the "Internet or network address:".  You'll need to
enter "http://localhost:8080/jackrabbit-server/repository/default/".
Then click "Next"
 - That'll prompt for a username and password.  Enter anything at all
(it doesn't matter, as long as you don't claim to be "anonymous").  Make
sure "Remember my password" is ticked.  Click ok (or press return).
 - The wizard will then attempt to open the folder, so if the username
or password is wrong or the server isn't working, it'll then tell you.
If all goes well, it'll then try to open the folder and prompt you for
the username and password again (Yes, it's forgotten already, even
though you told it to remember it, so tell it again).
 - That should result in a folder being displayed.  You should be able
to use this to browse around.
 - Note: If you didn't tell windows to remember the password, you'll
have to enter it in over and over again, instead of just twice.

Note: You can also mount the WebDAV view using Novell NetDrive, but it
reveals the same data as seen via the Windows-XP view.
Note#2: Contrary to many reports online, Novell NetDrive IS NOT FREE
(it's a no-cost add-on if you've already got Netware 6, hence is
downloadable from lots of universities etc for their students because
they're allowed to use it without further charge.  Those of us not using
Novell should limit usage to a 90 day evaluation only)
Note#3: You can also use WebDAV to see what's going on "under the hood"
and see more of the underlying properties and nodes etc inside the
repository if you point your WebDAV client at
However, this side of things is not intended as a generic WebDAV
filestore.  If you want this sort of low-level access, hit the JCR
directly or wait until a "JCR over WebDAV" client is released (or help
write it...)

10) Accessing the repository via RMI
 Stop the webapp and then edit
 Find the RepositoryStartup servlet configuration, and in there you'll
find a commented-out section about RMI.  Uncomment the 3 parameters
"rmi-port", "rmi-host" and "rmi-uri".
Set these to "1099", "localhost" and
 Now go along and find the next servlet, Repository.  At the end of that
section there's a "rmi-uri" parameter.  Make sure that's uncommented and
set to "//localhost:1099/jackrabbit.repository"
 Now restart the webapp - you should see (in the logs) a log to the
effect of:
RepositoryStartupServlet: Repository bound via RMI with name:
//localhost:1099/jackrabbit.repository (RepositoryStartupServlet.java,
line 286)

Ok, that's got your repository up and running and available via RMI.
Now you need some code to access it.  The crux of it is that you'll need
to do:
    import org.apache.jackrabbit.rmi.client.ClientRepositoryFactory;
    import javax.jcr.Repository;
    String name = "rmi://localhost:1099/jackrabbit.repository";
    ClientRepositoryFactory factory = new ClientRepositoryFactory();
    Repository repository = factory.getRepository(name);
and then use the "repository" you've obtained just like a normal JCR

I put together a simple command-line client (available on request).
It's devoid of comments (sorry), but should be fairly self-explanetory
(and the code pretty much follows that described in

 - Easy mistake: If you're using the Tomcat that's built-in to NetBeans
running on MS-Windows, and then running your client code on the same
machine, you may well hit the same strange error I did - EOFExceptions
and unmarshalling exceptions when you call factory.getRepository(name).
I got a "java.rmi.UnmarshalException: error unmarshalling return; nested
exception is: java.net.MalformedURLException: no protocol: and", and the
text "and" wasn't present in any URL I was sending...
I've no idea what the underlying cause was, but the problem went away
when I re-deployed the WAR file onto Tomcat on my Linux box.  I suspect
there's some strange limitation on the internal TCP socket comms within
Netbeans's Tomcat on WinXP, although I have no evidence to support this
theory as I lost interest the issue the moment I had a workaround (I'd
wasted a lot of time in the mistaken belief that the problem was with
the jcr-server code or with my configuration of it - Note to self: If in
doubt, blame microsoft and move on :-)

11) Advanced usage - a separate remote repository
Whilst it's possible to get the Tomcat servlets to publish the JCR via
RMI, it is also relatively easy to run your own "daemon" process that
runs a JCR as a separate process which then grants access to foreign
JVMs via RMI.  You can then run that on a separate box dedicated to the
task (which might well be necessary if the concerns regarding
performance of Jackrabbit over RMI are to be believed - it's certainly
not fast).
 First, you'll need to write a "daemon" (Microsoft-indoctrinated readers
should understand that a "daemon" is what a "service" was called before
microsoft decided to use a different name) program that starts a
repository, registers it with RMI, then sits waiting for someone to tell
it to do something.
 I did try attaching my own, but the list-server just said "ZIP
attachments are not accepted here", and it considers a JAR file to be a
ZIP file too.  I'm willing to email copies of "JcrRmiDaemon.zip" to
anyone who asks, at least in the short term.
 Then you'll need to run it with appropriate arguments, telling it all
about the security policy to use, the jaas.config file etc, and where to
put the repository files.

 Once that's running (i.e. starts and then hangs waiting for orders - if
it returns you to a command-prompt, it's broken), you can then tell the
Tomcat Servlet to use that instead of its own.
 Stop the tomcat servlet "jackrabbit-repository".
 Edit the tomcat file .../webapps/jackrabbit-server/WEB_INF/web.xml
 Delete the "R E P O S I T O R Y   S T A R T U P  S E R V L E T" section
in its entirity (this is the bit that says "If you already have the
repository registered in this appservers JNDI context, or if its
accessible via RMI, you do not need to use this servlet".  We've got an
RMI-accessible JCR, hence we don't need this - our daemon is doing its
job now.
 Scroll down to just above "W E B D A V  S E R V L E T" where you'll see
"<param-name>rmi-uri</param-name>" in a section that was originally
commented out (until we un-commented it in step 10).
Make sure it's un-commented and set the <param-value> to
rmi://localhost:1099/testRep (assuming that your daemon process is
running on localhost [i.e. same PC as Tomcat], and the daemon is running
on port 1099, and the repository it is running is registered with the
naming service under the name "testRep").
 Now restart the tomcat servlet "jackrabbit-repository"
 This should start up without complaint.
 Now try accessing the repository via WebDAV and/or your web-browser as
described in step 8 & 9 above - these should still work, and show an
empty repository.

Using this, you should be able to stuff a file into the repository
_either_ using your own software or WebDAV, and retrieve it _either_
using your own software, WebDAV, or the http-browser, and all remotely
too, so you can have a huge array of webservers running Tomcat, all
pointing at a single RMI-repository running on a separate (powerful)
box, which you could later replace with a commercial JCR implementation
if/when your needs outgrow Jackrabbit itself.

I hope this of some use to people, and saves folks from some of the
"learning experience" that I went through.
If anyone wants a copy of the code I mentioned that I wrote, or if they
can offer a permanent home for it, feel free to email (as long your
email will accept jar files of source code - this mailing list didn't).



This e-mail has been scanned for viruses by MCI's Internet Managed Scanning Services - powered
by MessageLabs. For further information visit http://www.mci.com

View raw message