From jbosscache-commits at lists.jboss.org Mon Nov 17 20:10:45 2008 Content-Type: multipart/mixed; boundary="===============8643306061093635026==" MIME-Version: 1.0 From: jbosscache-commits at lists.jboss.org To: jbosscache-commits at lists.jboss.org Subject: [jbosscache-commits] JBoss Cache SVN: r7156 - enterprise-docs/trunk/Cache_Tutorial/en-US. Date: Mon, 17 Nov 2008 20:10:45 -0500 Message-ID: --===============8643306061093635026== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: irooskov(a)redhat.com Date: 2008-11-17 20:10:44 -0500 (Mon, 17 Nov 2008) New Revision: 7156 Added: enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04.ent enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04.xml Removed: enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP03.ent enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP03.xml Modified: enterprise-docs/trunk/Cache_Tutorial/en-US/Book_Info.xml Log: updated for 4.3.4 Modified: enterprise-docs/trunk/Cache_Tutorial/en-US/Book_Info.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- enterprise-docs/trunk/Cache_Tutorial/en-US/Book_Info.xml 2008-11-18 01:= 09:42 UTC (rev 7155) +++ enterprise-docs/trunk/Cache_Tutorial/en-US/Book_Info.xml 2008-11-18 01:= 10:44 UTC (rev 7156) @@ -2,8 +2,8 @@ = - JBoss Cache Tutorial CP03 - for Use with JBoss Enterprise Application Platform 4.3 Cumulati= ve Patch 3 + JBoss Cache Tutorial CP04 + for Use with JBoss Enterprise Application Platform 4.3 Cumulati= ve Patch 4 2.0 1 JBoss Enterprise Application Platform Deleted: enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP= 03.ent =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP03.en= t 2008-11-18 01:09:42 UTC (rev 7155) +++ enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP03.en= t 2008-11-18 01:10:44 UTC (rev 7156) @@ -1,3 +0,0 @@ - - - Deleted: enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP= 03.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP03.xm= l 2008-11-18 01:09:42 UTC (rev 7155) +++ enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP03.xm= l 2008-11-18 01:10:44 UTC (rev 7156) @@ -1,503 +0,0 @@ - - - - - JBossCache Tutorial - - - Introduction - - JBossCache is an in-memory replicated (synchronous or asynchronous), tr= ansactional, and fine-grained cache. It consists of two subsystems: TreeCac= he (plain cache) and PojoCache (object-oriented POJO cache). In this tutori= al, we will demonstrate the usage of both cache features. For details of th= e usage and APIs, please refer to the user manuals for TreeCache and PojoCa= che. = - -
- Scope - - - - Cache creation and modification - - - - - Replication - - - - - PojoCache - - - - - Transaction - - - -
- = -
- - Configuration - - First download the standalone TreeCache code from here. Unzip i= t, and you will get a root directory (jboss-cache in our example). = - - - The configuration files are located under the etc directory. You can mo= dify the behavior of TreeCache through editing the various configuration fi= les. = - - - - - log4j.xml. Logging output. You can turn on logging= level or change log file directory (default is /tmp/jbosscache.lo= g). = - - - - - replSync-service.xml. Tree cache configuration fil= e (file name is not fixed. You specify the file to be read in Prop= ertyConfigurator). 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 confi= guration parameters, please refer to the Treecache. Note that this file is used i= n the BSH ( BeanShell, a l= ightweight Java compatible scripting language) script to configure the cach= e. = - - - - - jboss-aop.xml. 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 PojoCache. This file= is read in when the process is started. = - - - - - - Script - - The script files that are needed (located under install directory) in t= his tutorial are: = - - - - - build.sh (or build.bat for DOS/= Windows). Simple build script that wraps around ant. Users can simply type = sh build.sh for help. Note from now on, we will only ref= er to the Unix version with the understanding that there is a corresponding= DOS counterpart. The same goes for runDemoShell explained next. = - - - - - runDemoShell.sh. Simple run script that wraps arou= nd BeanShell. This is used to operate the replicated cache through interact= ive command line. = - - - - - plain.bsh. Java code that instantiate and configur= e the cache. It also creates an example cache entry. = - - - - - aop.bsh. Java codes that instantiate and configure= the aop cache. In addition, it also sets up the example POJO (plain old Ja= va object) classes (e.g., Person and Address). = - - - - - aopWithTx.bsh. Same with aop.bsh except it also in= stantiates a transaction context. = - - - - - - Example POJO - - The example POJO classes used for PojoCache demo are: Person and Address. They are located under te= sts/org/jboss/cache/aop directory. Person has = attributes of String age, Address addr, List languages = , 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. = - - - Here is the snippet of the class definition for Person and Address . = - -public class Person { - String name=3Dnull; - int age=3D0; - Map hobbies=3Dnull; - Address address=3Dnull; - Set skills; - List languages; - - public String getName() { return name; } - public void setName(String name) { this.name=3Dname; } - ... - } - = - -public class Address { - String street=3Dnull; - String city=3Dnull; - int zip=3D0; - - public String getStreet() { return street; } - public void setStreet(String street) { this.street=3Dstreet; } - ... - } - = - - - - Demo - - 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 t= he scripts under jboss-cache installation directory after you unzip the rel= ease package (jboss-cache-dist.zip). Due to the limitation of the GUI, plea= se note that: = - - - - - For each demo example, it'd be best if you re-start the whole set= up. - - - - - While you can modify the cache content on the GUI window and it will = show up on the BSH cache content (e.g., through cache.printDetails= () ), this won't work on PojoCache demo. That is, you can onl= y modify the cache content on the BSH window. - - - - - The two demo programs to run are: - - - - - On the first window for the GUI, type sh build.sh = to see the available commands. To run the GUI, type sh build.sh r= un.demo . It will startup a PojoCache GUI. Later on, you can clic= k 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 (u= nless it is a String type). = - - - - - On the second window for the interactive Java commands, type sh runSh= ellDemo.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.bs= h, aop.bsh, and aopWithTx.bsh). See the following for details. = - - - - - - Plain cache - - Once you are in the shell, you can either execute the script to populat= e the cache, or type it in manually by command line. To run the script, typ= e sourceRelative("plain.bsh"); under the interactive BSH= shell. For this to work, you'll need to have your working directory se= t to the directory in which plain.bsh resides (otherwise give the full path= name of plain.bsh). Basically, the script will create cache entries that wi= ll be replicated onto the GUI. (You may have to type show() into the result= ing beanshell window yourself) Here are the snippets for the script: = - -import org.jboss.cache.*; - show(); // verbose mode for bean shell - TreeCache tree =3D new TreeCache(); - PropertyConfigurator config =3D 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. - = - - - You should see in the GUI that a new entry of /a/b/c= has been created. Click on the node c to see the content. You can modify t= he contents from the GUI as well. To create another node, for example, you = can type in the shell: = - -tree.put("/a/b/c/d", "JBoss", "Open Source"); - tree.get("/a/b/c/d", "JBoss"); - = - - - - PojoCache - - Once you are in the shell, type sourceRelative("aop.bsh"); to execute the shell script. Basically, aop.bsh illustrates the step= s to instantiate a cache, configure it, and then create entries under it. H= ere are the snippets: = - -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 =3D new PojoCache(); - PropertyConfigurator config =3D new PropertyConfigurator(); // co= nfigure tree cache. - config.configure(tree, "META-INF/replSync-service.xml"); - Person joe =3D new Person(); // instantiate a Person object named= joe - joe.setName("Joe Black"); - joe.setAge(31); - Address addr =3D new Address(); // instantiate a Address object n= amed addr - addr.setCity("Sunnyvale"); - addr.setStreet("123 Albert Ave"); - addr.setZip(94086); joe.setAddress(addr); // set the address refe= rence - 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); - = - - - Note the API needed to put the object (and its dependent ones) into cac= he is putObject. Once the second window finishes execution, you should see = the first GUI window has been populated with entries of /aop/joe/address. C= lick on each tree node will display different values associated with that n= ode. = - - - Next step to see AOP in action, you can do plain get/set methods withou= t ever worrying about put it in the cache. For example, you can do in the s= hell window joe.setAge(20); and see that GUI gets updated with the age fiel= d 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 G= UI that the address got modified. = - - - Finally, PojoCache also supports get/set with parameter type of Collect= ion classes (i.e., List, Map, and Set). For example, type the following in = the shell command line: = - -ArrayList lang =3D new ArrayList(); - lang.add("Ensligh"); - lang.add("Mandarin"); - joe.setLanguages(lang); - = - - - - PojoCache with Transaction - - To see TreeCache transaction at work, you start with the same setup wit= h last section except you load the bsh of aopWithTx.bsh instead of aop.bsh.= The additional snippets are: = - -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 =3D new Properties(); - prop.put(Context.INITIAL_CONTEXT_FACTORY, - "org.jboss.cache.transaction.DummyContextFactory"); - UserTransaction tx =3D (UserTransaction)new - InitialContext(prop).lookup("UserTransaction"); - PojoCache tree =3D new PojoCache(); - PropertyConfigurator config =3D new PropertyConfigurator(); = - // configure tree cache. - config.configure(tree, "META-INF/replSync-service.xml"); - joe =3D new Person(); - joe.setName("Joe Black"); - joe.setAge(31); - - Address addr =3D 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(); - = - - - In this example, a default dummy transaction manager is used. - -tx.begin(); - addr.setZip(95131); - tx.rollback(); - = - - - - CacheLoader examples - - All the examples below are based on the JBossCache standalone distribut= ion. We assume the ZIP file has been unzipped into a directory jbo= ss-cache . = - -
- Local cache with CacheLoader - - 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 th= e CacheLoader. = - - - To run this, you have to modify jboss-cache/output/etc/META-I= NF/oodb-service.xml : change CacheLoaderConfig= to point to a valid directory (create it if it doesn't yet exist): = - -<attribute name=3D"CacheLoaderConfig"> - location=3Dc:\\tmp\\oodb - </attribute> - = - - - Then start the beanshell and source oodb.bsh into i= t. Note that oodb.bsh already contains code to create an= d retrieve POJO from the cache. So remember to comment them out if you deci= de to create the Person instance yourself. = - -bela(a)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 % - = - - - Next, create an instance of Person, and set its address and other fiel= ds: = - -bsh % p=3Dnew Person(); - <name=3Dnull, age=3D0, hobbies=3D, address=3Dnull, skills= =3Dnull, languages=3Dnull> - bsh % p.age=3D3; - <3> - bsh % p.name=3D"Michelle"; - <Michelle> - bsh % addr=3Dnew Address(); - <street=3Dnull, city=3Dnull, zip=3D0> - bsh % addr.city=3D"San Jose"; - <San Jose> - bsh % addr.zip=3D95124; - <95124> - bsh % addr.street=3D"1704 Almond Blossom Lane"; - <1704 Almond Blossom Lane> - bsh % p.setAddress(addr); - bsh % tree.putObject("/person/me", p); - bsh % p; - <name=3DMichelle, age=3D3, hobbies=3D, address=3Dstreet=3D1= 704 Almond Blossom Lane, = - city=3DSan Jose, zip=3D95124, skills=3Dnull, languages=3Dnull> - bsh % - = - - - The Person object with all of its fields and subobj= ects is now saved. Let's kill beanshell and restart it. At this point, = because the instance of Person we created was given the = name "p", we can retrieve it again: = - -bela(a)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=3Dtree.getObject("/person/me"); - <name=3DMichelle, age=3D3, hobbies=3D, address=3Dstreet=3D1= 704 Almond Blossom Lane, = - city=3DSan Jose, zip=3D95124, skills=3Dnull, languages=3Dnull> - bsh % tree; - </p - /address - > - bsh % - = - - - 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 previ= ously saved. = - -
- = -
- - Replicated cache with shared datastore - - The scenario that we'll run in this example is described in the doc= umentation for JBossCache. It consists of 2 separate nodes that replicate t= heir contents between each other. In addition, they both point to the same datastore. The configuration is in file jboss= -cache/output/etc/META-INF/replAsyncSharedCacheLoader-service.xml= : = - -<!-- Whether or not to fetch state on joining a cluster= --> - <attribute name=3D"FetchStateOnStartup">false</attrib= ute> - <attribute name=3D"CacheLoaderClass">org.jboss.cache.loa= der.FileCacheLoader</attribute> - <attribute name=3D"CacheLoaderConfig"> - location=3Dc:\\tmp - </attribute> - <attribute name=3D"CacheLoaderShared">true</attribute= > - <attribute name=3D"CacheLoaderPreload">/</attribute&g= t; - <attribute name=3D"CacheLoaderFetchTransientState">false= </attribute> - <attribute name=3D"CacheLoaderFetchPersistentState">true= </attribute> - - - The FetchStateOnStartup attribute set to fa= lse means that a newly started cache will not attempt to fetch the state (neither transient nor persistent). Therefore,= attributes CacheLoaderFetchTransientState and = CacheLoaderFetchPersistentState will be ignored. CacheLo= aderShared set to true means that both nodes w= ill share the same datastore, which resides in c:\tmp in= the example (this assumes that both nodes have access to the same file sys= tem). Please make sure that c:\tmp exists, or point the = config string to a different existing directory. = - - - This configuration would essentially provide for two cold nodes, in the sense that all contents of a new cache is in the datast= ore, and is lazy-loaded via the CacheLoader when accessed. However, this is= not true, as CacheLoaderPreload points to "/", which is= the root of the entire tree. Therefore, all of the contents of the cache a= re recursively pre-loaded. This is probably a bad configuration when you ha= ve a lot of data in the cache, because all of your dat= a will be loaded into the cache. = - - - Note that with a shared datastore, the node that makes a modification i= s the one who writes it to the store using the CacheLoader. This prevents b= oth nodes from writing the same data twice. = - - - We can now start 2 instances by opening two shells and executing the fo= llowing ANT target: = - -bela(a)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.ReplicationIntercept= or - [java] class org.jboss.cache.interceptors.CacheLoaderIntercept= or - [java] class org.jboss.cache.interceptors.TransactionIntercept= or - [java] ** view change: [192.168.1.184:1355|1] [192.168.1.184:1= 355, - 192.168.1.184:1357] - [java] ** node modified: / - = - - - 2 GUI instances will appear, showing the tree structure of the cache gr= aphically. Nodes can be added, modified or removed by right-clicking or usi= ng the menu. Any modification is replicated between the two nodes. If both = nodes are killed, and subsequently one or both nodes are restarted, the sta= te is the same as before shutdown as it was persisted to the shared store v= ia the CacheLoader. = - - - Note that the example above shows the 2 nodes running on the same machi= ne (192.168.1.184) on ports 1355 and 1357. = - - - - Replicated cache with unshared (local) datastore - - 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 configura= tion is in file jboss-cache/output/etc/META-INF/node{1,2}.xml . We'll look at node1.xml: = - -<attribute name=3D"CacheLoaderClass">org.jboss.cache= .loader.bdbje.BdbjeCacheLoader</attribute> - <attribute name=3D"CacheLoaderConfig"> - location=3Dc:\\tmp\\node1 - </attribute> - <attribute name=3D"CacheLoaderShared">false</attribut= e> - <attribute name=3D"CacheLoaderPreload">/</attribute&g= t; - <attribute name=3D"CacheLoaderFetchTransientState">false= </attribute> - <attribute name=3D"CacheLoaderFetchPersistentState">true= </attribute> - = - - - Again, we use the Sleepycat CacheLoader implementation in Cach= eLoaderClass . The CacheLoaderConfig points to= c:\tmp\node1 . This is the directory in which the Sleep= ycat DB for node1 will reside. File node2.xml has a configuration that poin= ts to c:\tmp\node2 , so we have 2 different unshared dat= astores. Note that, of course, we still have the same filesystem in our cas= e, because we run the 2 nodes on the same machine. In practice those two di= rectories would reside on two different machines, and each machine would ru= n one JBossCache process. Note that the 2 directories have to exis = - - - To create an unshared datastore, we set the CacheLoaderShared<= /literal> attribute to false . = - - - The example can be run by again opening 2 shells, and running 2 ANT tar= gets (here we show the target for node1): = - -bela(a)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 - ... - = - - - The run.demo.unshared.node2 target runs node2, which= will have its own store located at c:\tmp\node2 (shown = above). Whenever a change is made on either of the 2 nodes, it is replicate= d to the other node, and persisted in both local datastores. You can kill a= nd restart a node, or even both nodes, and the data will still be available= due to the persistent backend store(s). = - - - - Troubleshooting - - Here are some tips for troubleshooting, if you encounter problems durin= g this demo. = - - - - - 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 membe= rship view. See if it is updated when you run the BSH commands. It should s= how a view with at least two members. For example, on my window, I see = - -[java] ** view change: [BWANG-HOME:4381|1] [BWANG-HOME:438= 1, BWANG-HOME:4383] - = - - - with 2 members: 4381 and 4383. On the other hand, if you don't cl= ose the previous running cache instance, the membership view will also incl= ude the previous existing ones. This can corrupt the states. So you will ha= ve to make sure there is no running TreeCache processes before each demo. I= f you have problem with this, please consult the JGroups website - - - - - - -
- Added: enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04= .ent =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04.en= t (rev 0) +++ enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04.en= t 2008-11-18 01:10:44 UTC (rev 7156) @@ -0,0 +1,3 @@ + + + Added: enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04= .xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04.xm= l (rev 0) +++ enterprise-docs/trunk/Cache_Tutorial/en-US/JBoss_Cache_Tutorial_CP04.xm= l 2008-11-18 01:10:44 UTC (rev 7156) @@ -0,0 +1,503 @@ + + + + + JBossCache Tutorial + + + Introduction + + JBossCache is an in-memory replicated (synchronous or asynchronous), tr= ansactional, and fine-grained cache. It consists of two subsystems: TreeCac= he (plain cache) and PojoCache (object-oriented POJO cache). In this tutori= al, we will demonstrate the usage of both cache features. For details of th= e usage and APIs, please refer to the user manuals for TreeCache and PojoCa= che. = + +
+ Scope + + + + Cache creation and modification + + + + + Replication + + + + + PojoCache + + + + + Transaction + + + +
+ = +
+ + Configuration + + First download the standalone TreeCache code from here. Unzip i= t, and you will get a root directory (jboss-cache in our example). = + + + The configuration files are located under the etc directory. You can mo= dify the behavior of TreeCache through editing the various configuration fi= les. = + + + + + log4j.xml. Logging output. You can turn on logging= level or change log file directory (default is /tmp/jbosscache.lo= g). = + + + + + replSync-service.xml. Tree cache configuration fil= e (file name is not fixed. You specify the file to be read in Prop= ertyConfigurator). 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 confi= guration parameters, please refer to the Treecache. Note that this file is used i= n the BSH ( BeanShell, a l= ightweight Java compatible scripting language) script to configure the cach= e. = + + + + + jboss-aop.xml. 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 PojoCache. This file= is read in when the process is started. = + + + + + + Script + + The script files that are needed (located under install directory) in t= his tutorial are: = + + + + + build.sh (or build.bat for DOS/= Windows). Simple build script that wraps around ant. Users can simply type = sh build.sh for help. Note from now on, we will only ref= er to the Unix version with the understanding that there is a corresponding= DOS counterpart. The same goes for runDemoShell explained next. = + + + + + runDemoShell.sh. Simple run script that wraps arou= nd BeanShell. This is used to operate the replicated cache through interact= ive command line. = + + + + + plain.bsh. Java code that instantiate and configur= e the cache. It also creates an example cache entry. = + + + + + aop.bsh. Java codes that instantiate and configure= the aop cache. In addition, it also sets up the example POJO (plain old Ja= va object) classes (e.g., Person and Address). = + + + + + aopWithTx.bsh. Same with aop.bsh except it also in= stantiates a transaction context. = + + + + + + Example POJO + + The example POJO classes used for PojoCache demo are: Person and Address. They are located under te= sts/org/jboss/cache/aop directory. Person has = attributes of String age, Address addr, List languages = , 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. = + + + Here is the snippet of the class definition for Person and Address . = + +public class Person { + String name=3Dnull; + int age=3D0; + Map hobbies=3Dnull; + Address address=3Dnull; + Set skills; + List languages; + + public String getName() { return name; } + public void setName(String name) { this.name=3Dname; } + ... + } + = + +public class Address { + String street=3Dnull; + String city=3Dnull; + int zip=3D0; + + public String getStreet() { return street; } + public void setStreet(String street) { this.street=3Dstreet; } + ... + } + = + + + + Demo + + 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 t= he scripts under jboss-cache installation directory after you unzip the rel= ease package (jboss-cache-dist.zip). Due to the limitation of the GUI, plea= se note that: = + + + + + For each demo example, it'd be best if you re-start the whole set= up. + + + + + While you can modify the cache content on the GUI window and it will = show up on the BSH cache content (e.g., through cache.printDetails= () ), this won't work on PojoCache demo. That is, you can onl= y modify the cache content on the BSH window. + + + + + The two demo programs to run are: + + + + + On the first window for the GUI, type sh build.sh = to see the available commands. To run the GUI, type sh build.sh r= un.demo . It will startup a PojoCache GUI. Later on, you can clic= k 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 (u= nless it is a String type). = + + + + + On the second window for the interactive Java commands, type sh runSh= ellDemo.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.bs= h, aop.bsh, and aopWithTx.bsh). See the following for details. = + + + + + + Plain cache + + Once you are in the shell, you can either execute the script to populat= e the cache, or type it in manually by command line. To run the script, typ= e sourceRelative("plain.bsh"); under the interactive BSH= shell. For this to work, you'll need to have your working directory se= t to the directory in which plain.bsh resides (otherwise give the full path= name of plain.bsh). Basically, the script will create cache entries that wi= ll be replicated onto the GUI. (You may have to type show() into the result= ing beanshell window yourself) Here are the snippets for the script: = + +import org.jboss.cache.*; + show(); // verbose mode for bean shell + TreeCache tree =3D new TreeCache(); + PropertyConfigurator config =3D 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. + = + + + You should see in the GUI that a new entry of /a/b/c= has been created. Click on the node c to see the content. You can modify t= he contents from the GUI as well. To create another node, for example, you = can type in the shell: = + +tree.put("/a/b/c/d", "JBoss", "Open Source"); + tree.get("/a/b/c/d", "JBoss"); + = + + + + PojoCache + + Once you are in the shell, type sourceRelative("aop.bsh"); to execute the shell script. Basically, aop.bsh illustrates the step= s to instantiate a cache, configure it, and then create entries under it. H= ere are the snippets: = + +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 =3D new PojoCache(); + PropertyConfigurator config =3D new PropertyConfigurator(); // co= nfigure tree cache. + config.configure(tree, "META-INF/replSync-service.xml"); + Person joe =3D new Person(); // instantiate a Person object named= joe + joe.setName("Joe Black"); + joe.setAge(31); + Address addr =3D new Address(); // instantiate a Address object n= amed addr + addr.setCity("Sunnyvale"); + addr.setStreet("123 Albert Ave"); + addr.setZip(94086); joe.setAddress(addr); // set the address refe= rence + 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); + = + + + Note the API needed to put the object (and its dependent ones) into cac= he is putObject. Once the second window finishes execution, you should see = the first GUI window has been populated with entries of /aop/joe/address. C= lick on each tree node will display different values associated with that n= ode. = + + + Next step to see AOP in action, you can do plain get/set methods withou= t ever worrying about put it in the cache. For example, you can do in the s= hell window joe.setAge(20); and see that GUI gets updated with the age fiel= d 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 G= UI that the address got modified. = + + + Finally, PojoCache also supports get/set with parameter type of Collect= ion classes (i.e., List, Map, and Set). For example, type the following in = the shell command line: = + +ArrayList lang =3D new ArrayList(); + lang.add("Ensligh"); + lang.add("Mandarin"); + joe.setLanguages(lang); + = + + + + PojoCache with Transaction + + To see TreeCache transaction at work, you start with the same setup wit= h last section except you load the bsh of aopWithTx.bsh instead of aop.bsh.= The additional snippets are: = + +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 =3D new Properties(); + prop.put(Context.INITIAL_CONTEXT_FACTORY, + "org.jboss.cache.transaction.DummyContextFactory"); + UserTransaction tx =3D (UserTransaction)new + InitialContext(prop).lookup("UserTransaction"); + PojoCache tree =3D new PojoCache(); + PropertyConfigurator config =3D new PropertyConfigurator(); = + // configure tree cache. + config.configure(tree, "META-INF/replSync-service.xml"); + joe =3D new Person(); + joe.setName("Joe Black"); + joe.setAge(31); + + Address addr =3D 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(); + = + + + In this example, a default dummy transaction manager is used. + +tx.begin(); + addr.setZip(95131); + tx.rollback(); + = + + + + CacheLoader examples + + All the examples below are based on the JBossCache standalone distribut= ion. We assume the ZIP file has been unzipped into a directory jbo= ss-cache . = + +
+ Local cache with CacheLoader + + 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 th= e CacheLoader. = + + + To run this, you have to modify jboss-cache/output/etc/META-I= NF/oodb-service.xml : change CacheLoaderConfig= to point to a valid directory (create it if it doesn't yet exist): = + +<attribute name=3D"CacheLoaderConfig"> + location=3Dc:\\tmp\\oodb + </attribute> + = + + + Then start the beanshell and source oodb.bsh into i= t. Note that oodb.bsh already contains code to create an= d retrieve POJO from the cache. So remember to comment them out if you deci= de to create the Person instance yourself. = + +bela(a)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 % + = + + + Next, create an instance of Person, and set its address and other fiel= ds: = + +bsh % p=3Dnew Person(); + <name=3Dnull, age=3D0, hobbies=3D, address=3Dnull, skills= =3Dnull, languages=3Dnull> + bsh % p.age=3D3; + <3> + bsh % p.name=3D"Michelle"; + <Michelle> + bsh % addr=3Dnew Address(); + <street=3Dnull, city=3Dnull, zip=3D0> + bsh % addr.city=3D"San Jose"; + <San Jose> + bsh % addr.zip=3D95124; + <95124> + bsh % addr.street=3D"1704 Almond Blossom Lane"; + <1704 Almond Blossom Lane> + bsh % p.setAddress(addr); + bsh % tree.putObject("/person/me", p); + bsh % p; + <name=3DMichelle, age=3D3, hobbies=3D, address=3Dstreet=3D1= 704 Almond Blossom Lane, = + city=3DSan Jose, zip=3D95124, skills=3Dnull, languages=3Dnull> + bsh % + = + + + The Person object with all of its fields and subobj= ects is now saved. Let's kill beanshell and restart it. At this point, = because the instance of Person we created was given the = name "p", we can retrieve it again: = + +bela(a)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=3Dtree.getObject("/person/me"); + <name=3DMichelle, age=3D3, hobbies=3D, address=3Dstreet=3D1= 704 Almond Blossom Lane, = + city=3DSan Jose, zip=3D95124, skills=3Dnull, languages=3Dnull> + bsh % tree; + </p + /address + > + bsh % + = + + + 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 previ= ously saved. = + +
+ = +
+ + Replicated cache with shared datastore + + The scenario that we'll run in this example is described in the doc= umentation for JBossCache. It consists of 2 separate nodes that replicate t= heir contents between each other. In addition, they both point to the same datastore. The configuration is in file jboss= -cache/output/etc/META-INF/replAsyncSharedCacheLoader-service.xml= : = + +<!-- Whether or not to fetch state on joining a cluster= --> + <attribute name=3D"FetchStateOnStartup">false</attrib= ute> + <attribute name=3D"CacheLoaderClass">org.jboss.cache.loa= der.FileCacheLoader</attribute> + <attribute name=3D"CacheLoaderConfig"> + location=3Dc:\\tmp + </attribute> + <attribute name=3D"CacheLoaderShared">true</attribute= > + <attribute name=3D"CacheLoaderPreload">/</attribute&g= t; + <attribute name=3D"CacheLoaderFetchTransientState">false= </attribute> + <attribute name=3D"CacheLoaderFetchPersistentState">true= </attribute> + + + The FetchStateOnStartup attribute set to fa= lse means that a newly started cache will not attempt to fetch the state (neither transient nor persistent). Therefore,= attributes CacheLoaderFetchTransientState and = CacheLoaderFetchPersistentState will be ignored. CacheLo= aderShared set to true means that both nodes w= ill share the same datastore, which resides in c:\tmp in= the example (this assumes that both nodes have access to the same file sys= tem). Please make sure that c:\tmp exists, or point the = config string to a different existing directory. = + + + This configuration would essentially provide for two cold nodes, in the sense that all contents of a new cache is in the datast= ore, and is lazy-loaded via the CacheLoader when accessed. However, this is= not true, as CacheLoaderPreload points to "/", which is= the root of the entire tree. Therefore, all of the contents of the cache a= re recursively pre-loaded. This is probably a bad configuration when you ha= ve a lot of data in the cache, because all of your dat= a will be loaded into the cache. = + + + Note that with a shared datastore, the node that makes a modification i= s the one who writes it to the store using the CacheLoader. This prevents b= oth nodes from writing the same data twice. = + + + We can now start 2 instances by opening two shells and executing the fo= llowing ANT target: = + +bela(a)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.ReplicationIntercept= or + [java] class org.jboss.cache.interceptors.CacheLoaderIntercept= or + [java] class org.jboss.cache.interceptors.TransactionIntercept= or + [java] ** view change: [192.168.1.184:1355|1] [192.168.1.184:1= 355, + 192.168.1.184:1357] + [java] ** node modified: / + = + + + 2 GUI instances will appear, showing the tree structure of the cache gr= aphically. Nodes can be added, modified or removed by right-clicking or usi= ng the menu. Any modification is replicated between the two nodes. If both = nodes are killed, and subsequently one or both nodes are restarted, the sta= te is the same as before shutdown as it was persisted to the shared store v= ia the CacheLoader. = + + + Note that the example above shows the 2 nodes running on the same machi= ne (192.168.1.184) on ports 1355 and 1357. = + + + + Replicated cache with unshared (local) datastore + + 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 configura= tion is in file jboss-cache/output/etc/META-INF/node{1,2}.xml . We'll look at node1.xml: = + +<attribute name=3D"CacheLoaderClass">org.jboss.cache= .loader.bdbje.BdbjeCacheLoader</attribute> + <attribute name=3D"CacheLoaderConfig"> + location=3Dc:\\tmp\\node1 + </attribute> + <attribute name=3D"CacheLoaderShared">false</attribut= e> + <attribute name=3D"CacheLoaderPreload">/</attribute&g= t; + <attribute name=3D"CacheLoaderFetchTransientState">false= </attribute> + <attribute name=3D"CacheLoaderFetchPersistentState">true= </attribute> + = + + + Again, we use the Sleepycat CacheLoader implementation in Cach= eLoaderClass . The CacheLoaderConfig points to= c:\tmp\node1 . This is the directory in which the Sleep= ycat DB for node1 will reside. File node2.xml has a configuration that poin= ts to c:\tmp\node2 , so we have 2 different unshared dat= astores. Note that, of course, we still have the same filesystem in our cas= e, because we run the 2 nodes on the same machine. In practice those two di= rectories would reside on two different machines, and each machine would ru= n one JBossCache process. Note that the 2 directories have to exis = + + + To create an unshared datastore, we set the CacheLoaderShared<= /literal> attribute to false . = + + + The example can be run by again opening 2 shells, and running 2 ANT tar= gets (here we show the target for node1): = + +bela(a)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 + ... + = + + + The run.demo.unshared.node2 target runs node2, which= will have its own store located at c:\tmp\node2 (shown = above). Whenever a change is made on either of the 2 nodes, it is replicate= d to the other node, and persisted in both local datastores. You can kill a= nd restart a node, or even both nodes, and the data will still be available= due to the persistent backend store(s). = + + + + Troubleshooting + + Here are some tips for troubleshooting, if you encounter problems durin= g this demo. = + + + + + 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 membe= rship view. See if it is updated when you run the BSH commands. It should s= how a view with at least two members. For example, on my window, I see = + +[java] ** view change: [BWANG-HOME:4381|1] [BWANG-HOME:438= 1, BWANG-HOME:4383] + = + + + with 2 members: 4381 and 4383. On the other hand, if you don't cl= ose the previous running cache instance, the membership view will also incl= ude the previous existing ones. This can corrupt the states. So you will ha= ve to make sure there is no running TreeCache processes before each demo. I= f you have problem with this, please consult the JGroups website + + + + + + +
+ --===============8643306061093635026==--