Version 3

    After a long and arduous battle, I finally deployed a simple webapp that employs a combination of these technologies (JBoss EAP 6.2 [AS 7.3.0], Jackrabbit 2,7, Oracle 11g, and RestEasy 3.0).  Since this would have been impossible without help from many forums, I thought I would share my trail of bread crumbs here on this forum, for what it's worth.  The instructions from Brian Wallis were indeed very helpful, but certain steps were missing and/or out-of-date, thereby invoking further collision between my head and a nearby wall.

     

    This example uses RestEasy to receive data from an HTTP POST and passes it via the JCR API to Jackrabbit and then to an Oracle database for storage.  A subsequent HTTP GET will retreive the same data.

     

    Start with JBoss EAP 6.2 (or JBoss AS 7.3.0 Final).  This process also works with WildFly 8.1.0 Final.

     

    Add a JCR module to the jboss-eap-6.2/modules directory.  Here is what mine looks like:

     

    $ cd jboss-eap-6.2/modules/
    $ find javax -type f
    javax/jcr/main/jcr-2.0.jar
    javax/jcr/main/module.xml
    $ sha1sum javax/jcr/main/jcr-2.0.jar
    08297216bcfe4aea369ed6ee0d1718133f752e97  javax/jcr/main/jcr-2.0.jar
    $ cat javax/jcr/main/module.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <module xmlns="urn:jboss:module:1.1" name="javax.jcr">
      <resources>
        <resource-root path="jcr-2.0.jar"/>
      </resources>
      <dependencies>
        <module name="javax.transaction.api" export="true"/>
      </dependencies>
    </module>
    $
    
    
    

     

    Add an ojdbc module to the jboss-eap-6.2/modules directory. Here is what mine looks like:

     

    $ find com -type f
    com/oracle/db/main/ojdbc6.jar
    com/oracle/db/main/module.xml
    $ sha1sum com/oracle/db/main/ojdbc6.jar
    8d98e89385dafc7e1b8a2cfc1e016deb21246236  com/oracle/db/main/ojdbc6.jar
    $ cat com/oracle/db/main/module.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <module xmlns="urn:jboss:module:1.1" name="com.oracle.db">
      <resources>
        <resource-root path="ojdbc6.jar"/>
      </resources>
      <dependencies>
         <module name="javax.api"/>
         <module name="javax.transaction.api"/>
      </dependencies>
    </module>
    $
    
    
    

     

    Tell JBoss to register ojdbc as a core module, using jboss-cli.sh:

     

    jboss-eap-6.2/bin$ ./jboss-cli.sh
    You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
    [disconnected /] connect
    [standalone@localhost:9999 /] /subsystem=datasources/jdbc-driver=oracle:add(driver-name=oracle,driver-module-name=com.oracle.db,driver-xa-datasource-class-name=oracle.jdbc.xa.client.OracleXADataSource)
    {"outcome" => "success"}
    [standalone@localhost:9999 /]
    
    
    

     

    Add a datasource.  Here's what mine looks like:

     

    <subsystem xmlns="urn:jboss:domain:datasources:1.1">
       <datasources>
           <datasource jta="false" jndi-name="java:/jdbc/DocumentStoreDS" pool-name="DocumentStoreDS" enabled="true" use-ccm="false">
               <connection-url>jdbc:oracle:thin:@10.0.0.5:1521:xe</connection-url>
               <driver-class>oracle.jdbc.OracleDriver</driver-class>
               <driver>oracle</driver>
               <security>
                   <user-name>rabbit</user-name>
                   <password>rabbit</password>
               </security>
               <validation>
                   <validate-on-match>false</validate-on-match>
                   <background-validation>false</background-validation>
               </validation>
               <statement>
                   <share-prepared-statements>false</share-prepared-statements>
               </statement>
           </datasource>
           <drivers>
               <driver name="h2" module="com.h2database.h2">
                   <xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
               </driver>
               <driver name="oracle" module="com.oracle.db">
                   <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
               </driver>
           </drivers>
       </datasources>
    </subsystem>
    
    
    

     

    Disable JCA validation.  Note that this is a known (and apparently accepted?) workaround: https://issues.apache.org/jira/browse/JCR-3241

     

    <subsystem xmlns="urn:jboss:domain:jca:1.1">
       <archive-validation enabled="false" fail-on-error="true" fail-on-warn="false"/>
       ...
    </subsystem>
    
    
    

     

    Add a Resource Adapter for Jackrabbit.  The "HomeDir" and "ConfigFile" must reside somewhere on the server, but the actual repository contents will reside in the database, as specified in the repository.xml file.  The repository.xml file that I used is attached.


    <subsystem xmlns="urn:jboss:domain:resource-adapters:1.1">
       <resource-adapters>
           <resource-adapter id="jackrabbit-jca-2.8.0.rar">
               <archive>
                   jackrabbit-jca-2.8.0.rar
               </archive>
               <transaction-support>XATransaction</transaction-support>
               <connection-definitions>
                   <connection-definition class-name="org.apache.jackrabbit.jca.JCAManagedConnectionFactory" jndi-name="java:/jca/DocumentStore" enabled="true" pool-name="RabbitAdapter">
                       <config-property name="HomeDir">
                           /media/homespace/field
                       </config-property>
                       <config-property name="ConfigFile">
                           /media/homespace/field/repository.xml
                       </config-property>
                       <security>
                           <application/>
                       </security>
                       <validation>
                           <background-validation>false</background-validation>
                       </validation>
                   </connection-definition>
               </connection-definitions>
           </resource-adapter>
       </resource-adapters>
    </subsystem>
    
    
    

     

    Before deploying the jackrabbit-jca-2.8.0.rar file, it must be modified.  Decompress the file, and remove the two logback jars (core and classic).  Then add the ojdbc6.jar.  Then modify the MANIFEST.MF such that it states its dependency on javax.jcr.  Shown below are the contents of my MANIFEST.MF.  After adding the "Dependencies" line, compress it again, taking care to preserve your modification to the manifest (e.g. using the "m" option of the jar command).

     

    $ cat META-INF/MANIFEST.MF
    Manifest-Version: 1.0
    Archiver-Version: Plexus Archiver
    Created-By: Apache Maven
    Built-By: jzitting
    Build-Jdk: 1.7.0_40
    Dependencies: javax.jcr export,org.slf4j
    
    $
    
    
    

     

    Deploy jackrabbit-jca-2.8.0.rar.  This should connect to your database and create tables and sequences.  The attached repository.xml file will result in the creation of the following tables and sequences:

     

    TABLE_NAME
    ------------------------------
    JR_DATASTORE
    JR_FSDEF_FSENTRY
    JR_FSVER_FSENTRY
    JR_FS_FSENTRY
    JR_PMDEF_BINVAL
    JR_PMDEF_BUNDLE
    JR_PMDEF_NAMES
    JR_PMDEF_REFS
    JR_PMVER_BINVAL
    JR_PMVER_BUNDLE
    JR_PMVER_NAMES
    JR_PMVER_REFS
    
    SEQUENCE_NAME
    ------------------------------
    JR_PMDEF_SEQ_NAMES_ID
    JR_PMVER_SEQ_NAMES_ID
    
    
    

     

    Deploy conejo.war.  The source code (maven project) for conejo.war is attached.  Note that the maven-war-plugin is used to add the "Dependencies" line to MANIFEST.MF, as was done manually in a previous step for the rar file.  It should deploy without error and be ready to respond to GET and PUT requests over HTTP.

     

    Usage examples:

     

    Plain text:

     

    $ cat test.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <test>
       <hello>hola</hello>
       <bye>adios</bye>
    </test>
    $ curl -X PUT --data-binary '@test.xml' http://localhost:8080/conejo/repo/123/test.xml
    ok
    $ curl http://localhost:8080/conejo/repo/123/test.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <test>
       <hello>hola</hello>
       <bye>adios</bye>
    </test>
    $
    
    
    

     

    Binary data:

     

    $ curl -X PUT --data-binary '@mario.png' http://localhost:8080/conejo/repo/123/mario.png
    ok
    $ curl http://localhost:8080/conejo/repo/123/mario.png > data
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  700k  100  700k    0     0  1526k      0 --:--:-- --:--:-- --:--:-- 1526k
    $ cksum data mario.png
    1451617279 717492 data
    1451617279 717492 mario.png
    $
    
    
    

     

    Note: The Produces("*/*") annotation of FedEx.getContent() tells the browser that the HTTP body "could be anything".  The browser will then use the filename extension to guess at how to handle the content – so with the above example, putting http://localhost:8080/conejo/repo/123/mario.png in the browser will actually show the image.  Without the Produces("*/*") annotation, RestEasy seems to specify "application/octet-stream", or somehow declare binary data, and the browser does not guess at the filetype.

     

    Note: It seems to me that jackrabbit-jca-2.8.0.rar should not need to contain a copy of ojdbc6.jar, but it will not deploy without it.  I imagine there is (yet another) subtle configuration detail that would resolve this oddity, and if there is then I'd be glad to know it.