-
Language:
English
-
Language:
English
Red Hat Training
A Red Hat training course is available for Red Hat JBoss Data Virtualization
Chapter 4. Using the Hierarchical Database with Red Hat JBoss EAP
4.1. Configuring the Hierarchical Database
4.1.1. Hierarchical Database Configuration
Although JBoss Data Virtualization comes with a hierarchical database already configured, this topic describes the steps required to configure another if so desired.
Procedure 4.1. Task
Start the JBoss EAP server
Start JBoss EAP in standalone mode with the configuration of your choice. For example, the following starts with thestandalone.xml
configuration file:$ bin/standalone.sh -c=standalone.xml
Start the JBoss EAP Management CLI
You can use the JBoss EAP command line interface (CLI) tool to directly manipulate the configuration of the running server. If the server is running in domain mode, the CLI immediately propagates the changes to all the servers. Start the CLI and connect to your server as shown below:$ ./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 /]
Add a hierarchical database subsystem
Add the subsystem to the current configuration as shown below:[standalone@localhost:9999 /] /extension=org.modeshape:add() {"outcome" => "success"} [standalone@localhost:9999 /] ./subsystem=modeshape:add {"outcome" => "success"}
This updates the configuration's XML file (in this casestandalone.xml
) immediately.Add a hierarchical database repository
Before adding a repository, add or configure the JBoss EAP resources for the repository to use.Add an Infinispan cache
Each hierarchical database repository stores its content in an Infinispan cache. The following steps show how to put this cache in a new cache container calledmodeshape
, which you can use for other repositories:[standalone@localhost:9999 /] /subsystem=infinispan/cache-container=modeshape:add {"outcome" => "success"}
Once you have your container, here is how you can define a local cache namedsample
that uses non-XA transactions and persists all content immediately to themodeshape/store/sample
directory under thestandalone/data
directory:[standalone@localhost:9999 /] /subsystem=infinispan/cache-container=modeshape/local-cache=sample:add {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=modeshape/local-cache=sample/transaction=TRANSACTION:add(mode=NON_XA) { "outcome" => "success", "response-headers" => { "operation-requires-reload" => true, "process-state" => "reload-required" } } [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=modeshape/local-cache=sample/file-store=FILE_STORE:add(path="modeshape/store/sample",relative-to="jboss.server.data.dir",passivation=false,purge=false) { "outcome" => "success", "response-headers" => {"process-state" => "reload-required"} }
These commands run successfully, however, the last few may require a reload of the Infinispan service. This means that your changes are saved to the configuration, but these few may not take effect until the next restart or until you explicitly perform the reload:[standalone@localhost:9999 /] :reload { "outcome" => "success", "response-headers" => {"process-state" => "reload-required"} } [standalone@localhost:9999 /] :reload {"outcome" => "success"}
Add the repository
After defining the services for the repository to use, here is how you can define a repository calledsample
:[standalone@localhost:9999 /] ./subsystem=modeshape/repository=sample:add(security-domain="modeshape-security",cache-name="sample",cache-container="modeshape") {"outcome" => "success"}
This command configures thesample
repository to use the sample Infinispan cache in themodeshape
cache container, and to use themodeshape-security
security domain created earlier. Restart is not required after defining a repository. Most of the administrative operations take effect immediately even when applications are actively using the repository.You need not define thesecurity-domain="modeshape-security"
attribute because the repository uses a security domain with that name by default. Also, by default the repository tries to use an Infinispan cache with the name "modeshape" which is same as the repository in the cache container. You can specify these, but any attributes that match the default value will not be serialized to the XML configuration file.
4.1.2. Advanced Repository Configuration
Procedure 4.2. Task
- You can view the complete definition of a repository at any point by running the following command in the Management CLI:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample:read-resource(recursive=true) { "outcome" => "success", "result" => { "allow-workspace-creation" => true, "anonymous-roles" => undefined, "anonymous-username" => "<anonymous>", "binary-storage" => undefined, "cache-container" => "modeshape", "cluster-name" => undefined, "cluster-stack" => undefined, "default-workspace" => "default", "enable-monitoring" => true, "index-storage" => undefined, "indexing-analyzer-classname" => "org.apache.lucene.analysis.standard.StandardAnalyzer", "indexing-analyzer-module" => undefined, "indexing-async-max-queue-size" => 0, "indexing-async-thread-pool-size" => 1, "indexing-batch-size" => -1, "indexing-mode" => "SYNC", "indexing-reader-strategy" => "SHARED", "indexing-thread-pool" => "modeshape-workers", "jndi-name" => undefined, "minimum-binary-size" => 4096, "predefined-workspace-names" => undefined, "rebuild-indexes-upon-startup" => "IF_MISSING", "security-domain" => "modeshape-security", "sequencer" => undefined, "use-anonymous-upon-failed-authentication" => false } }
This shows all the attributes including the ones that are not set, or set to their default values. - To view details about each attribute and child, use the
:read-resource-description()
command. For example:[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample:read-resource-description(recursive=true) { "outcome" => "success", "result" => { "description" => "ModeShape repository", "attributes" => { "cache-name" => { "type" => STRING, "description" => "The name of the cache that is to be used for storing this repository's content", "expressions-allowed" => false, "nillable" => true, "min-length" => 1L, "max-length" => 2147483647L, "access-type" => "read-write", "storage" => "configuration", "restart-required" => "resource-services" }, "cache-container" => { "type" => STRING, "description" => "The name of the cache container that contains the cache to be used for storing this repository's content", "expressions-allowed" => false, "nillable" => true, "min-length" => 1L, "max-length" => 2147483647L, "access-type" => "read-write", "storage" => "configuration", "restart-required" => "resource-services" }, "jndi-name" => { "type" => STRING, "description" => "The optional alias in JNDI where this repository is to be registered, in addition to 'jcr/{repositoryName}", "expressions-allowed" => false, "nillable" => true, "min-length" => 1L, "max-length" => 2147483647L, "access-type" => "read-write", "storage" => "configuration", "restart-required" => "resource-services" }, ...
Here, the output shows the description of each attribute, the criteria for valid values, whether expressions such as system variables are allowed or not, and whether a restart is required or not before changes take effect.Most of the attributes have defaults, but the descriptions do not list some of the defaults because the defaults are functions of other attributes. For example, every repository is registered in JNDI underjcr/repositoryName
, and also under the JNDI name explicitly set with thejndi-name
attribute.
4.1.3. Repository Attributes
The following table contains the list of all the attributes for a hierarchical database repository:
Table 4.1. Repository Attributes
Attribute Name | Description |
---|---|
allow-workspace-creation | Specifies whether authenticated and authorized JCR users can create additional workspaces beyond the predefined, system, and default workspaces. The default value is 'true'. Set this to 'false' when you need to fix the workspaces. |
anonymous-roles | The list of names (of type String) of the roles for all anonymous users. An empty String in the role name results in disabling the logins. By default, anonymous users are given all roles: 'connect', 'readonly', 'readwrite', and 'admin'. |
anonymous-username | The username for all anonymous users. The username <anonymous> is used by default. |
cache-container | The name of the Infinispan cache container containing the cache. If not provided, the "modeshape" cache container is used. |
cache-name | The name of the Infinispan cache where repository content is stored. If not provided, the repository name is used for the cache name. |
cluster-name | Defines the name of the communication channel used to share events amongst all repository instances in the cluster. By default there is no value. This means that the repository is not participating in a cluster. |
cluster-stack | Specifies the name of the JGroups stack used by the repository to create a channel for events when the repository is clustered. By default there is no value. This means that the repository is not participating in a cluster. |
default-workspace | The name of the workspace to be used when sessions are created without specifying an explicit workspace name. By default, the "default" workspace name is used. |
enable-monitoring | Specifies whether the repository is to maintain the metrics that can be used to monitor the performance and activities. The default value is 'true', which means that the monitoring is enabled. |
indexing-analyzer-classname | The fully-qualified name of the Lucene analyzer implementation class. The default value is org.apache.lucene.analysis.standard.StandardAnalyzer . |
indexing-analyzer-module | The name of the module that contains the specified analyzer class. No value is specified by default, which means that the class is visible to the hierarchical database engine. |
indexing-async-max-queue-size | The maximum size of the queue used for asynchronous indexing. By default the value is '0'. The value is ignored if synchronous indexing is enabled. |
indexing-async-thread-pool-size | The size of the thread pool used for asynchronous indexing. By default the value is '1'. The value is ignored if synchronous indexing is enabled. |
indexing-batch-size | The size of the indexing batches. The default value is '-1', which means the batch sizes are unlimited. |
indexing-mode | The concurrency mode for indexing. The valid values are 'SYNC' and 'ASYNC'. |
indexing-reader-strategy | The strategy for sharing (or not sharing) index readers. The valid values are 'SHARED' and 'NOT_SHARED'. |
indexing-thread-pool | The name of the thread pool that the repository indexing system should use. The default value is 'modeshape-workers'. |
jndi-name | The repository is always bound in JNDI to the name 'jcr/{repositoryName}', however you can use this attribute to specify an additional location in JNDI where the repository is to be registered. |
minimum-binary-size | The size threshold that dictates whether String and binary values should be stored in the binary store. String and binary values smaller than this value are stored with the node, whereas String and binary values with a size equal to or greater than this limit are stored separately from the node in the binary store, keyed by the SHA-1 hash of the value. This is a space and performance optimization that stores each unique large value only once. The default value is '4096' bytes, or 4 kilobytes. |
predefined-workspace-names | The names of the workspaces that the repository ensures exist (or create if necessary) when the repository starts up. |
rebuild-indexes-upon-startup | Specifies whether the indexes need to be rebuilt immediately when each process starts up. Valid values are 'IF_MISSING' , 'ALWAYS' or 'NEVER. By default the value is 'IF_MISSING'. |
rebuild-upon-startup-mode | Specifies whether index rebuilding at startup should be synchronous or asynchronous. Valid values are 'SYNC' and 'ASYNC'. The default value is 'SYNC'. |
rebuild-upon-startup-include-system-content | Specifies whether the system content area (the nodes below /jcr:system) should be indexed or not when rebuilding indexes at startup. The default value is 'FALSE' |
security-domain | The name of the security domain that should be used for JAAS authentication. The default value is 'modeshape-security' |
use-anonymous-upon-failed-authentication | Indicates that the failed authentication attempts will not result in a javax.jcr.LoginException , but will instead fall back to anonymous access. If anonymous access is not enabled, then failed login attempts throw a LoginException . The default value is 'false'. |
default-initial-content | The file which should be treated as the default initial content imported into all workspace. |
workspaces-initial-content | A set of (workspaceName, initial content file) pairs, which defines the custom initial content files for each workspace. |
node-types | A sequence of node-type elements, where the value of each element represents a path to a CND file. This file should be imported at repository startup. |
external-sources | A sequence of source elements, where each element contains the definition of an external source |
4.1.4. Sequencers
Sequencers are POJOs that implement a specific interface. Sequencers allow a hierarchical database repository to help you extract more meaning from the artifacts you already are managing, and makes it much easier for applications to find and use all that valuable information. You can configure a repository with any number of sequencers and each one applies to content in the repository matching specific patterns. When content in the repository changes, it is automatically checked to see which sequencers might be able to run on the changed content. If any of the sequencers match, the hierarchical database automatically calls them by supplying the changed content. At that point, the sequencer's job is to process the supplied input, extract meaningful information, and write that derived information back into the repository where it can be accessed, searched and used by your client applications.
The derived information can take almost any form, and it typically varies for each sequencer. For example, an image sequencer is provided that extracts the simple metadata from different kinds of image files (such as JPEG, GIF, and PNG).
Another example is the Compact Node Definition (CND) sequencer that processes the CND files to extract and produce a structured representation of the node type definitions, property definitions, and child node definitions contained within the file.
4.1.5. Adding and Removing Sequencers
You can use the CLI to dynamically add and remove sequencers.
Procedure 4.3. Task
- Add a sequencer to the sample repository that operates against comma-separated value (CSV) files uploaded under the
/files
node as shown below:[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/sequencer=delimited-text-sequencer:add( classname="org.modeshape.sequencer.text.DelimitedTextSequencer", module="org.modeshape.sequencer.text", path-expressions=["/files(//*.csv[*])/jcr:content[@jcr:data] => /derived/text/delimited/$1"], properties=[{ "splitPattern"=>"," }]) {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/sequencer=delimited-text-sequencer:read-resource() { "outcome" => "success", "result" => { "classname" => "org.modeshape.sequencer.text.DelimitedTextSequencer", "module" => "org.modeshape.sequencer.text", "path-expressions" => ["/files(//*.csv[*])/jcr:content[@jcr:data] => /derived/text/delimited/$1"], "properties" => [{"splitPattern" => ","}] } }
This sequencer has an additional splitPattern property that specifies the delimiter. - To remove a sequencer, invoke the remove operation on the appropriate item as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/sequencer=delimited-text-sequencer:remove() {"outcome" => "success"}
4.1.6. Specify Index Storage
Procedure 4.4. Task
- To specify where indexes are stored, add the index storage resource to your configuration as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=index-storage:add() {"outcome" => "success"}
- Once you add the index storage node, add the storage type with required optional parameters as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=index-storage/storage-type=master-file-index-storage:add(connection-factory-jndi-name=conn-name,queue-jndi-name=queue-name, path=/somepath, source-path=/someotherpath) {"outcome" => "success"}
4.1.7. Specify Binary Storage
Procedure 4.5. Task
- To specify where large binary values are stored, you need to first add the binary storage resource to your configuration as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=binary-storage:add() {"outcome" => "success"}
- Once you add the binary storage node, add the storage type with the required optional parameters as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=binary-storage/storage-type=file-binary-storage:add(path=/somepath) {"outcome" => "success"}
4.1.8. Configure Composite Binary Stores
Composite binary stores are different from the rest of the standard binary stores, as they can aggregate any number of standard binary stores.
Procedure 4.6. Task
- Configure composite binary stores via CLI as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=binary-storage/storage-type=composite-binary-storage:add()
Ensure that each nested store has astore-name
property that is unique within the composite store and that the appropriateresource-container
is used when adding the store. Corresponding to each of the standard binary stores, the followingresource-containers
are available:- nested-storage-type-file - for file system binary stores
- nested-storage-type-cache - for cache binary stores
- nested-storage-type-db - for database binary stores
- nested-storage-type-custom - for custom (user defined) binary stores
- Add a file system binary store to a composite store as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=binary-storage/storage-type=composite-binary-storage/nested-storage-type-file=filesystem1:add(store-name=filesystem1, path="/somepath")
You can remove a file system binary store from a composite store as shown below:[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/configuration=binary-storage/storage-type=composite-binary-storage/nested-storage-type-file=filesystem1:remove()
4.1.9. Add and Remove Authentication and Authorization Providers
You can use the CLI to dynamically add and remove custom authentication and authorization providers.
Procedure 4.7. Task
- If your
org.modeshape.jcr.security.AuthorizationProvider
implementation is namedorg.example.MyAuthProvider
and is added to a neworg.example.auth
module, then use the following command to add this provider to the "sample" repository:[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/authenticator=custom:add(classname="org.example.MyAuthProvider", module="org.example.auth") {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/authenticator=jaas:read-resource() { "outcome" => "success", "result" => { "classname" => "org.modeshape.jcr.security.JaasProvider", "module" => "org.modeshape", "properties" => undefined } }
- To remove an authentication provider, invoke the "remove" operation on the appropriate item as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/authenticator=custom:remove() {"outcome" => "success"}
4.1.10. Set Instance-Level Fields on Provider Instances
Instance-level fields can be set on the provider instances.
Procedure 4.8. Task
- You can set the
auth-domain
field on the MyAuthProvider instance to the String value "global". To do this, add them via theproperties
parameter, which is a list of documents that each contain a single name-value pair:[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/authenticator=custom:add(classname="org.example.MyAuthProvider", module="org.example.auth", properties=[ {"foo"=>"bar"}, {"baz"=>"bam"} ] ) {"outcome" => "success"} /subsystem=modeshape/repository=sample/authenticator=custom:read-resource() { "outcome" => "success", "result" => { "classname" => "org.example.MyAuthProvider", "module" => "org.example.auth", "properties" => [ {"foo" => "bar"}, {"baz" => "bam"} ] } }
4.1.11. Add JDBC Data Source
Prerequisities
- Before adding a data source, add the driver as shown below:
[standalone@localhost:9999 /] /subsystem=datasources/jdbc-driver=modeshape-driver:add(driver-name="modeshape-driver", driver-module-name="org.modeshape.jdbc", driver-class-name="org.modeshape.jdbc.LocalJcrDriver") {"outcome" => "success"}
Procedure 4.9. Task
- Add the JDBC Data Source as shown below:
[standalone@localhost:9999 /] /subsystem=datasources/data-source="java:/datasources/ModeShapeDS":add(jndi-name="java:/datasources/ModeShapeDS",driver-name="modeshape-driver",connection-url="jdbc:jcr:jndi:jcr?repositoryName=artifacts",user-name="admin",password="admin") {"outcome" => "success"}
Note
A preconfigured datasource
java:/datasources/ModeShapeDS
already exists by default.
4.1.12. Add and Remove External Sources
Procedure 4.10. Task
- You can add one or more external sources to an existing repository to enable federation. Here is an example on how you can link an external file system source(via the FileSytemConnector) to the sample repository using the CLI:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/source=fsSource:add(classname="org.modeshape.connector.filesystem.FileSystemConnector",properties=[{"directoryPath"=>"."}], readonly="true", projections=["default:/projection1 => /"], cacheTtlSeconds="1") {"outcome" => "success"} [standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/source=fsSource:read-resource() { "outcome" => "success", "result" => { "cacheTtlSeconds" => "1", "classname" => "org.modeshape.connector.filesystem.FileSystemConnector", "module" => undefined, "projections" => ["default:/projection1 => /"], "properties" => [{"directoryPath" => "."}], "queryable" => undefined, "readonly" => "true" } }
- Specify the following attributes when adding an external source:
- classname (mandatory) - The fully qualified name of the
Connector
class that allows content to be retrieved and written to that external source. - module (optional) - The name of the JBoss EAP module where the above class is found.
- projections (optional) - A list of projection expressions representing predefined projection paths for the source. Projections can either be defined here or programmatically using the
FederationManager.createProjection(...)
method. - queryable (optional) - A flag indicating if the content exposed from the external source should be indexed by the repository or not. By default, this flag is set.
- readonly (optional) - A flag indicating if only read or both read and write is possible on the source.
- cacheTtlSeconds (optional) - The number of seconds any given node is to be held in the cache of the corresponding workspace from the external source.
- properties (optional) - An array of key-value pairs that allow any custom attributes to be passed down on the Connector implementation class.
- To remove an external source, invoke the remove method on the source as shown below:
[standalone@localhost:9999 /] /subsystem=modeshape/repository=sample/source=fsSource:remove() {"outcome" => "success"}
4.1.13. Working with Batch Mode
You can combine all commands except for the initial
/extension=org.modeshape:add()
command, into a batch operation:
[standalone@localhost:9999 /] /extension=org.modeshape:add() {"outcome" => "success"} [standalone@localhost:9999 /] batch [standalone@localhost:9999 / #] (paste the commands here) [standalone@localhost:9999 / #] run-batch The batch executed successfully.You can edit the batches before runnning them and paste multiple commands into a batch.
4.1.14. Clustering Configuration
Before configuring the hierarchical database to run in a cluster, ensure the JGroups subsystem is present in the JBoss EAP configuration.
Then the following parts need to be configured.
- Replicated Infinispan caches for the repository store and the binary store:
/subsystem=infinispan/cache-container=modeshape:add(module="org.modeshape") /subsystem=infinispan/cache-container=modeshape/transport=TRANSPORT:add(lock-timeout="60000") /subsystem=infinispan/cache-container=modeshape/replicated-cache=sample:add(mode="SYNC", batching="true") /subsystem=infinispan/cache-container=modeshape/replicated-cache=sample/transaction=TRANSACTION:add(mode=NON_XA) /subsystem=infinispan/cache-container=modeshape/replicated-cache=sample/file-store=FILE_STORE:add(path="modeshape/store/sample-${jboss.node.name}",relative-to="jboss.server.data.dir",passivation=false,purge=false) /subsystem=infinispan/cache-container=modeshape-binary-store:add(module="org.modeshape") /subsystem=infinispan/cache-container=modeshape-binary-store/transport=TRANSPORT:add(lock-timeout="60000") /subsystem=infinispan/cache-container=modeshape-binary-store/replicated-cache=sample-binary-data:add(mode="SYNC", batching="true") /subsystem=infinispan/cache-container=modeshape-binary-store/replicated-cache=sample-binary-data/transaction=TRANSACTION:add(mode=NON_XA) /subsystem=infinispan/cache-container=modeshape-binary-store/replicated-cache=sample-binary-data/file-store=FILE_STORE:add(path="modeshape/binary-store/sample-data-${jboss.node.name}",relative-to="jboss.server.data.dir",passivation=false,purge=false) /subsystem=infinispan/cache-container=modeshape-binary-store/replicated-cache=sample-binary-metadata:add(mode="SYNC", batching="true") /subsystem=infinispan/cache-container=modeshape-binary-store/replicated-cache=sample-binary-metadata/transaction=TRANSACTION:add(mode=NON_XA) /subsystem=infinispan/cache-container=modeshape-binary-store/replicated-cache=sample-binary-metadata/file-store=FILE_STORE:add(path="modeshape/binary-store/sample-metadata-${jboss.node.name}",relative-to="jboss.server.data.dir",passivation=false,purge=false)
- The main repository:
/subsystem=modeshape/repository=sample:add(cache-container="modeshape",cache-name="sample",cluster-name="modeshape-sample",cluster-stack="tcp",security-domain="modeshape-security")
- Indexing:
/subsystem=modeshape/repository=sample/configuration=index-storage:add() /subsystem=modeshape/repository=sample/configuration=index-storage/storage-type=local-file-index-storage:add(path="modeshape/indexes/sample-indexes-${jboss.node.name}")
- Binary Storage:
/subsystem=modeshape/repository=sample/configuration=binary-storage:add() /subsystem=modeshape/repository=sample/configuration=binary-storage/storage-type=cache-binary-storage:add(data-cache-name="sample-binary-data", metadata-cache-name="sample-binary-metadata", cache-container="modeshape-binary-store")