Jackrabbit On WebLogic
Applies to versions
- WebLogic 8.1 SP4
- Oracle 9i
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:
JNDIOracleDatabaseFileSystemandJNDIOracleDatabasePersistenceManager. 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);
}
}
- add app lifecycle listener or filter to call type creation code
- use federated cm api to create and access content (e.g. http://edocs/wlp/docs100/cm/index.html )
Also see: http://edocs/wlp/docs100/pdf/day170adapter_developers_guide.pdf