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:
JNDIOracleDatabaseFileSystem
andJNDIOracleDatabasePersistenceManager
. 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