diff --git a/src/main/asciidoc/reference/data.adoc b/src/main/asciidoc/reference/data.adoc
index 8ea08eca..6a507cc0 100644
--- a/src/main/asciidoc/reference/data.adoc
+++ b/src/main/asciidoc/reference/data.adoc
@@ -65,24 +65,253 @@ Since 1.1, Spring Data GemFire provides an implementation of the Spring 3.1 http
----
-[[apis:tx-mgmt]]
-== Transaction Management
+[[apis:transaction-management]]
+== Local, Cache Transaction Management
-One of the most popular features of Spring Framework is http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction[transaction management]. If you are not familiar with it, we strongly recommend http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction-motivation[reading] about it as it offers a consistent programming model that works transparently across multiple APIs and can be configured either programmatically or declaratively (the most popular choice).
+One of the most popular features of the _Spring Framework_ is
+http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction[Transaction Management].
-For GemFire, Spring Data GemFire provides a dedicated, per-cache, transaction manager that, once declared, allows Region operations to be executed atomically through Spring:
+If you are not familiar with _Spring's_ transaction abstraction then we strongly recommend
+http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction-motivation[reading]
+about _Spring's Transaction Management_ infrastructure as it offers a consistent _programming model_ that works
+transparently across multiple APIs and can be configured either programmatically or declaratively
+(the most popular choice).
+
+For GemFire, _Spring Data GemFire_ provides a dedicated, per-cache, transaction manager that, once declared,
+allows Region operations to be executed atomically through Spring:
[source,xml]
----
----
-NOTE: The example above can be simplified even more by eliminating the `cache-ref` attribute if the GemFire Cache is defined under the default name`gemfireCache`. As with the other Spring Data GemFire namespace elements, if the Cache bean name is not configured, the aforementioned naming convention will used. Additionally, the transaction manager name is`gemfireTransactionManager` if not explicitly specified.
+NOTE: The example above can be simplified even further by eliminating the `cache-ref` attribute if the GemFire cache
+is defined under the default name, `gemfireCache`. As with the other _Spring Data GemFire_ namespace elements,
+if the cache bean name is not configured, the aforementioned naming convention will be used.
+Additionally, the transaction manager name is "`gemfireTransactionManager`" if not explicitly specified.
-Currently, GemFire supports optimistic transactions with *read committed* isolation. Furthermore, to guarantee this isolation, developers should avoid making *in-place* changes that manually modify values present in the Cache. To prevent this from happening, the transaction manager configures the Cache to use *copy on read* semantics, meaning a clone of the actual value is created, each time a read is performed. This behavior can be disabled if needed through the `copyOnRead` property. For more information on the semantics of the underlying GemFire transaction manager, see the GemFire http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/CacheTransactionManager.html[documentation].
+Currently, Pivotal GemFire supports optimistic transactions with *read committed* isolation. Furthermore, to guarantee
+this isolation, developers should avoid making *in-place* changes that manually modify values present in the cache.
+To prevent this from happening, the transaction manager configures the cache to use *copy on read* semantics by default,
+meaning a clone of the actual value is created each time a read is performed. This behavior can be disabled if needed
+through the `copyOnRead` property.
+
+For more information on the semantics and behavior of the underlying Geode transaction manager, please refer to the Geode
+http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/CacheTransactionManager.html[CacheTransactionManager Javadoc]
+as well as the http://geode.apache.org/docs/guide/11/developing/transactions/chapter_overview.html[documentation].
+
+[[apis:global-transaction-management]]
+== Global, JTA Transaction Management
+
+It is also possible for Pivotal GemFire to participate in a Global, JTA based transaction, such as a transaction managed
+by an Java EE Application Server (e.g. WebSphere Application Server, a.k.a. WAS) using Container Managed Transactions
+(CMT) along with other JTA resources.
+
+However, unlike many other JTA "compliant" resources (e.g. JMS Message Brokers like ActiveMQ), Pivotal GemFire is *not*
+an XA compliant resource. Therefore, Pivotal GemFire must be positioned as the "_Last Resource_" in a JTA transaction
+(_prepare phase_) since it does not implement the 2-phase commit protocol, or rather does not handle
+distributed transactions.
+
+Many managed environments with CMT maintain support for "_Last Resource_", non-XA compliant resources in JTA transactions
+though it is not actually required in the JTA spec. More information on what a non-XA compliant, "_Last Resource_" means
+can be found in Red Hat's https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/5/html/Administration_And_Configuration_Guide/lrco-overview.html[documentation].
+In fact, Red Hat's JBoss project, http://narayana.io/[Narayana] is one such LGPL Open Source implementation. _Narayana_
+refers to this as "_Last Resource Commit Optimization_" (LRCO). More details can be found
+http://narayana.io//docs/project/index.html#d0e1859[here].
+
+However, whether you are using Pivotal GemFire in a standalone environment with an Open Source JTA Transaction Management
+implementation that supports "_Last Resource_", or a managed environment (e.g. Java EE AS such as WAS),
+_Spring Data Geode_ has you covered.
+
+There are a series of steps you must complete to properly use Pivotal GemFire as a "_Last Resource_" in a JTA transaction
+involving more than 1 transactional resource. Additionally, there can only be 1 non-XA compliant resource
+(e.g. Pivotal GemFire) in such an arrangement.
+
+1) First, you must complete Steps 1-4 in GemFire's documentation
+http://gemfire90.docs.pivotal.io/geode/developing/transactions/JTA_transactions.html#concept_csy_vfb_wk[here].
+
+NOTE: #1 above is independent of your _Spring [Boot] and/or [Data GemFire]_ application
+and must be completed successfully.
+
+2) Referring to Step 5 in GemFire's http://gemfire90.docs.pivotal.io/geode/developing/transactions/JTA_transactions.html#concept_csy_vfb_wk[documentation],
+_Spring Data GemFire's_ Annotation support will attempt to set the `GemFireCache`, http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/GemFireCache.html#setCopyOnRead-boolean-[`copyOnRead`]
+property for you when using the `@EnableGemFireAsLastResource` annotation.
+
+However, if SDG's auto-configuration is unsuccessful then you must explicitly set the `copy-on-read` attribute on the
+`` or `` element in XML or the `copyOnRead` property of the SDG `CacheFactoryBean` class
+in JavaConfig to *true*. For example...
+
+Peer Cache XML:
+
+[source,xml]
+----
+
+----
+
+Peer Cache JavaConfig:
+
+[source,java]
+----
+ @Bean
+ CacheFacatoryBean gemfireCache() {
+
+ CacheFactoryBean gemfireCache = new CacheFactoryBean();
+
+ gemfireCache.setClose(true);
+ gemfireCache.setCopyOnRead(true);
+
+ return gemfireCache;
+ }
+----
+
+Client Cache XML:
+
+[source,xml]
+----
+
+----
+
+Client Cache JavaConfig:
+
+[source,java]
+----
+ @Bean
+ ClientCacheFacatoryBean gemfireCache() {
+
+ ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
+
+ gemfireCache.setClose(true);
+ gemfireCache.setCopyOnRead(true);
+
+ return gemfireCache;
+ }
+----
+
+NOTE: explicitly setting the `copy-on-read` attribute or optionally the `copyOnRead` property
+really should not be necessary.
+
+3) At this point, you *skip* Steps 6-8 in GemFire's http://gemfire90.docs.pivotal.io/geode/developing/transactions/JTA_transactions.html#concept_csy_vfb_wk[documentation]
+and let _Spring Data Geode_ work its magic. All you need do is annotate your _Spring_ `@Configuration` class
+with _Spring Data GemFire's_ *new* `@EnableGemFireAsLastResource` annotation and a combination of _Spring's_
+http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction[Transaction Management]
+infrastructure and _Spring Data GemFire's_ `@EnableGemFireAsLastResource` configuration does the trick.
+
+The configuration looks like this...
+
+[source,java]
+----
+@Configuration
+@EnableGemFireAsLastResource
+@EnableTransactionManagement(order = 1)
+class GeodeConfiguration {
+
+ ...
+}
+----
+
+The only requirements are...
+
+3.1) The `@EnableGemFireAsLastResource` annotation must be declared on the same _Spring_ `@Configuration` class
+where _Spring's_ `@EnableTransactionManagement` annotation is also specified.
+
+3.2) The `order` attribute of the `@EnableTransactionManagement` annotation must be explicitly set to an integer value
+that is not `Integer.MAX_VALUE` or `Integer.MIN_VALUE` (defaults to `Integer.MAX_VALUE`).
+
+Of course, hopefully you are aware that you also need to configure _Spring's_ `JtaTransactionManager`
+when using JTA Transactions like so..
+
+[source,java]
+----
+@Bean
+public JtaTransactionManager transactionManager(UserTransaction userTransaction) {
+
+ JtaTransactionManager transactionManager = new JtaTransactionManager();
+
+ transactionManager.setUserTransaction(userTransaction);
+
+ return transactionManager;
+}
+----
+
+NOTE: The configuration in section <> does *not* apply here.
+The use of _Spring Data GemFire's_ `GemfireTransactionManager` is applicable only in "Local", Cache Transactions,
+*not* "Global", JTA Transactions. Therefore, you do *not* configure the SDG `GemfireTransactionManager` in this case.
+You configure _Spring's_ `JtaTransactionManager` as shown above.
+
+For more details on using _Spring's Transaction Management_ with JTA,
+see http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#transaction-application-server-integration[here].
+
+Effectively, _Spring Data GemFire's_ `@EnableGemFireAsLastResource` annotation imports configuration containing 2 Aspect
+bean definitions that handles the GemFire `o.a.g.ra.GFConnectionFactory.getConnection()`
+and `o.a.g.ra.GFConnection.close()` operations at the appropriate points during the transactional operation.
+
+Specifically, the correct sequence of events are...
+
+1. `jtaTransation.begin()`
+
+2. `GFConnectionFactory.getConnection()`
+
+3. Call the application's `@Transactional` service method
+
+4. Either `jtaTransaction.commit()` or `jtaTransaction.rollback()`
+
+5. Finally, `GFConnection.close()`
+
+This is consistent with how you, as the application developer, would code this manually if you had to use the JTA API
++ GemFire API yourself, as shown in the
+GemFire http://gemfire90.docs.pivotal.io/geode/developing/transactions/jca_adapter_example.html#concept_swv_z2p_wk[example].
+
+Thankfully, _Spring_ does the heavy lifting for you and all you need do after applying the appropriate configuration
+(shown above) is...
+
+[source,java]
+----
+@Service
+class MyTransactionalService ... {
+
+ @Transactional
+ public someTransactionalMethod() {
+ // perform business logic interacting with and accessing multiple JTA resources atomically, here
+ }
+
+ ...
+}
+----
+
+#1 & #4 above are appropriately handled for you by _Spring's_ JTA based `PlatformTransactionManager` once the
+`@Transactional` boundary is entered by your application (i.e. when the `MyTransactionSerivce.someTransactionalMethod()`
+is called).
+
+#2 & #3 are handled by _Spring Data GemFire's_ new Aspects enabled with the `@EnableGemFireAsLastResource` annotation.
+
+#3 of course is the responsibility of your application.
+
+Indeed, with the appropriate logging configured, you will see the correct sequence of events...
+
+[source,xml]
+----
+2017-Jun-22 11:11:37 TRACE TransactionInterceptor - Getting transaction for [example.app.service.MessageService.send]
+
+2017-Jun-22 11:11:37 TRACE GemFireAsLastResourceConnectionAcquiringAspect - Acquiring GemFire Connection
+from GemFire JCA ResourceAdapter registered at [gfe/jca]
+
+2017-Jun-22 11:11:37 TRACE MessageService - PRODUCER [ Message :
+[{ @type = example.app.domain.Message, id= MSG0000000000, message = SENT }],
+JSON : [{"id":"MSG0000000000","message":"SENT"}] ]
+
+2017-Jun-22 11:11:37 TRACE TransactionInterceptor - Completing transaction for [example.app.service.MessageService.send]
+
+2017-Jun-22 11:11:37 TRACE GemFireAsLastResourceConnectionClosingAspect - Closed GemFire Connection @ [Reference [...]]
+----
+
+For more details on using Pivotal GemFire in JTA transactions,
+see http://gemfire90.docs.pivotal.io/geode/developing/transactions/JTA_transactions.html[here].
+
+For more details on configuring Pivotal GemFire as a "_Last Resource_",
+see http://gemfire90.docs.pivotal.io/geode/developing/transactions/JTA_transactions.html#concept_csy_vfb_wk[here].
-:leveloffset: +1
include::{basedocdir}/reference/cq-container.adoc[]
+
:leveloffset: -1
[[apis:declarable]]
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableGemFireAsLastResource.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableGemFireAsLastResource.java
new file mode 100644
index 00000000..4881c301
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableGemFireAsLastResource.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.gemfire.config.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.context.annotation.Import;
+
+/**
+ * The {@link EnableGemFireAsLastResource} annotation is used to enable GemFire as a Last Resource in a Spring,
+ * CMT/JTA Transaction.
+ *
+ * @author John Blum
+ * @see org.springframework.context.annotation.EnableAspectJAutoProxy
+ * @see org.springframework.context.annotation.Import
+ * @see org.springframework.data.gemfire.config.annotation.GemFireAsLastResourceConfiguration
+ * @since 2.0.0
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@EnableAspectJAutoProxy
+@Import(GemFireAsLastResourceConfiguration.class)
+@SuppressWarnings("unused")
+public @interface EnableGemFireAsLastResource {
+
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/EnableRegionDataAccessTracing.java b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableRegionDataAccessTracing.java
new file mode 100644
index 00000000..de9b712d
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/EnableRegionDataAccessTracing.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.gemfire.config.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.context.annotation.Import;
+
+/**
+ * The EnableRegionDataAccessTracing class...
+ *
+ * @author John Blum
+ * @since 1.0.0
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Inherited
+@Documented
+@EnableAspectJAutoProxy
+@Import(RegionDataAccessTracingConfiguration.class)
+@SuppressWarnings("unused")
+public @interface EnableRegionDataAccessTracing {
+
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/GemFireAsLastResourceConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/GemFireAsLastResourceConfiguration.java
new file mode 100644
index 00000000..28abf480
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/GemFireAsLastResourceConfiguration.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.gemfire.config.annotation;
+
+import java.util.Map;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportAware;
+import org.springframework.core.annotation.AnnotationAttributes;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionAcquiringAspect;
+import org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionClosingAspect;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.util.Assert;
+
+/**
+ * The {@link GemFireAsLastResourceConfiguration} class is a Spring {@link Configuration @Configuration}
+ * annotated class used to configure the GemFire "Last Resource" Spring Data GemFire {@link Aspect Aspects}.
+ *
+ * @author John Blum
+ * @see org.aspectj.lang.annotation.Aspect
+ * @see org.springframework.context.annotation.Bean
+ * @see org.springframework.context.annotation.Configuration
+ * @see org.springframework.context.annotation.ImportAware
+ * @see org.springframework.core.annotation.AnnotationAttributes
+ * @see org.springframework.core.type.AnnotationMetadata
+ * @see org.springframework.data.gemfire.config.annotation.EnableGemFireAsLastResource
+ * @see org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionAcquiringAspect
+ * @see org.springframework.data.gemfire.config.annotation.support.GemFireAsLastResourceConnectionClosingAspect
+ * @see org.springframework.transaction.annotation.EnableTransactionManagement
+ * @see com.gemstone.gemfire.cache.GemFireCache
+ * @since 1.9.0
+ */
+@Configuration
+@SuppressWarnings("unused")
+public class GemFireAsLastResourceConfiguration implements ImportAware {
+
+ private Integer enableTransactionManagementOrder;
+
+ /* (non-Javadoc) */
+ @Override
+ public void setImportMetadata(AnnotationMetadata importMetadata) {
+ this.enableTransactionManagementOrder = resolveEnableTransactionManagementOrder(importMetadata);
+ }
+
+ /* (non-Javadoc) */
+ @SuppressWarnings("all")
+ protected int resolveEnableTransactionManagementOrder(AnnotationMetadata importMetadata) {
+
+ AnnotationAttributes enableTransactionManagementAttributes =
+ resolveEnableTransactionManagementAttributes(importMetadata);
+
+ Integer order = enableTransactionManagementAttributes.getNumber("order");
+
+ return validateOrder(order);
+ }
+
+ /* (non-Javadoc) */
+ private Integer validateOrder(Integer order) {
+
+ if (isInvalidOrder(order)) {
+ throw new IllegalArgumentException(String.format(
+ "The @%1$s(order) attribute value [%2$s] must be explicitly set to a value other than Integer.MAX_VALUE"
+ + " or Integer.MIN_VALUE", EnableTransactionManagement.class.getSimpleName(),
+ String.valueOf(order)));
+ }
+
+ return order;
+ }
+
+ /* (non-Javadoc) */
+ private boolean isInvalidOrder(Integer order) {
+ return !isValidOrder(order);
+ }
+
+ /* (non-Javadoc) */
+ private boolean isValidOrder(Integer order) {
+ return !(order == null || order == Integer.MAX_VALUE || order == Integer.MIN_VALUE);
+ }
+
+ /* (non-Javadoc) */
+ @SuppressWarnings("all")
+ protected AnnotationAttributes resolveEnableTransactionManagementAttributes(
+ AnnotationMetadata importMetadata) {
+
+ Map enableTransactionManagementAttributes =
+ importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName());
+
+ return validate(enableTransactionManagementAttributes);
+ }
+
+ /* (non-Javadoc) */
+ private AnnotationAttributes validate(Map enableTransactionManagementAttributes) {
+
+ Assert.state(enableTransactionManagementAttributes != null,
+ String.format("The @%1$s annotation may only be used on a Spring application @%2$s class"
+ + " that is also annotated with @%3$s having an explicit [order] set",
+ EnableGemFireAsLastResource.class.getSimpleName(), Configuration.class.getSimpleName(),
+ EnableTransactionManagement.class.getSimpleName()));
+
+ return AnnotationAttributes.fromMap(enableTransactionManagementAttributes);
+ }
+
+ /* (non-Javadoc) */
+ protected Integer getEnableTransactionManagementOrder() {
+
+ Assert.state(this.enableTransactionManagementOrder != null,
+ String.format("The @%1$s(order) attribute was not properly set [%2$s]; Also, please make your"
+ + " Spring application @%3$s annotated class is annotated with both @%4$s and @%1$s",
+ EnableTransactionManagement.class.getSimpleName(), this.enableTransactionManagementOrder,
+ Configuration.class.getSimpleName(), EnableGemFireAsLastResource.class.getSimpleName()));
+
+ return this.enableTransactionManagementOrder;
+ }
+
+ /* (non-Javadoc) */
+ @Bean
+ public Object gemfireCachePostProcessor(@Autowired(required = false) GemFireCache gemfireCache) {
+
+ if (gemfireCache != null) {
+ gemfireCache.setCopyOnRead(true);
+ }
+
+ return null;
+ }
+
+ /* (non-Javadoc) */
+ @Bean
+ public GemFireAsLastResourceConnectionAcquiringAspect gemfireJcaConnectionAcquiringAspect() {
+
+ GemFireAsLastResourceConnectionAcquiringAspect connectionAcquiringAspect =
+ new GemFireAsLastResourceConnectionAcquiringAspect();
+
+ int order = (getEnableTransactionManagementOrder() + 1);
+
+ connectionAcquiringAspect.setOrder(order);
+
+ return connectionAcquiringAspect;
+ }
+
+ /* (non-Javadoc) */
+ @Bean
+ public GemFireAsLastResourceConnectionClosingAspect gemfireJcaConnectionClosingAspect() {
+
+ GemFireAsLastResourceConnectionClosingAspect connectionClosingAspect =
+ new GemFireAsLastResourceConnectionClosingAspect();
+
+ int order = (getEnableTransactionManagementOrder() - 1);
+
+ connectionClosingAspect.setOrder(order);
+
+ return connectionClosingAspect;
+ }
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/RegionDataAccessTracingConfiguration.java b/src/main/java/org/springframework/data/gemfire/config/annotation/RegionDataAccessTracingConfiguration.java
new file mode 100644
index 00000000..a85c6346
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/RegionDataAccessTracingConfiguration.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.gemfire.config.annotation;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.gemfire.config.annotation.support.RegionDataAccessTracingAspect;
+
+/**
+ * The RegionDataAccessTracingConfiguration class...
+ *
+ * @author John Blum
+ * @since 1.0.0
+ */
+@Configuration
+@SuppressWarnings("unused")
+public class RegionDataAccessTracingConfiguration {
+
+ /* (non-Javadoc) */
+ @Bean
+ public RegionDataAccessTracingAspect regionDataAccessTracingAspect() {
+ return new RegionDataAccessTracingAspect();
+ }
+}
diff --git a/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractGemFireAsLastResourceAspectSupport.java b/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractGemFireAsLastResourceAspectSupport.java
new file mode 100644
index 00000000..db9495e2
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/config/annotation/support/AbstractGemFireAsLastResourceAspectSupport.java
@@ -0,0 +1,600 @@
+/*
+ * Copyright 2017 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.gemfire.config.annotation.support;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.resource.ResourceException;
+
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.ra.GFConnection;
+import com.gemstone.gemfire.ra.GFConnectionFactory;
+
+import org.aspectj.lang.annotation.Pointcut;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.Ordered;
+import org.springframework.data.gemfire.GemfireUtils;
+import org.springframework.util.StringUtils;
+
+/**
+ * {@link AbstractGemFireAsLastResourceAspectSupport} is an abstract base class encapsulating functionality common
+ * to all AOP Aspect extensions/implementations involving the GemFire JCA ResourceAdapter object registered in
+ * the JNDI context of a managed environment.
+ *
+ * @author John Blum
+ * @see javax.naming.Context
+ * @see com.gemstone.gemfire.cache.GemFireCache
+ * @see com.gemstone.gemfire.ra.GFConnection
+ * @see org.slf4j.Logger
+ * @see org.springframework.core.Ordered
+ * @since 1.0.0
+ */
+@SuppressWarnings("unused")
+public class AbstractGemFireAsLastResourceAspectSupport implements Ordered {
+
+ protected static final boolean DEFAULT_THROW_ON_ERROR = false;
+
+ protected static final int DEFAULT_ORDER = Integer.MAX_VALUE;
+
+ protected static final Consumer NO_OP_LOGGER = new Consumer() {
+ @Override
+ public void accept(String obj) {
+ }
+ };
+
+ protected static final String DEFAULT_GEMFIRE_JCA_RESOURCE_ADAPTER_JNDI_NAME = "gfe/jca";
+
+ private boolean throwOnError = DEFAULT_THROW_ON_ERROR;
+
+ private int order = DEFAULT_ORDER;
+
+ @Autowired(required = false)
+ private Context context;
+
+ @Autowired(required = false)
+ private GemFireCache gemfireCache;
+
+ private final Logger logger = newLogger();
+
+ @Value("${spring.data.gemfire.jca.resource-adapter.jndi.name:"
+ + DEFAULT_GEMFIRE_JCA_RESOURCE_ADAPTER_JNDI_NAME + "}")
+ private String gemfireJcaResourceAdapterJndiName;
+
+ @Value("${spring.data.gemfire.naming.context.factory:}")
+ private String initialContextFactory;
+
+ @Value("${spring.data.gemfire.naming.context.provider-url:}")
+ private String providerUrl;
+
+ /**
+ * Returns a reference to the naming {@link Context}.
+ *
+ * @return a reference to the naming {@link Context}.
+ * @see javax.naming.Context
+ */
+ protected synchronized Context getContext() {
+ return this.context;
+ }
+
+ /**
+ * Returns a reference to the {@link GemFireCache} used to interact with GemFire.
+ *
+ * @param {@link Class} sub-type of the {@link GemFireCache} in use.
+ * @return a reference to the {@link GemFireCache}.
+ * @see com.gemstone.gemfire.cache.GemFireCache
+ */
+ @SuppressWarnings("unchecked")
+ protected synchronized T getGemFireCache() {
+ return (T) this.gemfireCache;
+ }
+
+ /**
+ * Returns the configured reference to GemFire's JCA ResourceAdapter registered in the managed environment's
+ * JNDI context.
+ *
+ * @return a {@link String} containing the configured reference to GemFire's JCA ResourceAdapter
+ * registered in the managed environment's JNDI context.
+ */
+ public String getGemFireJcaResourceAdapterJndiName() {
+ return this.gemfireJcaResourceAdapterJndiName;
+ }
+
+ /**
+ * Returns the configured, fully-qualified classname of the {@link javax.naming.spi.InitialContextFactory}
+ * used to construct the {@link InitialContext} that is then used to lookup managed objects registered
+ * in the JNDI context of the managed environment.
+ *
+ * @return the configured, fully-qualified classname of the {@link javax.naming.spi.InitialContextFactory}
+ * used to construct the {@link InitialContext}.
+ */
+ public String getInitialContextFactory() {
+ return this.initialContextFactory;
+ }
+
+ /**
+ * Returns a reference to the {@link Logger} used to record debug, info, warning and error messages
+ * logged by the application.
+ *
+ * @return a reference to the configured {@link Logger} used by the application for logging purposes.
+ * @see org.slf4j.Logger
+ */
+ protected Logger getLogger() {
+ return this.logger;
+ }
+
+ /**
+ * Sets the order of this AOP Aspect relative to other Aspects in the chain of Aspects configured
+ * in Spring's Transaction Management.
+ *
+ * @param order int value specifying the relative order of this Aspect.
+ * @see org.springframework.core.Ordered
+ */
+ public void setOrder(int order) {
+ this.order = order;
+ }
+
+ /**
+ * Returns the order of this AOP Aspect relative to other Aspects in the chain of Aspects configured
+ * in Spring's Transaction Management.
+ *
+ * @return an int value specifying the relative order of this Aspect.
+ * @see org.springframework.core.Ordered
+ */
+ @Override
+ public int getOrder() {
+
+ int order = this.order;
+
+ return (!(order == Integer.MAX_VALUE || order == Integer.MIN_VALUE) ? order : getDefaultOrder());
+ }
+
+ /**
+ * Returns the default order used by this AOP Aspect in the chain of Aspects configured
+ * in Spring's Transaction Management.
+ *
+ * @return an int value specifying the default order used by this AOP Aspect in the chain of Aspects
+ * configured in Spring's Transaction Management.
+ */
+ protected Integer getDefaultOrder() {
+ return DEFAULT_ORDER;
+ }
+
+ /**
+ * Returns the URL of the Naming Context Provider as a {@link String}.
+ *
+ * @return the URL of the Naming Context Provider.
+ */
+ public String getProviderUrl() {
+ return this.providerUrl;
+ }
+
+ /**
+ * Determines whether an Exception should be thrown when this Aspect is unable to perform its function.
+ *
+ * Alternatively (and by default) the error condition is simply logged.
+ *
+ * Defaults to {@literal false}.
+ *
+ * @return a boolean value indicating whether this Aspect should throw an Exception when an error occurs
+ * preventing this Aspect from performing its normal function.
+ */
+ public boolean isThrowOnError() {
+ return this.throwOnError;
+ }
+
+ /**
+ * Defines an AOP Pointcut identifying Join Points during the execution of the application's components
+ * on which this Aspect should be applied.
+ *
+ * This particular Pointcut identifies {@link org.springframework.transaction.annotation.Transactional} annotated
+ * application service {@link Class types}. That is, the {@link org.springframework.transaction.annotation.Transactional}
+ * annotation is used at the class level.
+ *
+ * @see org.aspectj.lang.annotation.Pointcut
+ */
+ @Pointcut("@within(org.springframework.transaction.annotation.Transactional)")
+ protected void atTransactionalType() {}
+
+ /**
+ * Defines an AOP Pointcut identifying Join Points during the execution of the application's components
+ * on which this Aspect should be applied.
+ *
+ * This particular Pointcut identifies {@link org.springframework.transaction.annotation.Transactional} annotated
+ * application service {@link java.lang.reflect.Method methods}. That is, the
+ * {@link org.springframework.transaction.annotation.Transactional} annotation is used at the service class,
+ * service {@link java.lang.reflect.Method method} level.
+ *
+ * @see org.aspectj.lang.annotation.Pointcut
+ */
+ @Pointcut("@annotation(org.springframework.transaction.annotation.Transactional)")
+ protected void atTransactionalMethod() {}
+
+ /**
+ * Formats the given {@link String message} with the provided array of {@link Object arguments}.
+ *
+ * @param message {@link String} containing the message to format.
+ * @param args array of {@link Object arguments} used to format the message.
+ * @return the {@link String message} formatted with the provided array of {@link Object arguments}.
+ * @see java.lang.String#format(String, Object...)
+ */
+ protected String format(String message, Object... args) {
+ return String.format(message, args);
+ }
+
+ /**
+ * Logs the given {@link String message} formatted with the given array of {@link Object arguments}
+ * at {@link Level#DEBUG} level when debugging is enabled.
+ *
+ * @param {@link Class} type extension of {@link AbstractGemFireAsLastResourceAspectSupport}.
+ * @param message {@link String} containing the message to log.
+ * @param args array of {@link Object arguments} used to format the message.
+ * @return this aspect.
+ * @see org.slf4j.Logger#isDebugEnabled()
+ * @see org.slf4j.Logger#debug(String, Object...)
+ * @see #format(String, Object...)
+ */
+ @SuppressWarnings("unchecked")
+ protected T logDebugInfo(String message, Object... args) {
+
+ Logger logger = getLogger();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(format(message, args), args);
+ }
+
+ return (T) this;
+ }
+
+ /**
+ * Logs the given {@link String message} formatted with the given array of {@link Object arguments}
+ * at {@link Level#INFO} level when info logging is enabled.
+ *
+ * @param {@link Class} type extension of {@link AbstractGemFireAsLastResourceAspectSupport}.
+ * @param message {@link String} containing the message to log.
+ * @param args array of {@link Object arguments} used to format the message.
+ * @return this aspect.
+ * @see org.slf4j.Logger#isInfoEnabled()
+ * @see org.slf4j.Logger#info(String, Object...)
+ * @see #format(String, Object...)
+ */
+ @SuppressWarnings("unchecked")
+ protected T logInfo(String message, Object... args) {
+
+ Logger logger = getLogger();
+
+ if (logger.isInfoEnabled()) {
+ logger.info(format(message, args), args);
+ }
+
+ return (T) this;
+ }
+
+ /**
+ * Logs the given {@link String message} formatted with the given array of {@link Object arguments}
+ * at {@link Level#TRACE} level when tracing is enabled.
+ *
+ * @param {@link Class} type extension of {@link AbstractGemFireAsLastResourceAspectSupport}.
+ * @param message {@link String} containing the message to log.
+ * @param args array of {@link Object arguments} used to format the message.
+ * @return this aspect.
+ * @see #logTraceInfo(Supplier)
+ */
+ protected T logTraceInfo(final String message,
+ final Object... args) {
+
+ return logTraceInfo(new Supplier() {
+ @Override
+ public String get() {
+ return format(message, args);
+ }
+ });
+ }
+
+ /**
+ * Logs the given {@link Supplier log message} at {@link Level#TRACE} level when tracing is enabled.
+ *
+ * @param {@link Class} type extension of {@link AbstractGemFireAsLastResourceAspectSupport}.
+ * @param logMessage {@link Supplier} of the message to log.
+ * @return this aspect.
+ * @see org.slf4j.Logger#isTraceEnabled()
+ * @see org.slf4j.Logger#trace(String)
+ */
+ @SuppressWarnings("unchecked")
+ protected T logTraceInfo(Supplier logMessage) {
+
+ Logger logger = getLogger();
+
+ if (logger.isTraceEnabled()) {
+ logger.trace(logMessage.get());
+ }
+
+ return (T) this;
+ }
+
+ /**
+ * Logs the given {@link String message} formatted with the given array of {@link Object arguments}
+ * at {@link Level#WARN} level when warnings are enabled.
+ *
+ * @param {@link Class} type extension of {@link AbstractGemFireAsLastResourceAspectSupport}.
+ * @param message {@link String} containing the message to log.
+ * @param args array of {@link Object arguments} used to format the message.
+ * @return this aspect.
+ * @see org.slf4j.Logger#isWarnEnabled()
+ * @see org.slf4j.Logger#warn(String, Object...)
+ * @see #format(String, Object...)
+ */
+ @SuppressWarnings("unchecked")
+ protected T logWarning(String message, Object... args) {
+
+ Logger logger = getLogger();
+
+ if (logger.isWarnEnabled()) {
+ logger.warn(format(message, args), args);
+ }
+
+ return (T) this;
+ }
+
+ /**
+ * Logs the given {@link String message} formatted with the given array of {@link Object arguments}
+ * at {@link Level#ERROR} level when error logging is enabled.
+ *
+ * @param {@link Class} type extension of {@link AbstractGemFireAsLastResourceAspectSupport}.
+ * @param message {@link String} containing the message to log.
+ * @param args array of {@link Object arguments} used to format the message.
+ * @return this aspect.
+ * @see org.slf4j.Logger#isErrorEnabled()
+ * @see org.slf4j.Logger#error(String, Object...)
+ * @see #format(String, Object...)
+ */
+ @SuppressWarnings("unchecked")
+ protected T logError(String message, Object... args) {
+
+ Logger logger = getLogger();
+
+ if (logger.isErrorEnabled()) {
+ logger.error(format(message, args), args);
+ }
+
+ return (T) this;
+ }
+
+ /**
+ * Constructs a new instance of the {@link InitialContext} configured with the given {@link Hashtable environment}.
+ *
+ * @param environment {@link Hashtable} containing environment configuration meta-data used to access
+ * the JNDI context in a managed environment.
+ * @return a new instance of the {@link InitialContext} configured with the given {@link Hashtable environment}.
+ * @throws NamingException if the {@link InitialContext} could not be initialized with
+ * the provided {@link Hashtable environment}.
+ * @see javax.naming.InitialContext
+ * @see java.util.Hashtable
+ */
+ protected InitialContext newInitialContext(Hashtable, ?> environment) throws NamingException {
+ return new InitialContext(environment);
+ }
+
+ /**
+ * Constructs a new instance of {@link Logger} used by this application to log messages.
+ *
+ * @return a new, configured instance of {@link Logger}.
+ */
+ protected Logger newLogger() {
+ return LoggerFactory.getLogger(getClass());
+ }
+
+ /**
+ * Resolves the {@link Context} used to perform lookups of registered, managed objects in a management environment.
+ *
+ * @return the {@link Context} used to perform lookups of registered, managed objects in a managed environment.
+ * @throws IllegalStateException if the {@link Context} could not be resolved.
+ * @see com.gemstone.gemfire.cache.GemFireCache#getJNDIContext()
+ * @see #newInitialContext(Hashtable)
+ * @see #resolveEnvironment()
+ * @see #resolveGemFireCache()
+ * @see #getContext()
+ * @see javax.naming.Context
+ */
+ protected synchronized Context resolveContext() {
+
+ Context context = getContext();
+
+ if (context == null) {
+
+ Hashtable, ?> resolvedEnvironment = resolveEnvironment();
+
+ try {
+ context = this.context = newInitialContext(resolvedEnvironment);
+ }
+ catch (NamingException cause) {
+
+ GemFireCache gemfireCache = resolveGemFireCache();
+
+ context = this.context = (gemfireCache != null ? gemfireCache.getJNDIContext() : null);
+
+ if (context == null) {
+ throw new IllegalStateException(String.format(
+ "Failed to initialize an %1$s with the provided Environment configuration [%2$s]",
+ InitialContext.class.getName(), resolvedEnvironment), cause);
+
+ }
+ }
+ }
+
+ return context;
+ }
+
+ /**
+ * Resolves the {@link Hashtable environment} used by the application to configure the {@link InitialContext}.
+ *
+ * @return the resolved {@link Hashtable environment} used to configure the {@link InitialContext}.
+ * @see #getInitialContextFactory()
+ * @see #getProviderUrl()
+ * @see java.util.Hashtable
+ */
+ protected Hashtable, ?> resolveEnvironment() {
+
+ Hashtable