Apache Jackrabbit : JackrabbitOnWeblogic

Jackrabbit On WebLogic

Applies to versions

Setting up JNDI in Jackrabbit

        <FileSystem class="org.apache.jackrabbit.core.fs.db.JNDIOracleDatabaseFileSystem">
	        <param name="path" value="${rep.home}"/>
		<param name="dataSourceLocation" value="jdbc/jcr"/>
		<param name="checkValidConnectionSQL" value="select 0 from dual" />
		<param name="schemaObjectPrefix" value="default"/>
		<param name="schema" value="oracle" />
	</FileSystem>

	<PersistenceManager class="org.apache.jackrabbit.core.state.db.JNDIOracleDatabasePersistenceManager">
                <param name="path" value="${wsp.home}/db"/>
		<param name="dataSourceLocation" value="jdbc/jcr"/>
		<param name="checkValidConnectionSQL" value="select 0 from dual" />				
		<param name="schemaObjectPrefix" value="pm_def"/>
		<param name="schema" value="oracle" />
 		<param name="externalBLOBs" value="false"/>
	</PersistenceManager>
  • With Oracle you need an OracleConnection to be able to use Oracle extensions such as BLOB, Struct etc.
  • For Oracle support with JNDI a new classes are implemented: JNDIOracleDatabaseFileSystem and JNDIOracleDatabasePersistenceManager. The code for these classes stored on the ExamplesPage -> see the patch included on that page.

Configuring WebLogic

  • Use the default Oracle driver
  • Configure a datasource
  • create a JNDI name
  • now webLogic will return a wrapper DataSource for Oracle from which Jackrabbit can use Oracle extensions

Using WebDAV

  • No special configuration is needed for using WebDAV

