DEVELOPING WITH TERRACOTTA

Added by Tushar Khairnar, last edited by Sreenivasan Iyer on Aug 11, 2009  (view change)

Labels

 
(None)

Unknown macro: {builder-pagetitle}

Contents

The page Header does not exist.

DISTRIBUTED CACHE:

Do you have an example of how to deliver a cache as a service to many client applications?

Terracotta developed an "Authinator Application" that delivers an authentication/authorization service via a Restful interface.

What are my choices with regards to Terracotta-clustered distributed caches ?

Terracotta provides:

How do I drain my cache changes to the database asynchronously?

Yes, see Notes on Tim-Async

Do you have a replacement for JBossCache?

Yes,

How do I implement a reaper for my cache?

  • TTL Based Mechanism:
    • You have to set a TTL and update _ExpirationTime for your cache-entry when it is created.
    • Periodically run a reaper thread that compares _ExpirationTime to CurrentTime and removes cache-entries if needed (or annotates them as expired)

I understand that for semantic correctness, I need to read with a READ Lock. But what if I am ok with Read-committed - when will references on any JVM become eventually correct.

Just as in the JVM Memory Model, you get no guarantees as to when Thread Memory gets flushed to Main Memory, if the 2nd thread dosen't request the same monitor - similarly, there are no guarantees (although it could range from sub-seconds to few seconds). Some applications could allow you to read without a Read-Lock (some cost savings in that no lock need be acquired), but you may read state committed prior or partially - given that ReentrantReadWriteLocks.readLocks can be doled out multiple concurrent readers, it seems to us that it is almost better to ALWAYS READ with a READ LOCK since the cost of acquiring one is significantly lower.

CLASSLOADERS:

Does Terracotta support OSGI?

Not out of the box. But one can get around it by naming/registering classloaders. We have examples of Eclipse RCP applications (based on the Equinox implementation of the OSGI framework) being clustered via this technique with Terracotta. See http://forums.terracotta.org/forums/posts/list/15/131.page

When and why do I need to explicitly name and register ClassLoaders?

Object identity in Terracotta is the name of the ClassLoader + the fully qualified field reference. Hence the need to name/register classloaders, as of now to ensure that identity gets preserved when necessary in multiple-classloader environments.

How to share a root between web appplication and java application

Users can use "-Dcom.tc.loader.system.name=Any.class.loader.name" while starting their standalone java app to give a name to the standard class loader so that shared roots can have the same loader name between the java app and the webapp.

For Tomcat - -Dcom.tc.loader.system.name=Tomcat.Catalina:localhost:/webapp_name

If the classes are loaded through ExtensionClassLoader (java/ext) please use "-Dcom.tc.loader.ext.name=classloader.name".

MISCELLANEOUS:

What are semantics associated with the Concurrent Lock ?

A Concurrent Lock in Terracotta defines a transaction boundary but gives no visibility or correctness guarantees.
There is no conversation with the Terracotta server - but the "Terracotta transaction" begins when the concurrent lock is acquired and ends when the concurrent lock is released and all mutations within are batched and committed to the Terracotta server. So with a concurrent lock, 2 threads could read or write to a shared object graph concurrently (i.e no correctness guarantees). Defining no lock implies GETS/READS might work but there is no guarantee of correctness (in that one might be able to get stale or partially committed data) - but then you would not be able to write to it. With Concurrent Lock in place, GET/READS/WRITES can all work with no guarantees around correctness. (USAGE NOT RECOMMENDED)...

How do I share data between different Applications

You can share data between different applications running on the same web container(Tomcat, Jetty, etc.) For this use app-group functionality. Refer this URL : http://www.terracotta.org/web/display/docs/Configuration+Guide+and+Reference#ConfigurationGuideandReference-appgroups

Does Terracotta support annotations?

Yes - see http://www.terracotta.org/confluence/display/labs/Annotations

How do I share large DOM tree with terracotta?

As a DOM poses certain performance challenges when stored as a Terracotta DSO it is not advisable to
share DOM directly as DSO.

Here I have attached a sample that illustrated of how to share the xml associated with the Document and then
propagate the changes to other nodes via this xml.

To avoid recreating the entire Document everytime it is accessed from the backed xml, a version of the xml and the Document is kept which is compared to check if the Document corresponds to the xml or is stale. In the latter case Document is recreated from the xml and the Document version is updated. Note that Both Document and documentVersion are transient (with respect to TC).

Anytime a Document is modified in any node the xml is updated as well as the xml version is incremented. While accessing the Document on the other node, the Document version is compared with the xml version.

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.ElementHandler;

/**
 * Wrapper over Document to incorporate clustering of document 
 * with Terracotta in the form of xmlString.
 *
 */
public class XMLDocument {

	/** Underlying document */
	private transient Document xmlDocument;
	/** Version of dom  */
	private transient long domVersion;
	/** XML String (clustered) */
	private String xmlDocString;
	/** Version of xml string (clustered)*/
	private long xmlVersion;

	public XMLDocument(String xml) throws DocumentException {
		createDocumentFromXml(xml);
	}

