JBoss.orgCommunity Documentation
It's the draft for a future FAQ of JCR usage.
Session.getNodeByUUID() about 2.5 times faster of Session.getItem(String) and only 25% faster of Node.getNode(String). See the daily tests results for such comparisons, e.g.
Until it's applicable for a business logic it can be. But take in account the paths are human readable and lets you think in hierarchy. If it's important a location based approach is preferable.
Use Session.itemExists(String absPath), Node.hasNode(String relPath) or Property.hasProperty(String name). It's also is possible to check Node.hasNodes() and Node.hasProprties().
JCR Observation it's a way to listen on persistence changes of a Repository. It provides several options to configure the listener for an interesting only changes. For proper use it's important to understand concept of events filtering for a registered EventListener (8.3.3 Observation Manager). An often confusing part it's the absPath, it's an associated parent of a location you want to observe events on. I.e. it's a parent of child node(s) or this parent property(ies); if isDeep is true then you'll get events of all the subtree of child nodes also. Same actual for uuid and nodeTypeName parameters of ObservationManager.addEventListener() method.
No, direct access to items via JCR API is more efficient. Search will consume additional resources for index querying and only then return the items.
By default (if query do not contains any ordering statements) result nodes is sorted by document order.
No it does not supported There is two ways to ordering results, when path may be used as criteria:
order by property with value type NAME or PATH (jcr supports it)
order by jcr:path - sort by exact path of node (jcr do not supports it)
Order by jcr:path
If no order specification is supplied in the query statement, implementations may support document order on the result nodes (see 6.6.4.2 Document Order). And its sorted by order number.
By default (if query do not contains any ordering statements) result nodes is sorted by document order.
SELECT * FROM nt:unstructured WHERE jcr:path LIKE 'testRoot/%'
For specified jcr:path ordering there is different proceeding in XPath and SQL:
SQL no matter ascending or descending - query returns result nodes in random order: {code}SELECT * FROM nt:unstructured WHERE jcr:path LIKE 'testRoot/%' ORDER BY jcr:path{code}
XPath - jcr:path order construction is ignored (so result is not sorted according path); {code}/testRoot/* @jcr:primaryType='nt:unstructured' order by jcr:path{code}
1. Indexer uses jcr:encoding property of nt:resource node (used as jcr:content child node of nt:file) 2. if no jcr:encoding property set the Document Service will use the one configured in the service (defaultEncoding) 3. if has nothing configured a JVM default encoding will be used
If question is a performance it's difficult question, as each database can be configured to be more (and more) faster for each special case. MySQL with MyISAM engine will be faster. But MySQL has limitations for indexes for multilingual columns (Item names actually). So, with long Item names (larger ofOracle or PostgreSQL also are good for performance. DB2 and MSSQL slower in default configurations. Default configuration of Sybase leader of slowness. But in this question take the database server maintenance in account. MySQL and PostgreSQL are simple in installation and can works even on limited hardware. Oracle, DB2, MSSQL or Sybase need more efforts. Same actual for maintenance during the work. Note for Sybase: "check-sns-new-connection" data container configuration parameter should be set to "true". For testing or embedded use HSQLDB is the best. Apache Derby and H2 also supported. But H2 surprisingly needs "beta" feature enabled - MVCC=TRUE in JDBC url.
MySQL database should be configured to use single-byte encoding, e.g. "latin1". eXo JCR application (e.g. GateIn) should use JCR dialect "MySQL-UTF8".
In other words: MySQL database default encoding and JCR dialect cannot be UTF8 both. Use single-byte encoding (e.g. "latin1") for database and "mysql-utf8" dialect for eXo JCR.
Notice: "MySQL-UTF8" dialect cannot be auto-detected, it should be set explicitly in configuration.
Index's key length of JCR_SITEM (JCR_MITEM) table for mysql-utf8 dialect is reduced to 765 bytes (or 255 chars).
For properly work JCR with Sybase need for each workspace data container add new property "check-sns-new-connection" with false value like this:
<container class="org.exoplatform.services.jcr.impl.storage.jdbc.optimisation.CQJDBCWorkspaceDataContainer"> <properties> <property name="source-name" value="jdbcjcr" /> <property name="dialect" value="auto" /> <property name="multi-db" value="true" /> <property name="update-storage" value="false" /> <property name="max-buffer-size" value="200k" /> <property name="swap-directory" value="target/temp/swap/ws" /> <property name="swap-directory" value="target/temp/swap/ws" /> <property name="check-sns-new-connection" value="false" /> </properties>
Session session = repository.login(credentials); try { // here your code } finally { session.logout(); }
No. Any instance of Session or Node (acquired through session) shouldn't be used after logout anymore. At least it is highly recommended not to use.
So we have configured JCR in standalone mode and want to reconfigure it for clustered environment. First of all let's check whether all requirements are satisfied:
Dedicated RDBMS anyone like MySQL, Postges, Oracle and etc. but just not HSSQL;
Shared storage. The simples thing is to use shared FS like NFS or SMB mounted in operation system, but they are rather slow. The best thing is to use SAN (Storage Area Network);
Fast network between JCR nodes.
So now, need to configure Container a bit. Check exo-configuration.xml to be sure You are using JBossTS Transaction Service and JBossCache Transaction Manager, as shown below.
<component> <key>org.jboss.cache.transaction.TransactionManagerLookup</key> <type>org.jboss.cache.GenericTransactionManagerLookup</type> </component> <component> <key>org.exoplatform.services.transaction.TransactionService</key> <type>org.exoplatform.services.transaction.jbosscache.JBossTransactionsService</type> <init-params> <value-param> <name>timeout</name> <value>300</value> </value-param> </init-params> </component>
Next stage is actually the JCR configuration. We need JBossCache configuration templates for : data-cache, indexer-cache and lock-manager-cache. Later they will be used configuring JCR's core components. There are pre-bundled templates in EAR or JAR in conf/standalone/cluster. They can be used as is or re-written if needed. And now time to re-configure a bit each workspace. Actually need to change few parameters of <cache>, <query-handler> and <lock-manager>.
<cache> configuration should looks like this:
<cache enabled="true" class="org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.JBossCacheWorkspaceStorageCache"> <properties> <property name="jbosscache-configuration" value="test-jbosscache-data.xml" /> <property name="jgroups-configuration" value="udp-mux.xml" /> <property name="jgroups-multiplexer-stack" value="true" /> <property name="jbosscache-cluster-name" value="JCR-cluster-db1-ws" /> </properties> </cache>
"jbosscache-configuration" is the path to configuration template;
"jgroups-configuration" is path to JGroups configuration is multiplexer stack is used (default). This file is also pre-bundled with templates and is recommended for use;
"jgroups-multiplexer-stack" just simply "true". Strongly recommended;
"jbosscache-cluster-name" is the name of cluster group. Should be different for each workspace and each workspace component. I.e.: <repository_name>-<ws_name>-<component(cache\|lock\|index)>
<query-handler> configuration
You must replace or add in <query-handler> block the "changesfilter-class" parameter equals with:
<property name="changesfilter-class" value="org.exoplatform.services.jcr.impl.core.query.jbosscache.JBossCacheIndexChangesFilter"/>
add JBossCache-oriented configuration:
<property name="jbosscache-configuration" value="test-jbosscache-indexer.xml" /> <property name="jgroups-configuration" value="udp-mux.xml" /> <property name="jgroups-multiplexer-stack" value="true" /> <property name="jbosscache-cluster-name" value="JCR-cluster-indexer-db1-ws" /> <property name="max-volatile-time" value="60" />
Those properties have the same meaning and restrictions as in previous block. Last property "max-volatile-time" is not mandatory but recommended. This notifies that latest changes in index will be visible for each cluster node not later than in 60s.
<lock-manager> configuration
Maybe this is the hardest element to configure, because we have to define access to DB where locks will be stored. Replace exsiting lock-manager configuration with shown below.
<lock-manager class="org.exoplatform.services.jcr.impl.core.lock.jbosscache.CacheableLockManagerImpl"> <properties> <property name="time-out" value="15m" /> <property name="jbosscache-configuration" value="test-jbosscache-lock.xml" /> <property name="jgroups-configuration" value="udp-mux.xml" /> <property name="jgroups-multiplexer-stack" value="true" /> <property name="jbosscache-cluster-name" value="JCR-cluster-locks-db1-ws" /> <property name="jbosscache-cl-cache.jdbc.table.name" value="jcrlocks_db1_ws" /> <property name="jbosscache-cl-cache.jdbc.table.create" value="true" /> <property name="jbosscache-cl-cache.jdbc.table.drop" value="false" /> <property name="jbosscache-cl-cache.jdbc.table.primarykey" value="jcrlocks_db1_ws_pk" /> <property name="jbosscache-cl-cache.jdbc.fqn.column" value="fqn" /> <property name="jbosscache-cl-cache.jdbc.node.column" value="node" /> <property name="jbosscache-cl-cache.jdbc.parent.column" value="parent" /> <property name="jbosscache-cl-cache.jdbc.datasource" value="jdbcjcr" /> </properties> </lock-manager>
First few properties are the same as in previous components, but here you can see some strange "jbosscache-cl-cache.jdbc.*" properties. They define access parameters for database where lock are persisted.
"jbosscache-cl-cache.jdbc.table.create" - whether to create it or not. Usually "true";
"jbosscache-cl-cache.jdbc.table.drop" - whether to drop on a start or not. Use "false";
"jbosscache-cl-cache.jdbc.table.primarykey" - name of column with pk;
"jbosscache-cl-cache.jdbc.fqn.column" - name of one more column, use as in example if not sure (if much interested, please refer to JBossCache JDBCCacheLoader documentation)
"jbosscache-cl-cache.jdbc.node.column" - name of one more column, use as in example if not sure (if much interested, please refer to JBossCache JDBCCacheLoader documentation)
"jbosscache-cl-cache.jdbc.parent.column" - name of one more column, use as in example if not sure (if much interested, please refer to JBossCache JDBCCacheLoader documentation)
"jbosscache-cl-cache.jdbc.datasource" - name of configured in Container datasource, where you want to store locks. Bets idea is to use the same as used for workspace.
That's all. JCR is ready for running in a cluster.
understand remote site as different buildings separated by a WAN network.
There is few steps:
enable lucene spellchecker in jcr QueryHandler configuration:
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"> <properties> ... <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" /> ... </properties> </query-handler>
execute query with rep:spellcheck function and word that is checked:
Query query = qm.createQuery("select rep:spellcheck() from nt:base where " + "jcr:path = '/' and spellcheck('word that is checked')", Query.SQL); RowIterator rows = query.execute().getRows();
fetch a result:
Row r = rows.nextRow(); Value v = r.getValue("rep:spellcheck()");
If there is no any results, that means there is no suggestion, so word is correct or spellcheckers dictionary do not contain any word looking like checked word.
There is two parameters in jcr QueryHandler configuration:
minimal distance between checked word and proposed suggestion;
search for more popular suggestions;
<query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex"> <properties> ... <property name="spellchecker-class" value="org.exoplatform.services.jcr.impl.core.query.lucene.spell.LuceneSpellChecker$FiveSecondsRefreshInterval" /> <property name="spellchecker-more-popular" value="false" /> <property name="spellchecker-min-distance" value="0.55" /> ... </properties> </query-handler>
Minimal distance is counted as Levenshtein distance between checked word and spellchecker suggestion.
MorePopular paramter affects in next way: If "morePopular" disabled:
if the proposed word exist in the directory - no suggestion given;
if the proposed word doesn't exist in the directory - propose the closed word;
If "morePopular" enabled:
no matter word exist or not, checker will propose the closed word that is the most popular than checked word.
Remove existing repository, use :
RepositoryService.removeRepository(String repositoryName)
Restore repository, use
BackupManager.restore(RepositoryBackupChainLog log, RepositoryEntry repositoryEntry, boolean asynchronous)
Remove existing workspace, use :
ManageableRepository.removeWorkspace(String workspaceName)
Restore workspace, use :
BackupManager.restore(BackupChainLog log, String repositoryName, WorkspaceEntry workspaceEntry, boolean asynchronous)
This is a known finder bug started from Mac OS v.10.5.3 and not yet fixed, .
for more details follow: Apple Disscussion thread.
Use "cache-control" configuration parameter.
The value of this parameter must contain colon-separated pairs "MediaType:cache-control value"
For example if you need to cache all text/xml and text/plain files for 5 minutes (300 sec.) and other text/\* files for 10 minutes (600 sec.) use the next configuration:
<component> <type>org.exoplatform.services.jcr.webdav.WebDavServiceImpl</type> <init-params> <value-param> <name>cache-control</name> <value>text/xml,text/plain:max-age=300;text/*:max-age=600;</value> </value-param> <init-params> <component>
Simple Requests
For simple request such as: GET, HEAD, MKCOL, COPY, MOVE, DELETE, CHECKIN, CHECKOUT, UNCHECKOUT, LOCK, UNLOCK, VERSIONCONTROL, OPTIONS
perform:
curl -i -u 'user:pass' -X 'METHOD_NAME' 'resource_url'
for example to create a folder named test perform:
curl -i -u 'root:exo' -X MKCOL 'http://localhost:8080/rest/jcr/repository/production/test
to PUT a test.txt file from your current folder to "test "folder on server perform:
curl -i -u 'root:exo' -X PUT 'http://localhost:8080/rest/jcr/repository/production/test/test.txt' -d @test.txt
Requests with XML body
For requests which contains xml body such as: ORDER, PROPFIND, PROPPATCH, REPORT, SEARCH
add -d 'xml_body text' or -d @body.xml
(body.xml must contain a valid xml request bidy.) to you curl-command:
curl -i -u 'user:pass' -X 'METHOD_NAME' -H 'Headers' 'resource_url' -d 'xml_body text'
for example to find all files containing "test" perform:
curl -i -u "root:exo" -X "SEARCH" "http://192.168.0.7:8080/rest/jcr/repository/production/" -d "<?xml version='1.0' encoding='UTF-8' ?> <D:searchrequest xmlns:D='DAV:'> <D:sql>SELECT * FROM nt:base WHERE contains(*, 'text')</D:sql> </D:searchrequest>"
if you need to add some headers to your request use \-H key.
More information about methods parameters you can find in HTTP Extensions for Distributed Authoring specification.
OS client (Windows, Linux etc) doesn't set an encoding in a request. But eXo JCR WebDAV server looks for an encoding in a Content-Type header and set it to jcr:encoding. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, 14.17 Content-Type. e.g. Content-Type: text/html; charset=ISO-8859-4 So, if a client will set Content-Type header, e.g. JS code from a page, it will works for a text file as expected.
If WebDAV request doesn't contain a content encoding it's possible to write a dedicated action in a customer application. The action will set jcr:encoding using its own logic, e.g. based on IP or user preferences.