+ added exception translation

+ fixed config
+ added docs on TM management and exception translation
This commit is contained in:
costin
2010-07-02 16:17:28 +03:00
parent 2ab5d270c1
commit 0934d7f4a5
3 changed files with 54 additions and 13 deletions

View File

@@ -1,17 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="bootstrap">
<title>Bootstrapping GemFire through the Spring container</title>
<chapter id="apis">
<title>Working with the GemFire APIs</title>
<para>
Once the GemFire cache and regions have been configured, these can injected and used inside application objects. This chapter describes the integration with the
Spring transaction management, <classname>DaoException</classname> hierarchy and wiring of GemFire managed objects.
</para>
<section id="bootstrap:requirements">
<title>Requirements</title>
<para></para>
<note>
</note>
<section id="apis:exception-translation">
<title>Exception translation</title>
<para>Using a new API requires not just accommodating to the new semantics but also handling its particular exception set. To accommodate this case, Spring Framework provides a
generic, consistent exception <ulink url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/dao.html#dao-exceptions">hierarchy</ulink> that
abstracts one from proprietary (and usually checked) exceptions to a set of focused runtime exceptions. As mentioned in the Spring Framework documentation, by using annotations
(<literal>@Repository</literal>) or AOP, exception translations happens automatically without any code changes. The same holds true for GemFire as long as at least a
<classname>CacheFactoryBean</classname> is declared. The <interfacename>Cache</interfacename> factory acts as an exception translator which is automatically detected by the
Spring infrastructure and used accordingly.
</para>
</section>
<section id="apis:tx-mgmt">
<title>Transaction Management</title>
<para>One of the most popular features of Spring Framework is <ulink url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html">transaction</ulink>
management. If you are not familiar with it, we strongly recommend
<ulink url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-motivation">looking</ulink> into it as it offers a consistent programming
model that works transparently across multiple API that can be configured either programmatically or declaratively (the most popular choice).</para>
<para>For Gemfire, SGI provides a dedicated, per-cache, transaction manager that once declared, allows actions on the <interfacename>Region</interfacename>s to be grouped and executed atomically through
Spring:</para>
<programlisting><![CDATA[<bean id="transaction-manager" class="org.springframework.data.gemfire.GemfireTransactionManager" p:cache-ref="cache"/>]]></programlisting>
<para>Note that currently GemFire supports optimistic transactions with <emphasis>read committed</emphasis> isolation. Further more to guarantee this isolation, developers should
avoid making <emphasis>in-place</emphasis> changes, that is manually modifying the values present in the cache. To prevent this from happening, the transaction manager configured the cache
to use <emphasis>copy on read</emphasis> semantics, meaning a clone of the actual value is created, each time a read is performed. This behaviour can be disabled if needed through the
<literal>copyOnRead</literal> property. For more information on the semantics of the underlying GemFire transaction manager, see the GemFire
<ulink url="http://www.gemstone.com/docs/6.0.1/product/docs/japi/com/gemstone/gemfire/cache/CacheTransactionManager.html">documentation</ulink>.</para>
</section>
</chapter>

View File

@@ -29,8 +29,11 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.GemFireException;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.CacheFactory;
@@ -40,11 +43,18 @@ import com.gemstone.gemfire.distributed.DistributedSystem;
/**
* Factory used for configuring a Gemfire Cache manager. Allows either retrieval of an existing, opened cache
* or the creation of a new one.
* <p>This class implements the {@link org.springframework.dao.support.PersistenceExceptionTranslator}
* interface, as autodetected by Spring's
* {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor},
* for AOP-based translation of native exceptions to Spring DataAccessExceptions.
* Hence, the presence of this class automatically enables
* a PersistenceExceptionTranslationPostProcessor to translate GemFire exceptions.
*
* @author Costin Leau
*/
public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean,
InitializingBean, FactoryBean<Cache> {
InitializingBean, FactoryBean<Cache>, PersistenceExceptionTranslator {
private static final Log log = LogFactory.getLog(CacheFactoryBean.class);
@@ -126,6 +136,14 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
factoryLocator.destroy();
}
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
if (ex instanceof GemFireException) {
return GemfireCacheUtils.convertGemfireAccessException((GemFireException) ex);
}
return null;
}
public Cache getObject() throws Exception {
return cache;
}

View File

@@ -2,10 +2,7 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
default-lazy-init="true"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
<!-- all beans are lazy to allow the same config to be used between multiple tests -->
<!-- as there can be only one cache per VM -->
@@ -21,7 +18,6 @@
<bean id="named-cache" class="org.springframework.data.gemfire.CacheFactoryBean" p:name="named-cache">
<property name="properties">
<util:properties location="classpath:/deployment/env.properties"></util:properties>
<props>
<prop key="name">cache-with-props</prop>
</props>