	public XMLDocument(Document tabletemplateDoc) {
		this.xmlDocument = tabletemplateDoc;
		updateXmlString();
	}

	public Element getRootElement() {
		return this.getXmlDocument().getRootElement();
	}

	public void setXmlDocument(Document xmlDoc) {
		this.xmlDocument = xmlDoc;
		updateXmlString();
	}

	/** This method is called when a dom is modified outside the scope of this class 
	 * to update the xmlString associated with the dom.
	 */
	public synchronized void updateXmlString() {
		this.xmlDocString = this.xmlDocument.asXML();
		this.domVersion = ++this.xmlVersion;
	}

	/**
	 * Creates the DOM from the xml provided and increments and updates the version.
	 * @param xml
	 * @throws DocumentException
	 */
	private synchronized void createDocumentFromXml(String xml)
			throws DocumentException {
		this.xmlDocument = DocumentHelper.parseText(xml);
		this.xmlDocString = xml;
		this.domVersion = ++this.xmlVersion;
	}

	public synchronized void updateOnlyXML(String xml) {
		this.xmlDocString = xml;
		++this.xmlVersion;
	}

	/**
	 * Returns the xml document, reconstructing it from the xml string if the dom version is older, i.e.
	 * the dom has been modified in another VM and the xml string being shared by TC represents the latest
	 * Document. After reconstructing the dom the domVersion is updated to the xmlVersion.
	 * @return 
	 */
	public synchronized Document getXmlDocument() {
		if ((this.xmlDocument == null || (this.xmlVersion > this.domVersion))
				&& (this.xmlDocString != null)) {
			try {
				this.xmlDocument = DocumentHelper.parseText(this.xmlDocString);
				this.domVersion = this.xmlVersion;
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		return this.xmlDocument;
	}

	public synchronized String getXmlDocumentString() {
		return this.xmlDocString;
	}

	public String asXML() {
		return this.getXmlDocumentString();
	}
}

How can a C++ app interact with Java app over SOAP?

There are plenty of SOAP clients available for most popular programming languages. Typically, the use of these client libraries follows this pattern:

1. Your program passes the name of the remote method to invoke and any necessary parameters.
2. The library assembles the appropriate XML document of a SOAP request to package this information.
3. The library passes this XML document to the SOAP server identified by a SOAP endpoint URL, much the way you point a browser at a Web server address by specifying the server's URL.
4. After the SOAP server attempts to execute the method, it assembles a SOAP response XML document around the result of the execution and passes it back to the SOAP client.
5. Upon receiving the SOAP response, the client library parses the XML to get the result of the method invocation and passes this result to the program using the library.

We developed a sample application which exposes a simple Java map api as a web service (Using Axis engine) and C++ Client accesses this webservice by using MSSoap libraries as SOAP Client. This is written using Visual Studio and created an application of type 'exe' and used these libraries to connect to the Axis engine and get the information.

Web Service :

In this application, 'cache.jws' is deployed as web service which has the following methods

String get(String key)
String put(String key, String value)
int size()

Once this is deployed in 'axis' (<Tomcat_home>/webapps/axis), the service can be accessed by following URL

http://<HOST>:<PORT>/axis/cache.jws

This C++ client can be used to call the api on web service.

For Size - soapclient.exe <endpoint-url> size

For Put - soapclient.exe <endpoint-url> put key value

For Get - soapclient.exe <endpoint-url> get key

Precautions needed while clustering Quartz with Terracotta.

While clustering quartz with terracotta, all the terracotta client nodes need to have a unique instance id. The instance id can be provided to the node using a quartz.properties file by specifying it as a jvm argument as follows : -Dorg.quartz.properties=src/instance1.properties.

The quartz .properties along with other quartz's properties will have a unique org.quartz.scheduler.instanceId property defined in it.

This issue is discussed at the following forum post : http://forums.terracotta.org/forums/posts/list/2177.page

Sample applications illustrating the usage of terracotta and spring with various open source frameworks.

1. A sample application which shows how to use ehcache with spring in a terracotta clustered environment.
http://svn.terracotta.org/svn/forge/projects/samples/trunk/samples/sample-spring-ehcache

2. A sample application which shows how to use hibernate with spring in a terracotta clustered environment.
http://svn.terracotta.org/svn/forge/projects/samples/trunk/samples/sample-spring-hibernate

3. A sample application which shows how to use quartz with spring in a terracotta clustered environment.
http://svn.terracotta.org/svn/forge/projects/samples/trunk/samples/sample-spring-quartz

4. A sample application illustrating the usage of tim-hibernate, tim-masterworker and tim-async to scale a batch processing application.
http://svn.terracotta.org/svn/forge/projects/samples/trunk/samples/sample-ehcache-mw-asyncwrite

How to run Terracotta Server as Windows Service :

1. Terracotta Eng Hung's Blog Entry : http://unserializableone.blogspot.com/2009/06/starting-terracotta-server-as-windows.html

2. Forum Discussions : http://forums.terracotta.org/forums/posts/list/1248.page