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 corrections. 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 /opt/netbeans-4.1/ - 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 1.4.x): 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 1.4.x): 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 jackrabbit (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 8080. 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 .../webapps/jackrabbit-server/WEB_INF/lib/ 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 anyway. So you'll need to edit .../webapps/jackrabbit-server/WEB_INF/repository/repository.xml, find the AccessManager section and appended (immediately after </AccessManager>): <LoginModule class="org.apache.jackrabbit.core.security.SimpleLoginModule"> <param name="anonymousId" value="anonymous" /> </LoginModule> 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 exceptions. - 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 at org.apache.jackrabbit.j2ee.RepositoryStartupServlet.initRepository(Repos itoryStartupServlet.java:168) at org.apache.jackrabbit.j2ee.RepositoryStartupServlet.init(RepositoryStart upServlet.java:94) ... 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 tomcat. 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 http://localhost:8080/jackrabbit-server/repository/default/ 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 http://localhost:8080/jackrabbit-server/server/ 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 .../webapps/jackrabbit-server/WEB_INF/web.xml 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 "//localhost:1099/jackrabbit.repository". 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 repository. 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 http://www-128.ibm.com/developerworks/java/library/j-jcr/). - 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). TT4N Peter _____________________________________________________________________ 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
