Author: laubai
Date: 2010-04-12 00:52:16 -0400 (Mon, 12 Apr 2010)
New Revision: 8375
Added:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.ent
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.xml
Removed:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.ent
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.xml
Modified:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/Book_Info.xml
Log:
Updated version numbering for CP08.
Modified: enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/Book_Info.xml
===================================================================
--- enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/Book_Info.xml 2010-04-12
04:50:29 UTC (rev 8374)
+++ enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/Book_Info.xml 2010-04-12
04:52:16 UTC (rev 8375)
@@ -2,8 +2,8 @@
<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
<bookinfo id="JBoss_Cache">
- <title>JBoss Cache Tutorial CP07</title>
- <subtitle>for Use with JBoss Enterprise Application Platform 4.3 Cumulative Patch
7</subtitle>
+ <title>JBoss Cache Tutorial CP08</title>
+ <subtitle>for Use with JBoss Enterprise Application Platform 4.3 Cumulative Patch
8</subtitle>
<edition>2.0</edition>
<pubsnumber>1</pubsnumber>
<productname>JBoss Enterprise Application Platform</productname>
Deleted:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.ent
===================================================================
---
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.ent 2010-04-12
04:50:29 UTC (rev 8374)
+++
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.ent 2010-04-12
04:52:16 UTC (rev 8375)
@@ -1,3 +0,0 @@
-<!ENTITY HOLDER "Red Hat, Inc">
-<!ENTITY YEAR "2009">
-<!ENTITY VERSION "">
Deleted:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.xml
===================================================================
---
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.xml 2010-04-12
04:50:29 UTC (rev 8374)
+++
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.xml 2010-04-12
04:52:16 UTC (rev 8375)
@@ -1,503 +0,0 @@
-<?xml version='1.0'?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
-
-<book id="JBossCache_Tutorial">
- <title>JBossCache Tutorial</title>
- <xi:include href="Book_Info.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- <chapter id="JBossCache_Tutorial-Introduction">
- <title>Introduction</title>
- <para>
- JBossCache is an in-memory replicated (synchronous or asynchronous), transactional,
and fine-grained cache. It consists of two subsystems: TreeCache (plain cache) and
PojoCache (object-oriented POJO cache). In this tutorial, we will demonstrate the usage of
both cache features. For details of the usage and APIs, please refer to the user manuals
for <ulink
url="http://labs.jboss.org/portal/jbosscache/docs/index.html"&g...
and <ulink
url="http://labs.jboss.org/portal/jbosscache/docs/index.html"&g...;.
- </para>
- <section id="Introduction-Scope">
- <title>Scope</title>
- <itemizedlist>
- <listitem>
- <para>
- Cache creation and modification
- </para>
- </listitem>
- <listitem>
- <para>
- Replication
- </para>
- </listitem>
- <listitem>
- <para>
- PojoCache
- </para>
- </listitem>
- <listitem>
- <para>
- Transaction
- </para>
- </listitem>
- </itemizedlist>
- </section>
-
- </chapter>
- <chapter id="JBossCache_Tutorial-Configuration">
- <title>Configuration</title>
- <para>
- First download the standalone TreeCache code from <ulink
url="http://labs.jboss.org/portal/jbosscache/download/index.html&quo...;.
Unzip it, and you will get a root directory (jboss-cache in our example).
- </para>
- <para>
- The configuration files are located under the etc directory. You can modify the
behavior of TreeCache through editing the various configuration files.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>log4j.xml</literal>. Logging output. You can turn on logging
level or change log file directory (default is
<literal>/tmp/jbosscache.log</literal>).
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>replSync-service.xml</literal>. Tree cache configuration file
(file name is not fixed. You specify the file to be read in
<literal>PropertyConfigurator</literal>). The settings are for a replicated,
synchronous, and transactional cache. The default DummyTransactionManager is used with a
transaction isolation level of REPEATABLE_READ. For details of the configuration
parameters, please refer to the <ulink
url="http://www.jboss.org/products/jbosscache/docs">Treecach...;.
Note that this file is used in the BSH ( <ulink
url="http://www.beanshell.org/">BeanShell</ulink>, a lightweight Java
compatible scripting language) script to configure the cache.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>jboss-aop.xml</literal>. AOP pointcut and advice definition for
the example POJO classes, Person and Address, respectively. For details of how to put your
own class under AOP, please refer to the <ulink
url="http://www.jboss.org/products/jbosscache/docs">PojoCach...;.
This file is read in when the process is started.
- </para>
- </listitem>
- </itemizedlist>
- </chapter>
- <chapter id="JBossCache_Tutorial-Script">
- <title>Script</title>
- <para>
- The script files that are needed (located under install directory) in this tutorial
are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>build.sh</literal> (or <literal>build.bat</literal>
for DOS/Windows). Simple build script that wraps around ant. Users can simply type
<literal>sh build.sh</literal> for help. Note from now on, we will only refer
to the Unix version with the understanding that there is a corresponding DOS counterpart.
The same goes for runDemoShell explained next.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>runDemoShell.sh</literal>. Simple run script that wraps around
BeanShell. This is used to operate the replicated cache through interactive command line.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>plain.bsh</literal>. Java code that instantiate and configure
the cache. It also creates an example cache entry.
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>aop.bsh</literal>. Java codes that instantiate and configure
the aop cache. In addition, it also sets up the example POJO (plain old Java object)
classes (e.g., Person and Address).
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>aopWithTx.bsh</literal>. Same with aop.bsh except it also
instantiates a transaction context.
- </para>
- </listitem>
- </itemizedlist>
- </chapter>
- <chapter id="JBossCache_Tutorial-Example_POJO">
- <title>Example POJO</title>
- <para>
- The example POJO classes used for PojoCache demo are:
<literal>Person</literal> and <literal>Address</literal>. They are
located under <literal>tests/org/jboss/cache/aop</literal> directory.
<literal>Person</literal> has attributes of <literal>String age, Address
addr, List languages </literal> , etc. We will demonstrate that once you put the
POJO instance in the cache, plain get/set POJO methods will be intercepted by the cache.
- </para>
- <para>
- Here is the snippet of the class definition for <literal>Person</literal>
and <literal>Address</literal> .
- </para>
-<programlisting>public class Person {
- String name=null;
- int age=0;
- Map hobbies=null;
- Address address=null;
- Set skills;
- List languages;
-
- public String getName() { return name; }
- public void setName(String name) { this.name=name; }
- ...
- }
-
-</programlisting>
-<programlisting>public class Address {
- String street=null;
- String city=null;
- int zip=0;
-
- public String getStreet() { return street; }
- public void setStreet(String street) { this.street=street; }
- ...
- }
-
-</programlisting>
- </chapter>
- <chapter id="JBossCache_Tutorial-Demo">
- <title>Demo</title>
- <para>
- To run the demo, you will need at least two windows: one to peruse the cache contents
(plus non-aop operations) and the other to operate the cache directly. Of course, you can
also open more than one GUI window to see the cache replication at work to multiple
members. You will also need to run the scripts under jboss-cache installation directory
after you unzip the release package (jboss-cache-dist.zip). Due to the limitation of the
GUI, please note that:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- For each demo example, it'd be best if you re-start the whole setup.
- </para>
- </listitem>
- <listitem>
- <para>
- While you can modify the cache content on the GUI window and it will show up on the
BSH cache content (e.g., through <literal>cache.printDetails()</literal> ),
this won't work on PojoCache demo. That is, you can only modify the cache content
on the BSH window.
- </para>
- </listitem>
- </itemizedlist>
- <para>
- The two demo programs to run are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- On the first window for the GUI, type <literal>sh build.sh </literal> to
see the available commands. To run the GUI, type <literal>sh build.sh
run.demo</literal> . It will startup a PojoCache GUI. Later on, you can click on a
node to view the the contents. Note that you can also add/modify the node contents for
non-AOP cache entries. Since the GUI entry only accepts String for now, operation on aop
cache from the GUI will not always work (unless it is a String type).
- </para>
- </listitem>
- <listitem>
- <para>
- On the second window for the interactive Java commands, type sh runShellDemo.sh to
fire off the BeanShell interactive command shell (you can use either ^D or ^Z in Windows
and Unix to exit afterward). You can then read in the Java code scripts to showcase the
cache capabilities (e.g., plain.bsh, aop.bsh, and aopWithTx.bsh). See the following for
details.
- </para>
- </listitem>
- </itemizedlist>
- </chapter>
- <chapter id="JBossCache_Tutorial-Plain_cache">
- <title>Plain cache</title>
- <para>
- Once you are in the shell, you can either execute the script to populate the cache, or
type it in manually by command line. To run the script, type
<literal>sourceRelative("plain.bsh");</literal> under the
interactive BSH shell. For this to work, you'll need to have your working
directory set to the directory in which plain.bsh resides (otherwise give the full
pathname of plain.bsh). Basically, the script will create cache entries that will be
replicated onto the GUI. (You may have to type show() into the resulting beanshell window
yourself) Here are the snippets for the script:
- </para>
-<programlisting>import org.jboss.cache.*;
- show(); // verbose mode for bean shell
- TreeCache tree = new TreeCache();
- PropertyConfigurator config = new PropertyConfigurator();
- // configure tree cache. Needs to be in the classpath
- config.configure(tree, "META-INF/replSync-service.xml");
- tree.startService();
- // kick start tree cache
- tree.put("/a/b/c", "ben", "me");
- // create a cache entry.
- // Node "/a/b/c" will be created if it does not yet exist.
-
-</programlisting>
- <para>
- You should see in the GUI that a new entry of <literal>/a/b/c</literal>
has been created. Click on the node c to see the content. You can modify the contents from
the GUI as well. To create another node, for example, you can type in the shell:
- </para>
-<programlisting>tree.put("/a/b/c/d", "JBoss", "Open
Source");
- tree.get("/a/b/c/d", "JBoss");
-
-</programlisting>
- </chapter>
- <chapter id="JBossCache_Tutorial-PojoCache">
- <title>PojoCache</title>
- <para>
- Once you are in the shell, type
<literal>sourceRelative("aop.bsh");</literal> to execute the shell
script. Basically, aop.bsh illustrates the steps to instantiate a cache, configure it, and
then create entries under it. Here are the snippets:
- </para>
-<programlisting>import org.jboss.cache.PropertyConfigurator;
- import org.jboss.cache.aop.PojoCache;
- import org.jboss.cache.aop.test.Person;
- import org.jboss.cache.aop.test.Address;
- show(); // verbose mode for bean shell
- PojoCache tree = new PojoCache();
- PropertyConfigurator config = new PropertyConfigurator(); // configure tree
cache.
- config.configure(tree, "META-INF/replSync-service.xml");
- Person joe = new Person(); // instantiate a Person object named joe
- joe.setName("Joe Black");
- joe.setAge(31);
- Address addr = new Address(); // instantiate a Address object named addr
- addr.setCity("Sunnyvale");
- addr.setStreet("123 Albert Ave");
- addr.setZip(94086); joe.setAddress(addr); // set the address reference
- tree.startService(); // kick start tree cache
- tree.putObject("/aop/joe", joe);
- // add aop sanctioned object (and sub-objects) into cache.
- // since it is aop-sanctioned, use of plain get/set methods will take care
- // of cache contents automatically.
- joe.setAge(41);
-
-</programlisting>
- <para>
- Note the API needed to put the object (and its dependent ones) into cache is
putObject. Once the second window finishes execution, you should see the first GUI window
has been populated with entries of /aop/joe/address. Click on each tree node will display
different values associated with that node.
- </para>
- <para>
- Next step to see AOP in action, you can do plain get/set methods without ever worrying
about put it in the cache. For example, you can do in the shell window joe.setAge(20); and
see that GUI gets updated with the age field automatically (if not, click away and back
will refresh the GUI content). Also to demonstrate the object graph replication, you can
modify Joe's address and see the cache will update it automatically. For example,
type addr.setCity("San Jose"); in the interactive shell, you should see in the
GUI that the address got modified.
- </para>
- <para>
- Finally, PojoCache also supports get/set with parameter type of Collection classes
(i.e., List, Map, and Set). For example, type the following in the shell command line:
- </para>
-<programlisting>ArrayList lang = new ArrayList();
- lang.add("Ensligh");
- lang.add("Mandarin");
- joe.setLanguages(lang);
-
-</programlisting>
- </chapter>
- <chapter id="JBossCache_Tutorial-PojoCache_with_Transaction">
- <title>PojoCache with Transaction</title>
- <para>
- To see TreeCache transaction at work, you start with the same setup with last section
except you load the bsh of aopWithTx.bsh instead of aop.bsh. The additional snippets are:
- </para>
-<programlisting>import org.jboss.cache.PropertyConfigurator;
- import org.jboss.cache.aop.PojoCache;
- import org.jboss.cache.aop.test.Person;
- import org.jboss.cache.aop.test.Address;// Tx imports
- import javax.transaction.UserTransaction; import javax.naming.*;
- import org.jboss.cache.transaction.DummyTransactionManager;
- show(); // verbose mode for bean shell
- // Set up transaction manager
- DummyTransactionManager.getInstance();
- Properties prop = new Properties();
- prop.put(Context.INITIAL_CONTEXT_FACTORY,
- "org.jboss.cache.transaction.DummyContextFactory");
- UserTransaction tx = (UserTransaction)new
- InitialContext(prop).lookup("UserTransaction");
- PojoCache tree = new PojoCache();
- PropertyConfigurator config = new PropertyConfigurator();
- // configure tree cache.
- config.configure(tree, "META-INF/replSync-service.xml");
- joe = new Person();
- joe.setName("Joe Black");
- joe.setAge(31);
-
- Address addr = new Address();
- addr.setCity("Sunnyvale");
- addr.setStreet("123 Albert Ave");
- addr.setZip(94086);
- joe.setAddress(addr);
-
- tree.startService(); // kick start tree cache
- tree.putObject("/aop/joe", joe); // add aop sanctioned object
- // since it is aop-sanctioned, use of plain get/set methods will take care
- of cache contents automatically.
- // Also it is transacted
- tx.begin();
- joe.setAge(41);
- joe.getAddress().setZip(95124);
- tx.commit();
-
-</programlisting>
- <para>
- In this example, a default dummy transaction manager is used.
- </para>
-<programlisting>tx.begin();
- addr.setZip(95131);
- tx.rollback();
-
-</programlisting>
- </chapter>
- <chapter id="JBossCache_Tutorial-CacheLoader_examples">
- <title>CacheLoader examples</title>
- <para>
- All the examples below are based on the JBossCache standalone distribution. We assume
the ZIP file has been unzipped into a directory <literal>jboss-cache</literal>
.
- </para>
- <section id="CacheLoader_examples-Local_cache_with_CacheLoader">
- <title>Local cache with CacheLoader</title>
- <para>
- This demo shows a local PojoCache with a CacheLoader. We will insert a POJO into the
cache, and see that the POJO is transparently saved using the CacheLoader.
- </para>
- <para>
- To run this, you have to modify
<literal>jboss-cache/output/etc/META-INF/oodb-service.xml</literal> : change
<literal>CacheLoaderConfig</literal> to point to a valid directory (create it
if it doesn't yet exist):
- </para>
-<programlisting><attribute name="CacheLoaderConfig">
- location=c:\\tmp\\oodb
- </attribute>
-
-</programlisting>
- <para>
- Then start the beanshell and source <literal>oodb.bsh</literal> into it.
Note that <literal>oodb.bsh</literal> already contains code to create and
retrieve POJO from the cache. So remember to comment them out if you decide to create the
Person instance yourself.
- </para>
-<programlisting>bela@laptop /cygdrive/c/jboss-cache
- $ ./runShellDemo.sh
- BeanShell 1.3.0 - by Pat Niemeyer (pat(a)pat.net)
- bsh % sourceRelative("oodb.bsh");
- interceptor chain is:
- class org.jboss.cache.interceptors.CallInterceptor
- class org.jboss.cache.interceptors.CacheLoaderInterceptor
- class org.jboss.cache.interceptors.TransactionInterceptor
- <null>
- bsh %
-
-</programlisting>
- <para>
- Next, create an instance of Person, and set its address and other fields:
- </para>
-<programlisting>bsh % p=new Person();
- <name=null, age=0, hobbies=, address=null, skills=null,
languages=null>
- bsh % p.age=3;
- <3>
- bsh % p.name="Michelle";
- <Michelle>
- bsh % addr=new Address();
- <street=null, city=null, zip=0>
- bsh % addr.city="San Jose";
- <San Jose>
- bsh % addr.zip=95124;
- <95124>
- bsh % addr.street="1704 Almond Blossom Lane";
- <1704 Almond Blossom Lane>
- bsh % p.setAddress(addr);
- bsh % tree.putObject("/person/me", p);
- bsh % p;
- <name=Michelle, age=3, hobbies=, address=street=1704 Almond Blossom
Lane,
- city=San Jose, zip=95124, skills=null, languages=null>
- bsh %
-
-</programlisting>
- <para>
- The <literal>Person</literal> object with all of its fields and
subobjects is now saved. Let's kill beanshell and restart it. At this point,
because the instance of <literal>Person</literal> we created was given the
name "p", we can retrieve it again:
- </para>
-<programlisting>bela@laptop /cygdrive/c/jboss-cache
- $ ./runShellDemo.sh
- BeanShell 1.3.0 - by Pat Niemeyer (pat(a)pat.net)
- bsh % sourceRelative("oodb.bsh");
- interceptor chain is:
- class org.jboss.cache.interceptors.CallInterceptor
- class org.jboss.cache.interceptors.CacheLoaderInterceptor
- class org.jboss.cache.interceptors.TransactionInterceptor
- <null>
- bsh % tree;
- </>
- bsh % p=tree.getObject("/person/me");
- <name=Michelle, age=3, hobbies=, address=street=1704 Almond Blossom
Lane,
- city=San Jose, zip=95124, skills=null, languages=null>
- bsh % tree;
- </p
- /address
- >
- bsh %
-
-</programlisting>
- <para>
- The interesting thing here is that the cache was initially empty ("/").
Only when we loaded "p", did it get populated (lazy loading). You can see that
the values of "p" are loaded from the datastore where they were previously
saved.
- </para>
- </section>
-
- </chapter>
- <chapter
id="JBossCache_Tutorial-Replicated_cache_with_shared_datastore">
- <title>Replicated cache with shared datastore</title>
- <para>
- The scenario that we'll run in this example is described in the documentation
for JBossCache. It consists of 2 separate nodes that replicate their contents between each
other. In addition, they both point to the <emphasis>same</emphasis>
datastore. The configuration is in file
<literal>jboss-cache/output/etc/META-INF/replAsyncSharedCacheLoader-service.xml</literal>
:
- </para>
-<programlisting><!-- Whether or not to fetch state on joining a cluster
-->
- <attribute
name="FetchStateOnStartup">false</attribute>
- <attribute
name="CacheLoaderClass">org.jboss.cache.loader.FileCacheLoader</attribute>
- <attribute name="CacheLoaderConfig">
- location=c:\\tmp
- </attribute>
- <attribute
name="CacheLoaderShared">true</attribute>
- <attribute
name="CacheLoaderPreload">/</attribute>
- <attribute
name="CacheLoaderFetchTransientState">false</attribute>
- <attribute
name="CacheLoaderFetchPersistentState">true</attribute>
-</programlisting>
- <para>
- The <literal>FetchStateOnStartup</literal> attribute set to
<literal>false</literal> means that a newly started cache will
<emphasis>not</emphasis> attempt to fetch the state (neither transient nor
persistent). Therefore, attributes
<literal>CacheLoaderFetchTransientState</literal> and
<literal>CacheLoaderFetchPersistentState</literal> will be ignored.
<literal>CacheLoaderShared</literal> set to
<literal>true</literal> means that both nodes will share the same datastore,
which resides in <literal>c:\tmp</literal> in the example (this assumes that
both nodes have access to the same file system). Please make sure that
<literal>c:\tmp</literal> exists, or point the config string to a different
existing directory.
- </para>
- <para>
- This configuration would essentially provide for two
<literal>cold</literal> nodes, in the sense that all contents of a new cache
is in the datastore, and is lazy-loaded via the CacheLoader when accessed. However, this
is not true, as <literal>CacheLoaderPreload</literal> points to "/",
which is the root of the entire tree. Therefore, all of the contents of the cache are
recursively pre-loaded. This is probably a bad configuration when you have a lot of data
in the cache, because <emphasis>all</emphasis> of your data will be loaded
into the cache.
- </para>
- <para>
- Note that with a shared datastore, the node that makes a modification is the one who
writes it to the store using the CacheLoader. This prevents both nodes from writing the
same data twice.
- </para>
- <para>
- We can now start 2 instances by opening two shells and executing the following ANT
target:
- </para>
-<programlisting>bela@laptop /cygdrive/c/jboss-cache
- $ ./build.sh run.demo.async.shared.cacheloader
- Buildfile: build.xml
-
- init:
-
- compile:
-
- run.demo.async.shared.cacheloader:
- [java] ** node loaded: /a
- [java] ** node loaded: /a/b
- [java] ** node loaded: /a/b/c
- [java] ** node loaded: /uno
- [java] ** node loaded: /uno/due
-
- [java] -------------------------------------------------------
- [java] GMS: address is 192.168.1.184:1357
- [java] -------------------------------------------------------
- [java] interceptor chain is:
- [java] class org.jboss.cache.interceptors.CallInterceptor
- [java] class org.jboss.cache.interceptors.ReplicationInterceptor
- [java] class org.jboss.cache.interceptors.CacheLoaderInterceptor
- [java] class org.jboss.cache.interceptors.TransactionInterceptor
- [java] ** view change: [192.168.1.184:1355|1] [192.168.1.184:1355,
- 192.168.1.184:1357]
- [java] ** node modified: /
-
-</programlisting>
- <para>
- 2 GUI instances will appear, showing the tree structure of the cache graphically.
Nodes can be added, modified or removed by right-clicking or using the menu. Any
modification is replicated between the two nodes. If both nodes are killed, and
subsequently one or both nodes are restarted, the state is the same as before shutdown as
it was persisted to the shared store via the CacheLoader.
- </para>
- <para>
- Note that the example above shows the 2 nodes running on the same machine
(192.168.1.184) on ports 1355 and 1357.
- </para>
- </chapter>
- <chapter
id="JBossCache_Tutorial-Replicated_cache_with_unshared_local_datastore">
- <title>Replicated cache with unshared (local) datastore</title>
- <para>
- In this example, we'll run 2 nodes again, but this time, instead of sharing
the same datastore, each node has its own datastore. The configuration is in file
<literal>jboss-cache/output/etc/META-INF/node{1,2}.xml</literal> .
We'll look at node1.xml:
- </para>
-<programlisting><attribute
name="CacheLoaderClass">org.jboss.cache.loader.bdbje.BdbjeCacheLoader</attribute>
- <attribute name="CacheLoaderConfig">
- location=c:\\tmp\\node1
- </attribute>
- <attribute
name="CacheLoaderShared">false</attribute>
- <attribute
name="CacheLoaderPreload">/</attribute>
- <attribute
name="CacheLoaderFetchTransientState">false</attribute>
- <attribute
name="CacheLoaderFetchPersistentState">true</attribute>
-
-</programlisting>
- <para>
- Again, we use the Sleepycat CacheLoader implementation in
<literal>CacheLoaderClass</literal> . The
<literal>CacheLoaderConfig</literal> points to
<literal>c:\tmp\node1</literal> . This is the directory in which the Sleepycat
DB for node1 will reside. File node2.xml has a configuration that points to
<literal>c:\tmp\node2</literal> , so we have 2 different unshared datastores.
Note that, of course, we still have the same filesystem in our case, because we run the 2
nodes on the same machine. In practice those two directories would reside on two different
machines, and each machine would run one JBossCache process. Note that the 2 directories
have to exis
- </para>
- <para>
- To create an unshared datastore, we set the
<literal>CacheLoaderShared</literal> attribute to
<literal>false</literal> .
- </para>
- <para>
- The example can be run by again opening 2 shells, and running 2 ANT targets (here we
show the target for node1):
- </para>
-<programlisting>bela@laptop /cygdrive/c/jboss-cache
- $ ./build.sh run.demo.unshared.node2
- Buildfile: build.xml
-
- init:
-
- compile:
-
- run.demo.unshared.node2:
- [java] ** node loaded: /a
- [java] ** node loaded: /a/a2
- ...
-
-</programlisting>
- <para>
- The <literal>run.demo.unshared.node2</literal> target runs node2, which
will have its own store located at <literal>c:\tmp\node2</literal> (shown
above). Whenever a change is made on either of the 2 nodes, it is replicated to the other
node, and persisted in both local datastores. You can kill and restart a node, or even
both nodes, and the data will still be available due to the persistent backend store(s).
- </para>
- </chapter>
- <chapter id="JBossCache_Tutorial-Troubleshooting">
- <title>Troubleshooting</title>
- <para>
- Here are some tips for troubleshooting, if you encounter problems during this demo.
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Most of the time, the problem will come from cache replication layer, i.e., JGroups
package. On the output window, you can see the JGroups membership view. See if it is
updated when you run the BSH commands. It should show a view with at least two members.
For example, on my window, I see
- </para>
-<programlisting>[java] ** view change: [BWANG-HOME:4381|1] [BWANG-HOME:4381,
BWANG-HOME:4383]
-
-</programlisting>
- <para>
- with 2 members: 4381 and 4383. On the other hand, if you don't close the
previous running cache instance, the membership view will also include the previous
existing ones. This can corrupt the states. So you will have to make sure there is no
running TreeCache processes before each demo. If you have problem with this, please
consult the <ulink
url="http://www.jgroups.org/javagroupsnew/docs/index.html">J... website
</ulink>
- </para>
- </listitem>
- </itemizedlist>
- </chapter>
-<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="Revision_History.xml"/>
-
-</book>
-
Copied:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.ent
(from rev 8366,
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.ent)
===================================================================
---
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.ent
(rev 0)
+++
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.ent 2010-04-12
04:52:16 UTC (rev 8375)
@@ -0,0 +1,3 @@
+<!ENTITY HOLDER "Red Hat, Inc">
+<!ENTITY YEAR "2010">
+<!ENTITY VERSION "">
Copied:
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.xml
(from rev 8366,
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP07.xml)
===================================================================
---
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.xml
(rev 0)
+++
enterprise-docs/tags/JBoss_EAP_4_3_8/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP08.xml 2010-04-12
04:52:16 UTC (rev 8375)
@@ -0,0 +1,503 @@
+<?xml version='1.0'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd">
+
+<book id="JBossCache_Tutorial">
+ <title>JBossCache Tutorial</title>
+ <xi:include href="Book_Info.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <chapter id="JBossCache_Tutorial-Introduction">
+ <title>Introduction</title>
+ <para>
+ JBossCache is an in-memory replicated (synchronous or asynchronous), transactional,
and fine-grained cache. It consists of two subsystems: TreeCache (plain cache) and
PojoCache (object-oriented POJO cache). In this tutorial, we will demonstrate the usage of
both cache features. For details of the usage and APIs, please refer to the user manuals
for <ulink
url="http://labs.jboss.org/portal/jbosscache/docs/index.html"&g...
and <ulink
url="http://labs.jboss.org/portal/jbosscache/docs/index.html"&g...;.
+ </para>
+ <section id="Introduction-Scope">
+ <title>Scope</title>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Cache creation and modification
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Replication
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ PojoCache
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Transaction
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ </chapter>
+ <chapter id="JBossCache_Tutorial-Configuration">
+ <title>Configuration</title>
+ <para>
+ First download the standalone TreeCache code from <ulink
url="http://labs.jboss.org/portal/jbosscache/download/index.html&quo...;.
Unzip it, and you will get a root directory (jboss-cache in our example).
+ </para>
+ <para>
+ The configuration files are located under the etc directory. You can modify the
behavior of TreeCache through editing the various configuration files.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>log4j.xml</literal>. Logging output. You can turn on logging
level or change log file directory (default is
<literal>/tmp/jbosscache.log</literal>).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>replSync-service.xml</literal>. Tree cache configuration file
(file name is not fixed. You specify the file to be read in
<literal>PropertyConfigurator</literal>). The settings are for a replicated,
synchronous, and transactional cache. The default DummyTransactionManager is used with a
transaction isolation level of REPEATABLE_READ. For details of the configuration
parameters, please refer to the <ulink
url="http://www.jboss.org/products/jbosscache/docs">Treecach...;.
Note that this file is used in the BSH ( <ulink
url="http://www.beanshell.org/">BeanShell</ulink>, a lightweight Java
compatible scripting language) script to configure the cache.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>jboss-aop.xml</literal>. AOP pointcut and advice definition for
the example POJO classes, Person and Address, respectively. For details of how to put your
own class under AOP, please refer to the <ulink
url="http://www.jboss.org/products/jbosscache/docs">PojoCach...;.
This file is read in when the process is started.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-Script">
+ <title>Script</title>
+ <para>
+ The script files that are needed (located under install directory) in this tutorial
are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>build.sh</literal> (or <literal>build.bat</literal>
for DOS/Windows). Simple build script that wraps around ant. Users can simply type
<literal>sh build.sh</literal> for help. Note from now on, we will only refer
to the Unix version with the understanding that there is a corresponding DOS counterpart.
The same goes for runDemoShell explained next.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>runDemoShell.sh</literal>. Simple run script that wraps around
BeanShell. This is used to operate the replicated cache through interactive command line.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>plain.bsh</literal>. Java code that instantiate and configure
the cache. It also creates an example cache entry.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>aop.bsh</literal>. Java codes that instantiate and configure
the aop cache. In addition, it also sets up the example POJO (plain old Java object)
classes (e.g., Person and Address).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>aopWithTx.bsh</literal>. Same with aop.bsh except it also
instantiates a transaction context.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-Example_POJO">
+ <title>Example POJO</title>
+ <para>
+ The example POJO classes used for PojoCache demo are:
<literal>Person</literal> and <literal>Address</literal>. They are
located under <literal>tests/org/jboss/cache/aop</literal> directory.
<literal>Person</literal> has attributes of <literal>String age, Address
addr, List languages </literal> , etc. We will demonstrate that once you put the
POJO instance in the cache, plain get/set POJO methods will be intercepted by the cache.
+ </para>
+ <para>
+ Here is the snippet of the class definition for <literal>Person</literal>
and <literal>Address</literal> .
+ </para>
+<programlisting>public class Person {
+ String name=null;
+ int age=0;
+ Map hobbies=null;
+ Address address=null;
+ Set skills;
+ List languages;
+
+ public String getName() { return name; }
+ public void setName(String name) { this.name=name; }
+ ...
+ }
+
+</programlisting>
+<programlisting>public class Address {
+ String street=null;
+ String city=null;
+ int zip=0;
+
+ public String getStreet() { return street; }
+ public void setStreet(String street) { this.street=street; }
+ ...
+ }
+
+</programlisting>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-Demo">
+ <title>Demo</title>
+ <para>
+ To run the demo, you will need at least two windows: one to peruse the cache contents
(plus non-aop operations) and the other to operate the cache directly. Of course, you can
also open more than one GUI window to see the cache replication at work to multiple
members. You will also need to run the scripts under jboss-cache installation directory
after you unzip the release package (jboss-cache-dist.zip). Due to the limitation of the
GUI, please note that:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ For each demo example, it'd be best if you re-start the whole setup.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ While you can modify the cache content on the GUI window and it will show up on the
BSH cache content (e.g., through <literal>cache.printDetails()</literal> ),
this won't work on PojoCache demo. That is, you can only modify the cache content
on the BSH window.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ The two demo programs to run are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ On the first window for the GUI, type <literal>sh build.sh </literal> to
see the available commands. To run the GUI, type <literal>sh build.sh
run.demo</literal> . It will startup a PojoCache GUI. Later on, you can click on a
node to view the the contents. Note that you can also add/modify the node contents for
non-AOP cache entries. Since the GUI entry only accepts String for now, operation on aop
cache from the GUI will not always work (unless it is a String type).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ On the second window for the interactive Java commands, type sh runShellDemo.sh to
fire off the BeanShell interactive command shell (you can use either ^D or ^Z in Windows
and Unix to exit afterward). You can then read in the Java code scripts to showcase the
cache capabilities (e.g., plain.bsh, aop.bsh, and aopWithTx.bsh). See the following for
details.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-Plain_cache">
+ <title>Plain cache</title>
+ <para>
+ Once you are in the shell, you can either execute the script to populate the cache, or
type it in manually by command line. To run the script, type
<literal>sourceRelative("plain.bsh");</literal> under the
interactive BSH shell. For this to work, you'll need to have your working
directory set to the directory in which plain.bsh resides (otherwise give the full
pathname of plain.bsh). Basically, the script will create cache entries that will be
replicated onto the GUI. (You may have to type show() into the resulting beanshell window
yourself) Here are the snippets for the script:
+ </para>
+<programlisting>import org.jboss.cache.*;
+ show(); // verbose mode for bean shell
+ TreeCache tree = new TreeCache();
+ PropertyConfigurator config = new PropertyConfigurator();
+ // configure tree cache. Needs to be in the classpath
+ config.configure(tree, "META-INF/replSync-service.xml");
+ tree.startService();
+ // kick start tree cache
+ tree.put("/a/b/c", "ben", "me");
+ // create a cache entry.
+ // Node "/a/b/c" will be created if it does not yet exist.
+
+</programlisting>
+ <para>
+ You should see in the GUI that a new entry of <literal>/a/b/c</literal>
has been created. Click on the node c to see the content. You can modify the contents from
the GUI as well. To create another node, for example, you can type in the shell:
+ </para>
+<programlisting>tree.put("/a/b/c/d", "JBoss", "Open
Source");
+ tree.get("/a/b/c/d", "JBoss");
+
+</programlisting>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-PojoCache">
+ <title>PojoCache</title>
+ <para>
+ Once you are in the shell, type
<literal>sourceRelative("aop.bsh");</literal> to execute the shell
script. Basically, aop.bsh illustrates the steps to instantiate a cache, configure it, and
then create entries under it. Here are the snippets:
+ </para>
+<programlisting>import org.jboss.cache.PropertyConfigurator;
+ import org.jboss.cache.aop.PojoCache;
+ import org.jboss.cache.aop.test.Person;
+ import org.jboss.cache.aop.test.Address;
+ show(); // verbose mode for bean shell
+ PojoCache tree = new PojoCache();
+ PropertyConfigurator config = new PropertyConfigurator(); // configure tree
cache.
+ config.configure(tree, "META-INF/replSync-service.xml");
+ Person joe = new Person(); // instantiate a Person object named joe
+ joe.setName("Joe Black");
+ joe.setAge(31);
+ Address addr = new Address(); // instantiate a Address object named addr
+ addr.setCity("Sunnyvale");
+ addr.setStreet("123 Albert Ave");
+ addr.setZip(94086); joe.setAddress(addr); // set the address reference
+ tree.startService(); // kick start tree cache
+ tree.putObject("/aop/joe", joe);
+ // add aop sanctioned object (and sub-objects) into cache.
+ // since it is aop-sanctioned, use of plain get/set methods will take care
+ // of cache contents automatically.
+ joe.setAge(41);
+
+</programlisting>
+ <para>
+ Note the API needed to put the object (and its dependent ones) into cache is
putObject. Once the second window finishes execution, you should see the first GUI window
has been populated with entries of /aop/joe/address. Click on each tree node will display
different values associated with that node.
+ </para>
+ <para>
+ Next step to see AOP in action, you can do plain get/set methods without ever worrying
about put it in the cache. For example, you can do in the shell window joe.setAge(20); and
see that GUI gets updated with the age field automatically (if not, click away and back
will refresh the GUI content). Also to demonstrate the object graph replication, you can
modify Joe's address and see the cache will update it automatically. For example,
type addr.setCity("San Jose"); in the interactive shell, you should see in the
GUI that the address got modified.
+ </para>
+ <para>
+ Finally, PojoCache also supports get/set with parameter type of Collection classes
(i.e., List, Map, and Set). For example, type the following in the shell command line:
+ </para>
+<programlisting>ArrayList lang = new ArrayList();
+ lang.add("Ensligh");
+ lang.add("Mandarin");
+ joe.setLanguages(lang);
+
+</programlisting>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-PojoCache_with_Transaction">
+ <title>PojoCache with Transaction</title>
+ <para>
+ To see TreeCache transaction at work, you start with the same setup with last section
except you load the bsh of aopWithTx.bsh instead of aop.bsh. The additional snippets are:
+ </para>
+<programlisting>import org.jboss.cache.PropertyConfigurator;
+ import org.jboss.cache.aop.PojoCache;
+ import org.jboss.cache.aop.test.Person;
+ import org.jboss.cache.aop.test.Address;// Tx imports
+ import javax.transaction.UserTransaction; import javax.naming.*;
+ import org.jboss.cache.transaction.DummyTransactionManager;
+ show(); // verbose mode for bean shell
+ // Set up transaction manager
+ DummyTransactionManager.getInstance();
+ Properties prop = new Properties();
+ prop.put(Context.INITIAL_CONTEXT_FACTORY,
+ "org.jboss.cache.transaction.DummyContextFactory");
+ UserTransaction tx = (UserTransaction)new
+ InitialContext(prop).lookup("UserTransaction");
+ PojoCache tree = new PojoCache();
+ PropertyConfigurator config = new PropertyConfigurator();
+ // configure tree cache.
+ config.configure(tree, "META-INF/replSync-service.xml");
+ joe = new Person();
+ joe.setName("Joe Black");
+ joe.setAge(31);
+
+ Address addr = new Address();
+ addr.setCity("Sunnyvale");
+ addr.setStreet("123 Albert Ave");
+ addr.setZip(94086);
+ joe.setAddress(addr);
+
+ tree.startService(); // kick start tree cache
+ tree.putObject("/aop/joe", joe); // add aop sanctioned object
+ // since it is aop-sanctioned, use of plain get/set methods will take care
+ of cache contents automatically.
+ // Also it is transacted
+ tx.begin();
+ joe.setAge(41);
+ joe.getAddress().setZip(95124);
+ tx.commit();
+
+</programlisting>
+ <para>
+ In this example, a default dummy transaction manager is used.
+ </para>
+<programlisting>tx.begin();
+ addr.setZip(95131);
+ tx.rollback();
+
+</programlisting>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-CacheLoader_examples">
+ <title>CacheLoader examples</title>
+ <para>
+ All the examples below are based on the JBossCache standalone distribution. We assume
the ZIP file has been unzipped into a directory <literal>jboss-cache</literal>
.
+ </para>
+ <section id="CacheLoader_examples-Local_cache_with_CacheLoader">
+ <title>Local cache with CacheLoader</title>
+ <para>
+ This demo shows a local PojoCache with a CacheLoader. We will insert a POJO into the
cache, and see that the POJO is transparently saved using the CacheLoader.
+ </para>
+ <para>
+ To run this, you have to modify
<literal>jboss-cache/output/etc/META-INF/oodb-service.xml</literal> : change
<literal>CacheLoaderConfig</literal> to point to a valid directory (create it
if it doesn't yet exist):
+ </para>
+<programlisting><attribute name="CacheLoaderConfig">
+ location=c:\\tmp\\oodb
+ </attribute>
+
+</programlisting>
+ <para>
+ Then start the beanshell and source <literal>oodb.bsh</literal> into it.
Note that <literal>oodb.bsh</literal> already contains code to create and
retrieve POJO from the cache. So remember to comment them out if you decide to create the
Person instance yourself.
+ </para>
+<programlisting>bela@laptop /cygdrive/c/jboss-cache
+ $ ./runShellDemo.sh
+ BeanShell 1.3.0 - by Pat Niemeyer (pat(a)pat.net)
+ bsh % sourceRelative("oodb.bsh");
+ interceptor chain is:
+ class org.jboss.cache.interceptors.CallInterceptor
+ class org.jboss.cache.interceptors.CacheLoaderInterceptor
+ class org.jboss.cache.interceptors.TransactionInterceptor
+ <null>
+ bsh %
+
+</programlisting>
+ <para>
+ Next, create an instance of Person, and set its address and other fields:
+ </para>
+<programlisting>bsh % p=new Person();
+ <name=null, age=0, hobbies=, address=null, skills=null,
languages=null>
+ bsh % p.age=3;
+ <3>
+ bsh % p.name="Michelle";
+ <Michelle>
+ bsh % addr=new Address();
+ <street=null, city=null, zip=0>
+ bsh % addr.city="San Jose";
+ <San Jose>
+ bsh % addr.zip=95124;
+ <95124>
+ bsh % addr.street="1704 Almond Blossom Lane";
+ <1704 Almond Blossom Lane>
+ bsh % p.setAddress(addr);
+ bsh % tree.putObject("/person/me", p);
+ bsh % p;
+ <name=Michelle, age=3, hobbies=, address=street=1704 Almond Blossom
Lane,
+ city=San Jose, zip=95124, skills=null, languages=null>
+ bsh %
+
+</programlisting>
+ <para>
+ The <literal>Person</literal> object with all of its fields and
subobjects is now saved. Let's kill beanshell and restart it. At this point,
because the instance of <literal>Person</literal> we created was given the
name "p", we can retrieve it again:
+ </para>
+<programlisting>bela@laptop /cygdrive/c/jboss-cache
+ $ ./runShellDemo.sh
+ BeanShell 1.3.0 - by Pat Niemeyer (pat(a)pat.net)
+ bsh % sourceRelative("oodb.bsh");
+ interceptor chain is:
+ class org.jboss.cache.interceptors.CallInterceptor
+ class org.jboss.cache.interceptors.CacheLoaderInterceptor
+ class org.jboss.cache.interceptors.TransactionInterceptor
+ <null>
+ bsh % tree;
+ </>
+ bsh % p=tree.getObject("/person/me");
+ <name=Michelle, age=3, hobbies=, address=street=1704 Almond Blossom
Lane,
+ city=San Jose, zip=95124, skills=null, languages=null>
+ bsh % tree;
+ </p
+ /address
+ >
+ bsh %
+
+</programlisting>
+ <para>
+ The interesting thing here is that the cache was initially empty ("/").
Only when we loaded "p", did it get populated (lazy loading). You can see that
the values of "p" are loaded from the datastore where they were previously
saved.
+ </para>
+ </section>
+
+ </chapter>
+ <chapter
id="JBossCache_Tutorial-Replicated_cache_with_shared_datastore">
+ <title>Replicated cache with shared datastore</title>
+ <para>
+ The scenario that we'll run in this example is described in the documentation
for JBossCache. It consists of 2 separate nodes that replicate their contents between each
other. In addition, they both point to the <emphasis>same</emphasis>
datastore. The configuration is in file
<literal>jboss-cache/output/etc/META-INF/replAsyncSharedCacheLoader-service.xml</literal>
:
+ </para>
+<programlisting><!-- Whether or not to fetch state on joining a cluster
-->
+ <attribute
name="FetchStateOnStartup">false</attribute>
+ <attribute
name="CacheLoaderClass">org.jboss.cache.loader.FileCacheLoader</attribute>
+ <attribute name="CacheLoaderConfig">
+ location=c:\\tmp
+ </attribute>
+ <attribute
name="CacheLoaderShared">true</attribute>
+ <attribute
name="CacheLoaderPreload">/</attribute>
+ <attribute
name="CacheLoaderFetchTransientState">false</attribute>
+ <attribute
name="CacheLoaderFetchPersistentState">true</attribute>
+</programlisting>
+ <para>
+ The <literal>FetchStateOnStartup</literal> attribute set to
<literal>false</literal> means that a newly started cache will
<emphasis>not</emphasis> attempt to fetch the state (neither transient nor
persistent). Therefore, attributes
<literal>CacheLoaderFetchTransientState</literal> and
<literal>CacheLoaderFetchPersistentState</literal> will be ignored.
<literal>CacheLoaderShared</literal> set to
<literal>true</literal> means that both nodes will share the same datastore,
which resides in <literal>c:\tmp</literal> in the example (this assumes that
both nodes have access to the same file system). Please make sure that
<literal>c:\tmp</literal> exists, or point the config string to a different
existing directory.
+ </para>
+ <para>
+ This configuration would essentially provide for two
<literal>cold</literal> nodes, in the sense that all contents of a new cache
is in the datastore, and is lazy-loaded via the CacheLoader when accessed. However, this
is not true, as <literal>CacheLoaderPreload</literal> points to "/",
which is the root of the entire tree. Therefore, all of the contents of the cache are
recursively pre-loaded. This is probably a bad configuration when you have a lot of data
in the cache, because <emphasis>all</emphasis> of your data will be loaded
into the cache.
+ </para>
+ <para>
+ Note that with a shared datastore, the node that makes a modification is the one who
writes it to the store using the CacheLoader. This prevents both nodes from writing the
same data twice.
+ </para>
+ <para>
+ We can now start 2 instances by opening two shells and executing the following ANT
target:
+ </para>
+<programlisting>bela@laptop /cygdrive/c/jboss-cache
+ $ ./build.sh run.demo.async.shared.cacheloader
+ Buildfile: build.xml
+
+ init:
+
+ compile:
+
+ run.demo.async.shared.cacheloader:
+ [java] ** node loaded: /a
+ [java] ** node loaded: /a/b
+ [java] ** node loaded: /a/b/c
+ [java] ** node loaded: /uno
+ [java] ** node loaded: /uno/due
+
+ [java] -------------------------------------------------------
+ [java] GMS: address is 192.168.1.184:1357
+ [java] -------------------------------------------------------
+ [java] interceptor chain is:
+ [java] class org.jboss.cache.interceptors.CallInterceptor
+ [java] class org.jboss.cache.interceptors.ReplicationInterceptor
+ [java] class org.jboss.cache.interceptors.CacheLoaderInterceptor
+ [java] class org.jboss.cache.interceptors.TransactionInterceptor
+ [java] ** view change: [192.168.1.184:1355|1] [192.168.1.184:1355,
+ 192.168.1.184:1357]
+ [java] ** node modified: /
+
+</programlisting>
+ <para>
+ 2 GUI instances will appear, showing the tree structure of the cache graphically.
Nodes can be added, modified or removed by right-clicking or using the menu. Any
modification is replicated between the two nodes. If both nodes are killed, and
subsequently one or both nodes are restarted, the state is the same as before shutdown as
it was persisted to the shared store via the CacheLoader.
+ </para>
+ <para>
+ Note that the example above shows the 2 nodes running on the same machine
(192.168.1.184) on ports 1355 and 1357.
+ </para>
+ </chapter>
+ <chapter
id="JBossCache_Tutorial-Replicated_cache_with_unshared_local_datastore">
+ <title>Replicated cache with unshared (local) datastore</title>
+ <para>
+ In this example, we'll run 2 nodes again, but this time, instead of sharing
the same datastore, each node has its own datastore. The configuration is in file
<literal>jboss-cache/output/etc/META-INF/node{1,2}.xml</literal> .
We'll look at node1.xml:
+ </para>
+<programlisting><attribute
name="CacheLoaderClass">org.jboss.cache.loader.bdbje.BdbjeCacheLoader</attribute>
+ <attribute name="CacheLoaderConfig">
+ location=c:\\tmp\\node1
+ </attribute>
+ <attribute
name="CacheLoaderShared">false</attribute>
+ <attribute
name="CacheLoaderPreload">/</attribute>
+ <attribute
name="CacheLoaderFetchTransientState">false</attribute>
+ <attribute
name="CacheLoaderFetchPersistentState">true</attribute>
+
+</programlisting>
+ <para>
+ Again, we use the Sleepycat CacheLoader implementation in
<literal>CacheLoaderClass</literal> . The
<literal>CacheLoaderConfig</literal> points to
<literal>c:\tmp\node1</literal> . This is the directory in which the Sleepycat
DB for node1 will reside. File node2.xml has a configuration that points to
<literal>c:\tmp\node2</literal> , so we have 2 different unshared datastores.
Note that, of course, we still have the same filesystem in our case, because we run the 2
nodes on the same machine. In practice those two directories would reside on two different
machines, and each machine would run one JBossCache process. Note that the 2 directories
have to exis
+ </para>
+ <para>
+ To create an unshared datastore, we set the
<literal>CacheLoaderShared</literal> attribute to
<literal>false</literal> .
+ </para>
+ <para>
+ The example can be run by again opening 2 shells, and running 2 ANT targets (here we
show the target for node1):
+ </para>
+<programlisting>bela@laptop /cygdrive/c/jboss-cache
+ $ ./build.sh run.demo.unshared.node2
+ Buildfile: build.xml
+
+ init:
+
+ compile:
+
+ run.demo.unshared.node2:
+ [java] ** node loaded: /a
+ [java] ** node loaded: /a/a2
+ ...
+
+</programlisting>
+ <para>
+ The <literal>run.demo.unshared.node2</literal> target runs node2, which
will have its own store located at <literal>c:\tmp\node2</literal> (shown
above). Whenever a change is made on either of the 2 nodes, it is replicated to the other
node, and persisted in both local datastores. You can kill and restart a node, or even
both nodes, and the data will still be available due to the persistent backend store(s).
+ </para>
+ </chapter>
+ <chapter id="JBossCache_Tutorial-Troubleshooting">
+ <title>Troubleshooting</title>
+ <para>
+ Here are some tips for troubleshooting, if you encounter problems during this demo.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Most of the time, the problem will come from cache replication layer, i.e., JGroups
package. On the output window, you can see the JGroups membership view. See if it is
updated when you run the BSH commands. It should show a view with at least two members.
For example, on my window, I see
+ </para>
+<programlisting>[java] ** view change: [BWANG-HOME:4381|1] [BWANG-HOME:4381,
BWANG-HOME:4383]
+
+</programlisting>
+ <para>
+ with 2 members: 4381 and 4383. On the other hand, if you don't close the
previous running cache instance, the membership view will also include the previous
existing ones. This can corrupt the states. So you will have to make sure there is no
running TreeCache processes before each demo. If you have problem with this, please
consult the <ulink
url="http://www.jgroups.org/javagroupsnew/docs/index.html">J... website
</ulink>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </chapter>
+<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="Revision_History.xml"/>
+
+</book>
+