[dna-commits] DNA SVN: r1005 - in trunk/docs/reference/src/main/docbook/en-US: content/core and 1 other directory.
dna-commits at lists.jboss.org
dna-commits at lists.jboss.org
Tue Jun 9 02:11:42 EDT 2009
Author: rhauch
Date: 2009-06-09 02:11:41 -0400 (Tue, 09 Jun 2009)
New Revision: 1005
Modified:
trunk/docs/reference/src/main/docbook/en-US/content/core/connector.xml
trunk/docs/reference/src/main/docbook/en-US/content/core/graph.xml
trunk/docs/reference/src/main/docbook/en-US/custom.dtd
Log:
Added to the graph chapter new sections on requests, request processors, and observation.
Modified: trunk/docs/reference/src/main/docbook/en-US/content/core/connector.xml
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/content/core/connector.xml 2009-06-09 04:32:58 UTC (rev 1004)
+++ trunk/docs/reference/src/main/docbook/en-US/content/core/connector.xml 2009-06-09 06:11:41 UTC (rev 1005)
@@ -51,20 +51,20 @@
in one spot, using one powerful standard API.
</para>
<sect1 id="connectors">
- <title>Repository connectors</title>
+ <title>Connectors</title>
<para>
With JBoss DNA, your applications use the <ulink url="&JSR170;">JCR API</ulink> to work with the repository,
but the DNA repository transparently fetches the information from different kinds of repositories and storage systems,
not just a single purpose-built store. This is fundamentally what makes JBoss DNA different.
</para>
<para>How does JBoss DNA do this? At the heart of JBoss DNA and it's JCR implementation is a simple graph-based
- <emphasis>repository connector</emphasis> system. Essentially, JBoss DNA's JCR implementation uses a single
- repository connector to access all content:
+ <emphasis>connector</emphasis> system. Essentially, JBoss DNA's JCR implementation uses a single
+ connector to access all content:
<figure id="dnajcr-and-connector">
- <title>JBoss DNA's JCR implementation delegates to a repository connector</title>
+ <title>JBoss DNA's JCR implementation delegates to a connector</title>
<graphic align="center" scale="100" fileref="dnajcr-and-connector.png"/>
</figure>
- That single repository connector could use an in-memory repository, a JBoss Cache instance (including those that are clustered and replicated),
+ That single connector could use an in-memory repository, a JBoss Cache instance (including those that are clustered and replicated),
or a federated repository where content from multiple sources is unified.
<figure id="dna-connectors-0.2">
<title>JBoss DNA can put JCR on top of multiple kinds of systems</title>
@@ -128,9 +128,9 @@
A repository source instance is then used to establish <emphasis role="strong">connections</emphasis> to
that source. A connector provides an implementation of the &RepositoryConnection; interface, which
defines methods for interacting with the external system. In particular, the <code>execute(...)</code> method
- takes an &ExecutionContext; instance and a &Request; object. The &ExectuionContext; object defines the
- environment in which the processing is occurring, including information about the JAAS &Subject; and &LoginContext;.
- The &Request; object describes the requested operations on the content, with different concrete subclasses
+ takes an &ExecutionContext; instance and a &Request; object. The &ExecutionContext; object defines the
+ environment in which the processing is occurring,
+ while the &Request; object describes the requested operations on the content, with different concrete subclasses
representing each type of activity. Examples of commands include (but not limited to) getting a node, moving a node, creating a node,
changing a node, and deleting a node. And, if the repository source is able to participate in JTA/JTS distributed transactions, then the
&RepositoryConnection; must implement the <code>getXaResource()</code> method by returning
@@ -161,123 +161,15 @@
JBoss DNA components, including the <link linkend="jcr">JCR</link> implementation.
</para>
<para>
- So, we've so far learned what a repository connector is and how they're used to establish connections to the underlying sources
- and access the content in those sources. In the <link linkend="repository-service">next section</link>, we'll show how these
- source instances can be configured, managed, and their connections pooled. After that, we'll look review JBoss DNA's
- <link linkend="connector-library">existing connectors</link> and show how to <link linkend="custom-connectors">create your own connectors</link>.
+ So, we've so far learned what a connector is and how they're used to establish connections to the underlying sources
+ and access the content in those sources. Next we'll show how connectors expose the notion of workspaces, and describe
+ how to <link linkend="custom-connectors">create your own connectors</link>.
</para>
</sect1>
- <sect1 id="repository-workspaces">
- <title>Workspaces</title>
- <para>The <link linkend="graph-api-workspaces">previous chapter</link> talked about how connector expose their information through the graph language of JBoss DNA.
- This is true, except that we didn't dive into too much of the detail. JBoss DNA graphs have the notion of <emphasis>workspaces</emphasis>
- in which the content appears, and its very easy for clients using the graph to switch between workspaces. In fact,
- workspaces differ from each other in that they provide different views of the same information.
- </para>
- <para>Consider a source control system, like SVN or CVS. These systems provide different views of the source code:
- a mainline development branch as well as other branches (or tags) commonly used for releases. So, just like one source
- file might appear in the mainline branch as well as the previous two release branches, a node in a repository source
- might appear in multiple workspaces.
- </para>
- <para>
- However, each connector can kind of decide how (or whether) it uses workspaces. For example, there may be no overlap
- in the content between workspaces. Or a connector might only expose a single workspace (in other words, there's only one
- "default" workspace).
- </para>
- </sect1>
- <sect1 id="repository-service">
- <title>Repository Service</title>
- <para>The JBoss DNA &RepositoryService; is the component that manages the <emphasis>repository sources</emphasis>
- and the connections to them. &RepositorySource; instances can be programmatically added to the service, but
- the service can actually read its configuration from a configuration repository (which, by the way, is represented by a
- just another &RepositorySource; instance that's usually added programmatically to the service). The service connects to
- the configuration repository, reads the content in a particular area, and automatically sets up the &RepositorySource; instances
- per the information found in the configuration repository.
- </para>
- <para>
- The &RepositoryService; also transparently maintains for each source a pool of reusable connections. The pooling properties
- can be controlled via the configuration repository, or adjusted programmatically.
- </para>
- <para>
- Using a repository, then, involves simply asking the &RepositoryService; for a &RepositoryConnection;
- to the repository given the repository's name. If a source exists with that name, the service checks out a connection from
- the source's pool. The resulting connection is actually a wrapper around the underlying pooled connection, so the
- component that requested the connection can simply close it, and under the covers the actual connection is simply returned
- to the pool.
- </para>
- <para>To instantiate the &RepositoryService;, we need to first have a few other objects:
- <itemizedlist>
- <listitem>
- <para>
- A &ExecutionContext; instance, as discussed <link linkend="execution-context">earlier</link>.
- </para>
- </listitem>
- <listitem>
- <para>
- A &RepositoryLibrary; instance that manages the list of &RepositorySource; instances,
- properly injects the execution contexts into each repository source, and provides a configurable pool of connections
- for each source.
- </para>
- </listitem>
- <listitem>
- <para>
- A <emphasis>configuration repository</emphasis> that contains descriptions of all of the repository sources
- as well as any information those sources need. Because this is a regular repository, this could be a simple
- repository with content loaded from an XML file, or it could be a shared
- central repository with information about all of the JBoss DNA repositories used across your organization.
- </para>
- </listitem>
- </itemizedlist>
- With these components in place, we can then instantiate the &RepositoryService; and start it (using its
- &ServiceAdministrator;). During startup, the service reads the configuration repository and loads any
- defined &RepositorySource; instances into the repository library, using the class loader factory
- (available in the &ExecutionContext;) to obtain.
- </para>
- <para>
- Here's sample code that shows how to set up and start the repository service. You can see something similar
- in the example application in the <code>startRepositories()</code> method of the
- <code>org.jboss.example.dna.repository.RepositoryClient</code> class.
- </para>
- <programlisting>
- // Create the top-level execution context with all standard components ...
- &ExecutionContext; context = new ExecutionContext();
-
- // Create the library for the RepositorySource instances ...
- &RepositoryLibrary; sources = new &RepositoryLibrary;(context);
-
- // Load into the source manager the repository source for the configuration repository ...
- &InMemoryRepositorySource; configSource = new &InMemoryRepositorySource;();
- configSource.setName("Configuration");
- sources.addSource(configSource);
-
- // Now instantiate the Repository Service ...
- &RepositoryService; service = new &RepositoryService;(sources, configSource.getName(), context);
- service.getAdministrator().start();
- </programlisting>
-
- <para>After startup completes, the repositories are ready to be used. The client application obtains the list of repositories
- and presents them to the user. When the user selects one, the client application starts navigating that repository
- starting at its root node (e.g., the "/" path). As you type a command to list the contents of the current node or to
- "change directories" to a different node, the client application obtains the information for the node using a simple
- procedure:
- <orderedlist>
- <listitem>
- <para>Get a connection to the repository.</para>
- </listitem>
- <listitem>
- <para>Using the connection, find the current node and read its properties and children, putting the information
- into a simple Java plain old Java object (POJO).</para>
- </listitem>
- <listitem>
- <para>Close the connection to the repository (in a finally block to ensure it always happens).</para>
- </listitem>
- </orderedlist>
- </para>
- </sect1>
<sect1 id="connector-library">
- <title>Out-of-the-box repository connectors</title>
+ <title>Out-of-the-box connectors</title>
<para>
- A number of repository connectors are already available in JBoss DNA, and are outlined in detail
+ A number of connectors are already available in JBoss DNA, and are outlined in detail
<link linkend="provied-connectors-part">later in the document</link>.
Note that we do want to build <ulink url="https://jira.jboss.org/jira/secure/IssueNavigator.jspa?reset=true&mode=hide&pid=12310520&sorter/order=DESC&sorter/field=priority&resolution=-1&component=12311441">more connectors</ulink>
in the upcoming releases.
@@ -286,7 +178,7 @@
<sect1 id="custom-connectors">
<title>Writing custom connectors</title>
<para>
- There may come a time when you want to tackle creating your own repository connector. Maybe the connectors we provide out-of-the-box
+ There may come a time when you want to tackle creating your own connector. Maybe the connectors we provide out-of-the-box
don't work with your source. Maybe you want to use a different cache system.
Maybe you have a system that you want to make available through a JBoss DNA repository. Or, maybe you're
a contributor and want to help us round out our library with a new connector. No matter what the reason, creating a new connector
@@ -356,7 +248,7 @@
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-graph</artifactId>
- <version>0.4</version>
+ <version>0.5</version>
</dependency>
]]></programlisting>
<para>
@@ -371,17 +263,18 @@
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-graph</artifactId>
- <version>0.4</version>
+ <version>0.5</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-common</artifactId>
- <version>0.4</version>
+ <version>0.5</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
+<!-- Unit testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -441,6 +334,37 @@
Most of the semantics of the class are defined by the &RepositorySource; and inherited interface.
However, there are a few characteristics that are worth mentioning here.
</para>
+ <sect3 id="repository-workspaces">
+ <title>Workspaces</title>
+ <para>The <link linkend="graph-api-workspaces">previous chapter</link> talked about how connector expose their information through the graph language of JBoss DNA.
+ This is true, except that we didn't dive into too much of the detail. JBoss DNA graphs have the notion of <emphasis>workspaces</emphasis>
+ in which the content appears, and its very easy for clients using the graph to switch between workspaces. In fact,
+ workspaces differ from each other in that they provide different views of the same information.
+ </para>
+ <para>Consider a source control system, like SVN or CVS. These systems provide different views of the source code:
+ a mainline development branch as well as other branches (or tags) commonly used for releases. So, just like one source
+ file might appear in the mainline branch as well as the previous two release branches, a node in a repository source
+ might appear in multiple workspaces.
+ </para>
+ <para>
+ However, each connector can kind of decide how (or whether) it uses workspaces. For example, there may be no overlap
+ in the content between workspaces. Or a connector might only expose a single workspace (in other words, there's only one
+ "default" workspace).
+ </para>
+ </sect3>
+ <sect3 id="connector_events">
+ <title>Broadcasting events</title>
+ <para>
+ When your &RepositorySource; instance is put into the library within a running JBoss DNA system,
+ the <code>initialize(&RepositoryContext;)</code> method will be called on the instance.
+ The supplied &RepositoryContext; object represents the context in which the &RepositorySource;
+ is running, and provides access to an &ExecutionContext;, a &RepositoryConnectionFactory; that can be used
+ to obtain connections to other sources, and an &Observer; of your source that should be called with
+ events describing the &Changes; being made within the source, either as a result of &ChangeRequest; operations being
+ performed on this source, or as a result of operations being performed on the content from outside
+ the source.
+ </para>
+ </sect3>
<sect3 id="connector_cache_policy">
<title>Cache policy</title>
<para>
@@ -538,7 +462,7 @@
<para>
One job of the &RepositorySource; implementation is to create connections to the underlying sources.
Connections are represented by classes that implement the &RepositoryConnection; interface, and creating this
- class is the next step in writing a repository connector. This is what we'll cover in this section.
+ class is the next step in writing a connector. This is what we'll cover in this section.
</para>
<para>
The &RepositoryConnection; interface is pretty straightforward:
@@ -580,13 +504,6 @@
boolean ping( long time, &TimeUnit; unit ) throws InterruptedException;
/**
- * Set the listener that is to receive notifications to changes to content within this source.
- *
- * @param listener the new listener, or null if no component is interested in the change notifications
- */
- void setListener( &RepositorySourceListener; listener );
-
- /**
* Get the default cache policy for this repository. If none is provided, a global cache policy
* will be used.
*
@@ -601,8 +518,7 @@
* @param request the request to be executed; never null
* @throws RepositorySourceException if there is a problem loading the node data
*/
- void execute( &ExecutionContext; context,
- &Request; request ) throws &RepositorySourceException;;
+ void execute( &ExecutionContext; context, &Request; request ) throws &RepositorySourceException;;
/**
* Close this connection to signal that it is no longer needed and that any accumulated
@@ -618,6 +534,7 @@
a connection pool.
</para>
<para>
+ If the connector is able to publish events, then
DNA hasn't yet defined the event mechanism, so connectors don't have any methods to invoke on the &RepositorySourceListener;.
This will be defined in the next release, so feel free to manage the listeners now. Note that by default the &RepositorySourceCapabilities; returns
<code>false</code> for <code>supportsEvents()</code>.
@@ -629,293 +546,12 @@
as well as the subject performing the request. This was discussed <link linkend="execution-context">earlier</link>.
</para>
<para>
- The second parameter, however, represents a request that is to be processed by the connector. Request objects can
- take many different forms, as there are different classes for each kind of request (see the table below).
+ The second parameter, however, represents a &Request; that is to be processed by the connector. Request objects can
+ take many different forms, as there are different classes for each kind of request (see the
+ <link linkend="graph-requests">previous chapter</link> for details).
Each request contains the information a connector needs to do the processing, and it also is the place
where the connector places the results (or the error, if one occurs).
</para>
- <para>
- How do the requests reference a node (or nodes)? Since requests are coming from a client, the client
- may identify a particular node using a &Location; object that is created with:
- <itemizedlist>
- <listitem>
- <para>the &Path; to the node; or</para>
- </listitem>
- <listitem>
- <para>one or more <emphasis>identification properties</emphasis> that are likely source=specific
- and that are represented with &Property; objects; or</para>
- </listitem>
- <listitem>
- <para>a combination of both.</para>
- </listitem>
- </itemizedlist>
- So, when a client knows the path or the identification properties, they can create a &Location;. However,
- all of the requests return &Location; objects, so often times the client simply uses the location
- from a previous request. Since &Location; is an immutable class, it is perfectly safe to reuse them.
- </para>
- <para>
- One more thing about locations: while the request may have an incomplete location (e.g., a path but no
- identification properties), the connector is expected to set on the request the <emphasis>actual</emphasis>
- location that contains the path and all identification properties. So as long as the client
- reuses the actual locations in subsequent requests, the connectors will have the benefit of having
- both the path and identification properties. Connectors can then be written to leverage this
- information, although the connector should still perform as expected when requests have incomplete locations.
- </para>
- <table frame='all'>
- <title>Types of Node Operation Requests</title>
- <tgroup cols='2' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>ReadNodeRequest</entry>
- <entry>
- A request to read from the named workspace in the source a node's properties and children.
- The node may be specified by path and/or by identification properties.
- The connector returns all properties and the locations for all children,
- or sets a &PathNotFoundException; error on the request if the node did not exist in the workspace.
- If the node is found, the connector sets on the request the actual location of the node (including the path and identification properties).
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>VerifyNodeExistsRequest</entry>
- <entry>
- A request to verify the existance of a node at the specified location in the named workspace of the source.
- The connector returns all the actual location for the node if it exists, or
- sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>ReadAllPropertiesRequest</entry>
- <entry>
- A request to read from the named workspace in the source all of the properties of a node.
- The node may be specified by path and/or by identification properties.
- The connector returns all properties that were found on the node,
- or sets a &PathNotFoundException; error on the request if the node did not exist in the workspace.
- If the node is found, the connector sets on the request the actual location of the node (including the path and identification properties).
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>ReadPropertyRequest</entry>
- <entry>
- A request to read from the named workspace in the source a single property of a node.
- The node may be specified by path and/or by identification properties,
- and the property is specified by name.
- The connector returns the property if found on the node,
- or sets a &PathNotFoundException; error on the request if the node or property did not exist in the workspace.
- If the node is found, the connector sets on the request the actual location of the node (including the path and identification properties).
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>ReadAllChildrenRequest</entry>
- <entry>
- A request to read from the named workspace in the source all of the children of a node.
- The node may be specified by path and/or by identification properties.
- The connector returns an ordered list of locations for each child found on the node,
- an empty list if the node had no children,
- or sets a &PathNotFoundException; error on the request if the node did not exist in the workspace.
- If the node is found, the connector sets on the request the actual location of the parent node (including the path and identification properties).
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>ReadBlockOfChildrenRequest</entry>
- <entry>
- A request to read from the named workspace in the source a block of children of a node, starting with the n<superscript>th</superscript> children.
- This is designed to allow paging through the children, which is much more efficient for large numbers of children.
- The node may be specified by path and/or by identification properties, and the block
- is defined by a starting index and a count (i.e., the block size).
- The connector returns an ordered list of locations for each of the node's children found in the block,
- or an empty list if there are no children in that range.
- The connector also sets on the request the actual location of the parent node (including the path and identification properties)
- or sets a &PathNotFoundException; error on the request if the parent node did not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>ReadNextBlockOfChildrenRequest</entry>
- <entry>
- A request to read from the named workspace in the source a block of children of a node, starting with the children that immediately follow
- a previously-returned child.
- This is designed to allow paging through the children, which is much more efficient for large numbers of children.
- The node may be specified by path and/or by identification properties, and the block
- is defined by the location of the node immediately preceding the block and a count (i.e., the block size).
- The connector returns an ordered list of locations for each of the node's children found in the block,
- or an empty list if there are no children in that range.
- The connector also sets on the request the actual location of the parent node (including the path and identification properties)
- or sets a &PathNotFoundException; error on the request if the parent node did not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>ReadBranchRequest</entry>
- <entry>
- A request to read a portion of a subgraph that has as its root a particular node, up to a maximum depth.
- This request is an efficient mechanism when a branch (or part of a branch) is to be navigated and processed,
- and replaces some non-trivial code to read the branch iteratively using multiple <code>ReadNodeRequest</code>s.
- The connector reads the branch to the specified maximum depth, returning the properties and children for all
- nodes found in the branch.
- The connector also sets on the request the actual location of the branch's root node (including the path and identification properties).
- The connector sets a &PathNotFoundException; error on the request if the node at
- the top of the branch does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>CreateNodeRequest</entry>
- <entry>
- A request to create a node at the specified location and setting on the new node the properties included in the request.
- The connector creates the node at the desired location, adjusting any same-name-sibling indexes as required.
- (If an SNS index is provided in the new node's location, existing children with the same name after that SNS index
- will have their SNS indexes adjusted. However, if the requested location does not include a SNS index, the new
- node is added after all existing children, and it's SNS index is set accordingly.)
- The connector also sets on the request the actual location of the new node (including the path and identification properties)..
- The connector sets a &PathNotFoundException; error on the request if the parent node does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>RemovePropertiesRequest</entry>
- <entry>
- A request to remove a set of properties on an existing node. The request contains the location of the node as well as the
- names of the properties to be removed. The connector performs these changes and sets on the request the
- actual location (including the path and identification properties) of the node.
- The connector sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>UpdatePropertiesRequest</entry>
- <entry>
- A request to set or update properties on an existing node. The request contains the location of the node as well as the
- properties to be set and those to be deleted. The connector performs these changes and sets on the request the
- actual location (including the path and identification properties) of the node.
- The connector sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>RenameNodeRequest</entry>
- <entry>
- A request to change the name of a node. The connector changes the node's name, adjusts all SNS indexes
- accordingly, and returns the actual locations (including the path and identification properties) of both the original
- location and the new location.
- The connector sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>CopyBranchRequest</entry>
- <entry>
- A request to copy a portion of a subgraph that has as its root a particular node, up to a maximum depth.
- The request includes the name of the workspace where the original node is located as well as the name of the
- workspace where the copy is to be placed (these may be the same, but may be different).
- The connector copies the branch from the original location, up to the specified maximum depth, and places a copy
- of the node as a child of the new location.
- The connector also sets on the request the actual location (including the path and identification properties)
- of the original location as well as the location of the new copy.
- The connector sets a &PathNotFoundException; error on the request if the node at
- the top of the branch does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if one of the named workspaces does not exist.
- </entry>
- </row>
- <row>
- <entry>MoveBranchRequest</entry>
- <entry>
- A request to move a subgraph that has a particular node as its root.
- The connector moves the branch from the original location and places it as child of the specified new location.
- The connector also sets on the request the actual location (including the path and identification properties)
- of the original and new locations. The connector will adjust SNS indexes accordingly.
- The connector sets a &PathNotFoundException; error on the request if the node that is to be moved or the
- new location do not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>DeleteBranchRequest</entry>
- <entry>
- A request to delete an entire branch specified by a single node's location.
- The connector deletes the specified node and all nodes below it, and sets the actual location,
- including the path and identification properties, of the node that was deleted.
- The connector sets a &PathNotFoundException; error on the request if the node being deleted does not exist in the workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>CompositeRequest</entry>
- <entry>
- A request that actually comprises multiple requests (none of which will be a composite).
- The connector simply processes all of the requests in the composite request, but should set on the composite
- request any error (usually the first error) that occurs during processing of the contained requests.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- <para>There are also requests that deal with workspaces:</para>
- <table frame='all'>
- <title>Types of Workspace Requests</title>
- <tgroup cols='2' align='left' colsep='1' rowsep='1'>
- <colspec colname='c1' colwidth="1*"/>
- <colspec colname='c2' colwidth="1*"/>
- <thead>
- <row>
- <entry>Name</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>GetWorkspacesRequest</entry>
- <entry>
- A request to obtain the names of the existing workspaces that are accessible to the caller.
- </entry>
- </row>
- <row>
- <entry>VerifyWorkspaceRequest</entry>
- <entry>
- A request to verify that a workspace with a particular name exists.
- The connector returns the actual location for the root node if the workspace exists, as well as the actual name of the workspace
- (e.g., the default workspace name if a null name is supplied).
- </entry>
- </row>
- <row>
- <entry>CreateWorkspaceRequest</entry>
- <entry>
- A request to create a workspace with a particular name.
- The connector returns the actual location for the root node if the workspace exists, as well as the actual name of the workspace
- (e.g., the default workspace name if a null name is supplied).
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace already exists.
- </entry>
- </row>
- <row>
- <entry>DestroyWorkspaceRequest</entry>
- <entry>
- A request to destroy a workspace with a particular name.
- The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
- </entry>
- </row>
- <row>
- <entry>CloneWorkspaceRequest</entry>
- <entry>
- A request to clone one named workspace as another new named workspace.
- The connector sets a &InvalidWorkspaceException; error on the request if the original workspace does not exist,
- or if the new workspace already exists.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
<para>
Although there are over a dozen different kinds of requests, we do anticipate adding more in future releases.
For example, DNA will likely support searching repository content in sources through an additional subclass of &Request;.
@@ -923,7 +559,8 @@
</para>
<para>
A connector is technically free to implement the <code>execute(...)</code> method in any way, as long as the semantics
- are maintained. But DNA provides a &RequestProcessor; class that can simplify writing your own connector and at the
+ are maintained. But as discussed in the <link linkend="graph-request-processors">previous chapter</link>, JBoss DNA provides
+ a &RequestProcessor; class that can simplify writing your own connector and at the
same time help insulate your connector from new kinds of requests that may be added in the future. The &RequestProcessor;
is an abstract class that defines a <code>process(...)</code> method for each concrete &Request; subclass.
In other words, there is a <code>process(CompositeRequest)</code> method, a <code>process(ReadNodeRequest)</code> method,
@@ -984,28 +621,16 @@
don't become polluted with slow-running tests that break if the external system is not available.
</para>
</sect2>
- <sect2 id="deploying_custom_connectors">
- <title>Configuring and deploying custom connectors</title>
- <para>
- After building your connector project, you need to configure the JBoss DNA components your application is using so
- that they use your connector. In a lot of cases, this will entail instantiating your connector's &RepositorySource; class,
- setting the various properties, and registering it with a &RepositoryLibrary;. Or, it will entail using a configuration
- repository to use your source and letting &RepositoryService; instantiate and set up your &RepositorySource; instance.
- Or, you can just instantiate and set it up manually, passing the instance to whatever component needs it.
- </para>
- <para>
- And of course you have to make the JAR file containing your connector (as well as any dependency JARs) available to
- your application's classpath.
- </para>
- </sect2>
</sect1>
<sect1>
<title>Summary</title>
<para>
- In this chapter, we covered all the aspects of JBoss DNA repositories, including the connector framework,
+ In this chapter, we covered all the aspects of JBoss DNA connectors, including the connector API,
how DNA's JCR implementation works with connectors, what connectors are available (and how to use them),
and how to write your own connector. So now that you know how to set up and use JBoss DNA repositories,
- the <link linkend="jcr">next chapter</link> describes how you can leverage JBoss DNA's JCR implementation.
+ the <link linkend="sequencing-framework">next chapter</link> describes the sequencing framework and how
+ to build your own custom sequencers. After that, we'll get into <link linkend="configuration">how to configure
+ JBoss DNA</link> to use the connectors and sequencers.
</para>
</sect1>
</chapter>
Modified: trunk/docs/reference/src/main/docbook/en-US/content/core/graph.xml
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/content/core/graph.xml 2009-06-09 04:32:58 UTC (rev 1004)
+++ trunk/docs/reference/src/main/docbook/en-US/content/core/graph.xml 2009-06-09 06:11:41 UTC (rev 1005)
@@ -962,6 +962,441 @@
</para>
</sect2>
</sect1>
+ <sect1 id="graph-requests">
+ <title>Requests</title>
+ <para>
+ JBoss DNA &Graph; objects operate upon the underlying graph content, but we haven't really talked about how that works.
+ Recall that the &Graph; objects don't maintain any stateful representation of the content, but instead submit requests
+ to the underlying graph and return representations of the requested portions of the content.
+ This section focuses on what those requests look like, since they'll actually become very important when
+ working with <link linkend="connector-framework">connectors</link> in the next chapter.
+ </para>
+ <para>
+ A graph &Request; is an encapsulation of a command that is to be executed by the underlying graph owner (typically
+ a connector). Request objects can take many different forms, as there are different classes for each kind of request.
+ Each request contains the information needed to complete the processing, and it also is the place
+ where the results (or error) are recorded.
+ </para>
+ <para>
+ The &Graph; object creates the &Request; objects using &Location; objects to identify the node (or nodes) that are the
+ subject of the request. The &Graph; can either submit the request immediately, or it can batch multiple requests
+ together into "units of work". The submitted requests are then processed by the underlying system (e.g., connector)
+ and returned back to the &Graph; object, which then extracts and returns the results.
+ </para>
+ <para>
+ There are actually quite a few different types of &Request; classes:
+ </para>
+ <table frame='all'>
+ <title>Types of Read Requests</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>ReadNodeRequest</entry>
+ <entry>
+ A request to read from the named workspace in the source a node's properties and children.
+ The node may be specified by path and/or by identification properties.
+ The connector returns all properties and the locations for all children,
+ or sets a &PathNotFoundException; error on the request if the node did not exist in the workspace.
+ If the node is found, the connector sets on the request the actual location of the node (including the path and identification properties).
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>VerifyNodeExistsRequest</entry>
+ <entry>
+ A request to verify the existance of a node at the specified location in the named workspace of the source.
+ The connector returns all the actual location for the node if it exists, or
+ sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>ReadAllPropertiesRequest</entry>
+ <entry>
+ A request to read from the named workspace in the source all of the properties of a node.
+ The node may be specified by path and/or by identification properties.
+ The connector returns all properties that were found on the node,
+ or sets a &PathNotFoundException; error on the request if the node did not exist in the workspace.
+ If the node is found, the connector sets on the request the actual location of the node (including the path and identification properties).
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>ReadPropertyRequest</entry>
+ <entry>
+ A request to read from the named workspace in the source a single property of a node.
+ The node may be specified by path and/or by identification properties,
+ and the property is specified by name.
+ The connector returns the property if found on the node,
+ or sets a &PathNotFoundException; error on the request if the node or property did not exist in the workspace.
+ If the node is found, the connector sets on the request the actual location of the node (including the path and identification properties).
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>ReadAllChildrenRequest</entry>
+ <entry>
+ A request to read from the named workspace in the source all of the children of a node.
+ The node may be specified by path and/or by identification properties.
+ The connector returns an ordered list of locations for each child found on the node,
+ an empty list if the node had no children,
+ or sets a &PathNotFoundException; error on the request if the node did not exist in the workspace.
+ If the node is found, the connector sets on the request the actual location of the parent node (including the path and identification properties).
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>ReadBlockOfChildrenRequest</entry>
+ <entry>
+ A request to read from the named workspace in the source a block of children of a node, starting with the n<superscript>th</superscript> children.
+ This is designed to allow paging through the children, which is much more efficient for large numbers of children.
+ The node may be specified by path and/or by identification properties, and the block
+ is defined by a starting index and a count (i.e., the block size).
+ The connector returns an ordered list of locations for each of the node's children found in the block,
+ or an empty list if there are no children in that range.
+ The connector also sets on the request the actual location of the parent node (including the path and identification properties)
+ or sets a &PathNotFoundException; error on the request if the parent node did not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>ReadNextBlockOfChildrenRequest</entry>
+ <entry>
+ A request to read from the named workspace in the source a block of children of a node, starting with the children that immediately follow
+ a previously-returned child.
+ This is designed to allow paging through the children, which is much more efficient for large numbers of children.
+ The node may be specified by path and/or by identification properties, and the block
+ is defined by the location of the node immediately preceding the block and a count (i.e., the block size).
+ The connector returns an ordered list of locations for each of the node's children found in the block,
+ or an empty list if there are no children in that range.
+ The connector also sets on the request the actual location of the parent node (including the path and identification properties)
+ or sets a &PathNotFoundException; error on the request if the parent node did not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>ReadBranchRequest</entry>
+ <entry>
+ A request to read a portion of a subgraph that has as its root a particular node, up to a maximum depth.
+ This request is an efficient mechanism when a branch (or part of a branch) is to be navigated and processed,
+ and replaces some non-trivial code to read the branch iteratively using multiple <code>ReadNodeRequest</code>s.
+ The connector reads the branch to the specified maximum depth, returning the properties and children for all
+ nodes found in the branch.
+ The connector also sets on the request the actual location of the branch's root node (including the path and identification properties).
+ The connector sets a &PathNotFoundException; error on the request if the node at
+ the top of the branch does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ &ChangeRequest; is a subclass of &Request; that provides a base class for all the requests that request a change
+ be made to the content. As we'll see later, these &ChangeRequest; objects also get reused by the
+ <link linkend="graph-observation">observation</link> system.
+ </para>
+ <table frame='all'>
+ <title>Types of Change Requests</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>CreateNodeRequest</entry>
+ <entry>
+ A request to create a node at the specified location and setting on the new node the properties included in the request.
+ The connector creates the node at the desired location, adjusting any same-name-sibling indexes as required.
+ (If an SNS index is provided in the new node's location, existing children with the same name after that SNS index
+ will have their SNS indexes adjusted. However, if the requested location does not include a SNS index, the new
+ node is added after all existing children, and it's SNS index is set accordingly.)
+ The connector also sets on the request the actual location of the new node (including the path and identification properties)..
+ The connector sets a &PathNotFoundException; error on the request if the parent node does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>RemovePropertiesRequest</entry>
+ <entry>
+ A request to remove a set of properties on an existing node. The request contains the location of the node as well as the
+ names of the properties to be removed. The connector performs these changes and sets on the request the
+ actual location (including the path and identification properties) of the node.
+ The connector sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>UpdatePropertiesRequest</entry>
+ <entry>
+ A request to set or update properties on an existing node. The request contains the location of the node as well as the
+ properties to be set and those to be deleted. The connector performs these changes and sets on the request the
+ actual location (including the path and identification properties) of the node.
+ The connector sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>RenameNodeRequest</entry>
+ <entry>
+ A request to change the name of a node. The connector changes the node's name, adjusts all SNS indexes
+ accordingly, and returns the actual locations (including the path and identification properties) of both the original
+ location and the new location.
+ The connector sets a &PathNotFoundException; error on the request if the node does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>CopyBranchRequest</entry>
+ <entry>
+ A request to copy a portion of a subgraph that has as its root a particular node, up to a maximum depth.
+ The request includes the name of the workspace where the original node is located as well as the name of the
+ workspace where the copy is to be placed (these may be the same, but may be different).
+ The connector copies the branch from the original location, up to the specified maximum depth, and places a copy
+ of the node as a child of the new location.
+ The connector also sets on the request the actual location (including the path and identification properties)
+ of the original location as well as the location of the new copy.
+ The connector sets a &PathNotFoundException; error on the request if the node at
+ the top of the branch does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if one of the named workspaces does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>MoveBranchRequest</entry>
+ <entry>
+ A request to move a subgraph that has a particular node as its root.
+ The connector moves the branch from the original location and places it as child of the specified new location.
+ The connector also sets on the request the actual location (including the path and identification properties)
+ of the original and new locations. The connector will adjust SNS indexes accordingly.
+ The connector sets a &PathNotFoundException; error on the request if the node that is to be moved or the
+ new location do not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>DeleteBranchRequest</entry>
+ <entry>
+ A request to delete an entire branch specified by a single node's location.
+ The connector deletes the specified node and all nodes below it, and sets the actual location,
+ including the path and identification properties, of the node that was deleted.
+ The connector sets a &PathNotFoundException; error on the request if the node being deleted does not exist in the workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>CompositeRequest</entry>
+ <entry>
+ A request that actually comprises multiple requests (none of which will be a composite).
+ The connector simply processes all of the requests in the composite request, but should set on the composite
+ request any error (usually the first error) that occurs during processing of the contained requests.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>There are also requests that deal with workspaces:</para>
+ <table frame='all'>
+ <title>Types of Workspace Read Requests</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>GetWorkspacesRequest</entry>
+ <entry>
+ A request to obtain the names of the existing workspaces that are accessible to the caller.
+ </entry>
+ </row>
+ <row>
+ <entry>VerifyWorkspaceRequest</entry>
+ <entry>
+ A request to verify that a workspace with a particular name exists.
+ The connector returns the actual location for the root node if the workspace exists, as well as the actual name of the workspace
+ (e.g., the default workspace name if a null name is supplied).
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>And there are also requests that deal with changing workspaces (and thus extend &ChangeRequest;):</para>
+ <table frame='all'>
+ <title>Types of Workspace Change Requests</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>CreateWorkspaceRequest</entry>
+ <entry>
+ A request to create a workspace with a particular name.
+ The connector returns the actual location for the root node if the workspace exists, as well as the actual name of the workspace
+ (e.g., the default workspace name if a null name is supplied).
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace already exists.
+ </entry>
+ </row>
+ <row>
+ <entry>DestroyWorkspaceRequest</entry>
+ <entry>
+ A request to destroy a workspace with a particular name.
+ The connector sets a &InvalidWorkspaceException; error on the request if the named workspace does not exist.
+ </entry>
+ </row>
+ <row>
+ <entry>CloneWorkspaceRequest</entry>
+ <entry>
+ A request to clone one named workspace as another new named workspace.
+ The connector sets a &InvalidWorkspaceException; error on the request if the original workspace does not exist,
+ or if the new workspace already exists.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ <para>
+ Although there are over a dozen different kinds of requests, we do anticipate adding more in future releases.
+ For example, DNA will likely support searching repository content in sources through an additional subclass of &Request;.
+ Getting the version history for a node will likely be another kind of request added in an upcoming release.
+ </para>
+ <para>
+ This section covered the different kinds of &Request; classes. The next section provides a easy way to encapsulate how
+ a component should responds to these requests, and after that we'll see how these &Request; objects are also used
+ in the <link linkend="graph-observation">observation</link> framework.
+ </para>
+ </sect1>
+ <sect1 id="graph-request-processors">
+ <title>Request processors</title>
+ <para>
+ JBoss DNA connectors are typically the components that receive these &Request; objects. We'll dive deep into connectors
+ in the <link linkend="connector-framework">next chapter</link>, but before we do there is one more component related to
+ &Request;s that should be discussed.
+ </para>
+ <para>
+ The &RequestProcessor; class is an abstract class that defines a <code>process(...)</code> method for each concrete &Request; subclass.
+ In other words, there is a <code>process(CompositeRequest)</code> method, a <code>process(ReadNodeRequest)</code> method,
+ and so on. This makes it easy to implement behavior that responds to the different kinds of &Request; classes:
+ simply subclass the &RequestProcessor;, override all of the abstract methods, and optionally
+ overriding any of the other methods that have a default implementation.
+ </para>
+ <note>
+ <para>
+ The &RequestProcessor; abstract class contains default implementations for quite a few of the <code>process(...)</code> methods,
+ and these will be <emphasis>sufficient</emphasis> but probably not efficient or optimum. If you can provide a more efficient
+ implementation given your source, feel free to do so. However, if performance is not a big issue, all of the concrete methods
+ will provide the correct behavior. Keep things simple to start out - you can always provide better implementations later.
+ </para>
+ </note>
+ </sect1>
+ <sect1 id="graph-observation">
+ <title>Observation</title>
+ <para>
+ The JBoss DNA graph model also incorporates an observation framework that allows components to register and
+ be notified when changes occur within the content owned by a graph.
+ </para>
+ <para>
+ Many event frameworks define the listeners and sources as interfaces. While this is often useful, it requires
+ the implementations properly address the thread-safe semantics of managing and calling the listeners.
+ The JBoss DNA observation framework uses abstract or concrete classes to minimize the effort required for implementing
+ &ChangeObserver; or &Observable;. These abstract classes provide implementations for a number of
+ utility methods (such as the <code>unregister()</code> method on &ChangeObserver;) that
+ also save effort and code.
+ </para>
+ <para>
+ However, one of the more important reasons for providing classes is that &ChangeObserver; uses
+ weak references to track the &Observable; instances, and the &ChangeObservers;
+ class uses weak references for the listeners. This means that an observer does not prevent &Observable; instances
+ from being garbage collected, nor do observers prevent &Observable; instances from being garbage collected.
+ These abstract class provide all this functionality for free.
+ </para>
+ <sect2 id="graph-observable">
+ <title>Observable</title>
+ <para>
+ Any component that can have changes and be observed can implement the &Observable; interface. This interface
+ allows &Observers; to register (or be registered) to receive notifications of the changes. However, a concrete and thread-safe
+ implementation of this interface, called &ChangeObservers;, is available and should be used where possible, since it
+ automatically manages the registered &ChangeObserver; instances and properly implements the register and unregister mechanisms.
+ </para>
+ </sect2>
+ <sect2 id="graph-observers">
+ <title>Observers</title>
+ <para>
+ Components that are to recieve notifications of changes are called <emphasis>observers</emphasis>. To create an observer, simply extend
+ the &ChangeObserver; abstract class and provide an implementation of the <code>notify(&Changes;)</code> method.
+ Then, register the observer with an &Observable; using its <code>register(&ChangeObserver;)</code> method.
+ The observer's <code>notify(&Changes;)</code> method will then be called with the changes that have
+ been made to the &Observable;.
+ </para>
+ <para>
+ When an observer is no longer needed, it should be unregistered from all &Observable; instances with which
+ it was registered. The &ChangeObserver; class automatically tracks which &Observable; instances it is
+ registered with, and calling the observer's <code>unregister()</code> will unregister the observer from
+ all of these &Observable;s. Alternatively, an observer can be unregistered from a single &Observable; using the
+ &Observable;'s <code>unregister(&ChangeObserver;)</code> method.
+ </para>
+ </sect2>
+ <sect2 id="graph-changes">
+ <title>Changes</title>
+ <para>
+ The &Changes; class represents the set of individual changes that have been made during a single, atomic
+ operation. Each &Changes; instance has information about the source of the changes, the timestamp at which
+ the changes occurred, and the individual changes that were made. These individual changes take the form of
+ &ChangeRequest; objects, which we'll see more of in the next chapter. Each request is
+ frozen, meaning it is immutable and will not change. Also none of the change requests will be marked as cancelled.
+ </para>
+ <para>
+ Using the actual &ChangeRequest; objects as the "events" has a number of advantages.
+ First, the existing &ChangeRequest; subclasses already contain the information to accurately and completely
+ describe the operation. Reusing these classes means we don't need a duplicate class structure or come up with a generic
+ event class.
+ </para>
+ <para>
+ Second, the requests have all the state required for an event, plus they often will have more. For example,
+ the &DeleteBranchRequest; has the actual location of the branch that was deleted (and in this way is not much different than
+ a more generic event), but the &CreateNodeRequest; has the actual location of the created node along with the properties
+ of that node. Additionally, the &RemovePropertyRequest; has the actual location of the node along with the name of the property
+ that was removed. In many cases, these requests have all the information a more general event class might have but
+ then hopefully enough information for many observers to use directly without having to read the graph to decide what
+ actually changed.
+ </para>
+ <para>
+ Third, the requests that make up a &Changes; instance can actually be replayed. Consider the case of a cache
+ that is backed by a &RepositorySource;, which might use an observer to keep the cache in sync.
+ As the cache is notified of &Changes;, the cache can simply replay the changes against its source.
+ </para>
+ </sect2>
+ <para>
+ As we'll see in the <link linkend="connector-framework">next chapter</link>, each connector is responsible for propagating
+ the &ChangeRequest; objects to the connector's &Observer;. But that's not the only use of &Observers;.
+ We'll also see later how the <link linkend="sequencing-framework">sequencing system</link> uses &Observers; to monitor
+ for changes in the graph content to determine which, if any, sequencers should be run. And, the
+ <link linkend="jcr">JCR implementation</link> also uses the observation framework to propagate those changes
+ to JCR clients.
+ </para>
+ </sect1>
<sect1>
<title>Summary</title>
<para>
Modified: trunk/docs/reference/src/main/docbook/en-US/custom.dtd
===================================================================
--- trunk/docs/reference/src/main/docbook/en-US/custom.dtd 2009-06-09 04:32:58 UTC (rev 1004)
+++ trunk/docs/reference/src/main/docbook/en-US/custom.dtd 2009-06-09 06:11:41 UTC (rev 1005)
@@ -116,10 +116,11 @@
<!ENTITY PropertyType "<ulink url='&API;graph/property/PropertyType.html'><classname>PropertyType</classname></ulink>">
<!ENTITY PathNotFoundException "<ulink url='&API;graph/property/PathNotFoundException.html'><classname>PathNotFoundException</classname></ulink>">
<!ENTITY RepositorySource "<ulink url='&API;graph/connector/RepositorySource.html'><interface>RepositorySource</interface></ulink>">
+<!ENTITY RepositoryContext "<ulink url='&API;graph/connector/RepositoryContext.html'><interface>RepositoryContext</interface></ulink>">
<!ENTITY RepositoryConnection "<ulink url='&API;graph/connector/RepositoryConnection.html'><interface>RepositoryConnection</interface></ulink>">
<!ENTITY RepositoryConnectionFactory "<ulink url='&API;graph/connector/RepositoryConnectionFactory.html'><interface>RepositoryConnectionFactory</interface></ulink>">
-<!ENTITY RepositorySourceListener "<ulink url='&API;graph/connector/RepositorySourceListener.html'><interface>RepositorySourceListener</interface></ulink>">
<!ENTITY RepositorySourceCapabilities "<ulink url='&API;graph/connector/RepositorySourceCapabilities.html'><classname>RepositorySourceCapabilities</classname></ulink>">
+<!ENTITY RepositorySourceException "<ulink url='&API;graph/connector/RepositorySourceException.html'><classname>RepositorySourceException</classname></ulink>">
<!ENTITY InMemoryRepository "<ulink url='&API;graph/connector/inmemory/InMemoryRepository.html'><classname>InMemoryRepository</classname></ulink>">
<!ENTITY InMemoryRepositorySource "<ulink url='&API;graph/connector/inmemory/InMemoryRepositorySource.html'><classname>InMemoryRepositorySource</classname></ulink>">
<!ENTITY FederatedRepository "<ulink url='&API;graph/connector/federation/FederatedRepository.html'><classname>FederatedRepository</classname></ulink>">
@@ -127,9 +128,13 @@
<!ENTITY Projection "<ulink url='&API;graph/connector/federation/Projection.html'><classname>Projection</classname></ulink>">
<!ENTITY CachePolicy "<ulink url='&API;graph/cache/CachePolicy.html'><interface>CachePolicy</interface></ulink>">
<!ENTITY Request "<ulink url='&API;graph/request/Request.html'><classname>Request</classname></ulink>">
+<!ENTITY ChangeRequest "<ulink url='&API;graph/request/ChangeRequest.html'><classname>ChangeRequest</classname></ulink>">
<!ENTITY CompositeRequest "<ulink url='&API;graph/request/CompositeRequest.html'><classname>CompositeRequest</classname></ulink>">
<!ENTITY ReadNodeRequest "<ulink url='&API;graph/request/ReadNodeRequest.html'><classname>ReadNodeRequest</classname></ulink>">
+<!ENTITY RemovePropertyRequest "<ulink url='&API;graph/request/RemovePropertyRequest.html'><classname>RemovePropertyRequest</classname></ulink>">
+<!ENTITY CreateNodeRequest "<ulink url='&API;graph/request/CreateNodeRequest.html'><classname>CreateNodeRequest</classname></ulink>">
<!ENTITY CopyBranchRequest "<ulink url='&API;graph/request/CopyBranchRequest.html'><classname>CopyBranchRequest</classname></ulink>">
+<!ENTITY DeleteBranchRequest "<ulink url='&API;graph/request/DeleteBranchRequest.html'><classname>DeleteBranchRequest</classname></ulink>">
<!ENTITY InvalidRequestException "<ulink url='&API;graph/request/InvalidRequestException.html'><classname>InvalidRequestException</classname></ulink>">
<!ENTITY InvalidWorkspaceException "<ulink url='&API;graph/request/InvalidWorkspaceException.html'><classname>InvalidWorkspaceException</classname></ulink>">
<!ENTITY UnsupportedRequestException "<ulink url='&API;graph/request/UnsupportedRequestException.html'><classname>UnsupportedRequestException</classname></ulink>">
@@ -140,6 +145,12 @@
<!ENTITY MimeTypeDetector "<ulink url='&API;graph/mimetype/MimeTypeDetector.html'><interface>MimeTypeDetector</interface></ulink>">
<!ENTITY MockSequencerOutput "<ulink url='&API;graph/sequencer/MockSequencerOutput.html'><interface>MockSequencerOutput</interface></ulink>">
<!ENTITY MockSequencerContext "<ulink url='&API;graph/sequencer/MockSequencerContext.html'><interface>MockSequencerContext</interface></ulink>">
+<!ENTITY Observer "<ulink url='&API;graph/observer/Observer.html'><interface>Observer</interface></ulink>">
+<!ENTITY Observable "<ulink url='&API;graph/observer/Observable.html'><interface>Observable</interface></ulink>">
+<!ENTITY ChangeObserver "<ulink url='&API;graph/observer/ChangeObserver.html'><classname>ChangeObserver</classname></ulink>">
+<!ENTITY NetChangeObserver "<ulink url='&API;graph/observer/NetChangeObserver.html'><classname>NetChangeObserver</classname></ulink>">
+<!ENTITY ChangeObservers "<ulink url='&API;graph/observer/ChangeObservers.html'><classname>ChangeObservers</classname></ulink>">
+<!ENTITY Changes "<ulink url='&API;graph/observer/Changes.html'><classname>Changes</classname></ulink>">
<!-- Types in dna-repository -->
More information about the dna-commits
mailing list