jackrabbit on WLP

  • Download Jackrabbit JCA Resource Adapter (e.g. jackrabbit-jca-1.3.1.rar ) from - http://jackrabbit.apache.org/downloads.html
  • Explode the rar ** put jars in system class path (this is architecturally unsound, use RMI appraoch for real world application) ** put only the MANIFEST.MF, ra.xml & weblogic-ra.xml in autodeploy/jackrabbit-jca-1.3.1/META-INF dir (WLS Console doesn't seem to work well with .rar files)
  • modify ra.xml to point to repository directory & repository.xml (repository must be in domain root or BEA_HOME)

Sample ra.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
  Sample ra.xml
  -->
<connector xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
           http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
    version="1.5">

    <display-name>Jackrabbit JCR Adapter</display-name>
    <vendor-name>Apache.org</vendor-name>
    <eis-type>JCR Adapter</eis-type>
    <resourceadapter-version>1.0</resourceadapter-version>

    <resourceadapter>
        <resourceadapter-class>org.apache.jackrabbit.jca.JCAResourceAdapter</resourceadapter-class>
        <outbound-resourceadapter>

            <connection-definition>
                <managedconnectionfactory-class>org.apache.jackrabbit.jca.JCAManagedConnectionFactory</managedconnectionfactory-class>
                
                <config-property>
                    <config-property-name>HomeDir</config-property-name>
                    <config-property-type>java.lang.String</config-property-type>
                    <config-property-value>
                        @DOMAIN_HOME/jackrabbit
                    </config-property-value>
                </config-property>
                <config-property>
                    <config-property-name>ConfigFile</config-property-name>
                    <config-property-type>java.lang.String</config-property-type>
                    <config-property-value>
                        @DOMAIN_HOME/jackrabbit/repository.xml
                    </config-property-value>
                </config-property>
                
                <connectionfactory-interface>javax.jcr.Repository</connectionfactory-interface>
                <connectionfactory-impl-class>org.apache.jackrabbit.jca.JCARepositoryHandle</connectionfactory-impl-class>
                
                <connection-interface>javax.jcr.Session</connection-interface>
                <connection-impl-class>org.apache.jackrabbit.jca.JCASessionHandle</connection-impl-class>
            </connection-definition>
            
            <transaction-support>XATransaction</transaction-support>
            <reauthentication-support>false</reauthentication-support>
        </outbound-resourceadapter>            
    </resourceadapter>
</connector>

Sample weblogic-ra.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE weblogic-connection-factory-dd SYSTEM "http://www.bea.com/servers/wls810/dtd/weblogic810-ra.dtd" >

<!--
  Sample weblogic-ra.xml
  -->

<weblogic-connection-factory-dd>
  <connection-factory-name>contentRepository</connection-factory-name>
  <jndi-name>repository</jndi-name>

  <pool-params>
    <initial-capacity>10</initial-capacity>
    <max-capacity>50</max-capacity>
    <capacity-increment>1</capacity-increment>
    <shrinking-enabled>true</shrinking-enabled>
    <connection-profiling-enabled>true</connection-profiling-enabled>
    <shrink-frequency-seconds>5</shrink-frequency-seconds>

    <inactive-connection-timeout-seconds>0</inactive-connection-timeout-seconds>
    <highest-num-waiters>2147483647</highest-num-waiters>
    <highest-num-unavailable>0</highest-num-unavailable>
    <connection-creation-retry-frequency-seconds>1</connection-creation-retry-frequency-seconds>

    <connection-reserve-timeout-seconds>10</connection-reserve-timeout-seconds>
    <test-frequency-seconds>0</test-frequency-seconds>
    <match-connections-supported>true</match-connections-supported>
  </pool-params>
</weblogic-connection-factory-dd>
  • write scripting to map dirs to local system
  • add entry to content-config.xml

Sample content-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<content-config xmlns="http://www.bea.com/ns/portal/90/content-config">
    <!-- 
      Sample content-config.xml
      -->
    <content-store>
        <!-- ... snipped for brevity ... -->
    </content-store>
    <content-store>
        <name>Jackrabbit</name>
        <description>Jackrabbit JNDI Content Repository Configuration</description>
        <class-name>com.day.content.spi.jsr170.JNDIRepository</class-name>
        <repository-property>
            <description>JSR-170 Repository Workspace</description>
            <name>jsr170.workspace</name>
            <value>jackrabbit</value>
        </repository-property>
        <repository-property>
            <description>JSR-170 Repository JNDI name</description>
            <name>jsr170.jndi.name</name>
            <value>repository</value>
        </repository-property>
        <read-only>false</read-only>
        <binary-cache-max-entry-size>1024</binary-cache-max-entry-size>
        <search-is-enabled>true</search-is-enabled>
        <fulltext-search-is-enabled>false</fulltext-search-is-enabled>
        <search-indexing-is-enabled>true</search-indexing-is-enabled>
    </content-store>
</content-config>
  • write custom node type def file (cnd)

Sample Custom Node Type Definition File

<nt = 'http://www.jcp.org/jcr/nt/1.0'>
<flix = 'http://wlp.bea.com/jcr/1.0/flix'>

[flix:MEDIA] > nt:unstructured
 - flix:TITLE (string) primary mandatory
 - flix:RELEASE_DATE (long) mandatory
 - flix:THUMBNAIL (binary)
 - flix:LENGTH (long)
 - flix:DIRECTOR (name) mandatory
 - flix:CAST (name) mandatory multiple
 - flix:GENRE (string) mandatory multiple
   < 'Action', 'Comedy', 'Drama', 'Horror', 'Romance', 'Sci-Fi & Fantasy', 'Thrillers' 
 - flix:MEDIA_TYPE (string) = 'DVD' mandatory
   < 'VHS', 'DVD', 'Blue-Ray', 'HD DVD', 'CD', 'PS3', 'XBOX 360', 'Wii', 'PS2'
 - flix:IMDB_LINK (string)
 - flix:QUOTES (string) multiple
 - flix:SYNOPSIS (string) mandatory
 - flix:TRAILER_CLIP (binary)
 - flix:STOCK_STATUS (string) = 'in stock' mandatory
   < 'unreleased', 'in stock', 'out of stock'
  • write code against jackrabbit api to create types & content

Sample Type and Node Creation Code

package com.bea.wlp.scenarios.flix.jackrabbit;

import javax.jcr.NamespaceException;
import javax.jcr.NamespaceRegistry;
import javax.jcr.Node;
import javax.jcr.Workspace;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.naming.Context;
import javax.naming.InitialContext;

import org.apache.jackrabbit.core.TransientRepository;
import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Calendar;
import java.util.Date;
import java.util.Hashtable;
import java.util.List;
import java.util.Iterator;

public class CustomNodeTypeLoader 
{
    public static final String REPO_JNDI_NAME = "repository";
	public static final String CND_FILE_NAME = "/schemas/flixTypes.cnd";
    public static final String FLIX_NS_PREFIX = "flix";
    public static final String FLIX_NS_URI = "http://wlp.bea.com/jcr/1.0/flix";

    public void loadCustomNodeTypes()
    {
        try
        {
            InitialContext ctx = new InitialContext();
            Repository repository = (Repository)ctx.lookup(REPO_JNDI_NAME);

            Session session = repository.login(new SimpleCredentials("weblogic", "weblogic".toCharArray()));
            Workspace ws = session.getWorkspace();
            
            NamespaceRegistry nsr = ws.getNamespaceRegistry();
            
            try {
            	nsr.registerNamespace(FLIX_NS_PREFIX, FLIX_NS_URI);
            } catch (NamespaceException e) {
                // ignore - implies we've already registered the namespace
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            Reader cndFileReader = new InputStreamReader(this.getClass().getResourceAsStream(CND_FILE_NAME));
            
            // Create a CompactNodeTypeDefReader
            CompactNodeTypeDefReader cndReader = new CompactNodeTypeDefReader(cndFileReader, CND_FILE_NAME);
    
            // Get the List of NodeTypeDef objects
            List ntdList = cndReader.getNodeTypeDefs();
    
            // Get the NodeTypeManager from the Workspace.
            // Note that it must be cast from the generic JCR NodeTypeManager to the
            // Jackrabbit-specific implementation.
            NodeTypeManagerImpl ntmgr =(NodeTypeManagerImpl)ws.getNodeTypeManager();
    
            // Acquire the NodeTypeRegistry
            NodeTypeRegistry ntreg = ntmgr.getNodeTypeRegistry();
    
            // Loop through the prepared NodeTypeDefs
            for (Iterator i = ntdList.iterator(); i.hasNext();) {
    
                // Get the NodeTypeDef...
                NodeTypeDef ntd = (NodeTypeDef)i.next();

                try {
	                // ...and register it
	                ntreg.registerNodeType(ntd);
	            } catch (InvalidNodeTypeDefException e) {
	                // ignore - implies we've already created the type
	            } catch (Exception e) {
	                throw new RuntimeException(e);
	            }
            }
            
            Node rootNode = session.getRootNode();
            Node baseNode = rootNode.addNode("Flix Media Auto", "nt:unstructured");
            
            Calendar releaseDate = Calendar.getInstance();
            
            releaseDate.set(2007, 8, 17);
            createNode(baseNode, "Superbad", releaseDate, 114, "Greg Mottola", "Jonah Hill", "Comdey", "DVD", 
            		"http://www.imdb.com/title/tt0829482/", "Same-sies!", "Hilarous!", "unreleased");
            
            
            session.save();
        } catch (InvalidNodeTypeDefException e) {
            // ignore - implies we've already created everything
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    
    public void createNode(Node parentNode, String title, Calendar releaseDate, long length, String director, 
    		String castMember, String genre, String mediaType, String imdbLink, String quote, String synopsis, 
    		String stockStatus)
    	throws Exception
    {
    	Node newNode = parentNode.addNode(title, "flix:MEDIA");
        newNode.setProperty("flix:TITLE", title);
        newNode.setProperty("flix:RELEASE_DATE", releaseDate);
        newNode.setProperty("flix:LENGTH", length);
        newNode.setProperty("flix:DIRECTOR", director);
        newNode.setProperty("flix:CAST", castMember);
        newNode.setProperty("flix:GENRE", genre);
        newNode.setProperty("flix:MEDIA_TYPE", mediaType);
        newNode.setProperty("flix:IMDB_LINK", imdbLink);
        newNode.setProperty("flix:QUOTES", quote);
        newNode.setProperty("flix:SYNOPSIS", synopsis);
        newNode.setProperty("flix:STOCK_STATUS", stockStatus);
    }
}

Also see: http://edocs/wlp/docs100/pdf/day170adapter_developers_guide.pdf