You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2016/02/08 17:51:57 UTC

[09/32] incubator-geode git commit: GEODE-14: Integration of GemFire Session Replication and Hibernate modules

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java
new file mode 100644
index 0000000..620a332
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireCollectionRegion.java
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.CollectionRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.CollectionRegionAccessStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory;
+
+public class GemFireCollectionRegion extends GemFireBaseRegion implements CollectionRegion {
+
+  private Logger log = LoggerFactory.getLogger(getClass());
+  
+  public GemFireCollectionRegion(Region<Object, EntityWrapper> region,
+      boolean isClient, CacheDataDescription metadata,
+      GemFireRegionFactory regionFactory) {
+    super(region, isClient, metadata, regionFactory);
+  }
+
+  @Override
+  public boolean isTransactionAware() {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  @Override
+  public CacheDataDescription getCacheDataDescription() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public CollectionRegionAccessStrategy buildAccessStrategy(
+      AccessType accessType) throws CacheException {
+    log.debug("creating collection access for region:"+this.region.getName());
+    return new CollectionAccess(this);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java
new file mode 100644
index 0000000..22ac466
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireEntityRegion.java
@@ -0,0 +1,187 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+
+import org.hibernate.cache.CacheDataDescription;
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.EntityRegion;
+import org.hibernate.cache.access.AccessType;
+import org.hibernate.cache.access.EntityRegionAccessStrategy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+import com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory;
+import com.gemstone.gemfire.modules.util.ModuleStatistics;
+
+public class GemFireEntityRegion extends GemFireBaseRegion implements EntityRegion {
+
+  private final Logger log = LoggerFactory.getLogger(getClass());
+  
+  private final boolean USE_JTA = Boolean.getBoolean("gemfiremodules.useJTA");
+  
+  /**
+   * keys for which interest has been registered already
+   */
+  private ConcurrentMap<Object, Boolean> registeredKeys = new ConcurrentHashMap<Object, Boolean>();
+
+  /**
+   * map to store the entries that were pre-fetched when the underlying region has no local storage
+   */
+  protected ConcurrentMap<Object, EntityWrapper> preFetchMap = new ConcurrentHashMap<Object, EntityWrapper>();
+  
+  public GemFireEntityRegion(Region<Object, EntityWrapper> region,
+      boolean isClient, CacheDataDescription metadata, GemFireRegionFactory regionFactory) {
+    super(region, isClient, metadata, regionFactory);
+  }
+
+  @Override
+  public boolean isTransactionAware() {
+    // there are no colocation guarantees while using hibernate
+    // so return false for a PartitionedRegion for now
+    if (USE_JTA) {
+      return true;
+    }
+    return false;
+  }
+
+  @Override
+  public CacheDataDescription getCacheDataDescription() {
+    return this.metadata;
+  }
+
+  @Override
+  public EntityRegionAccessStrategy buildAccessStrategy(AccessType accessType)
+      throws CacheException {
+    if (AccessType.READ_ONLY.equals(accessType)) {
+      log.info("creating read-only access for region: " + this.getName());
+      return new ReadOnlyAccess(this);
+    }
+    else if (AccessType.NONSTRICT_READ_WRITE.equals(accessType)) {
+      log.info("creating nonstrict-read-write access for region: "
+          + this.getName());
+      return new NonStrictReadWriteAccess(this);
+    }
+    else if (AccessType.READ_WRITE.equals(accessType)) {
+    	log.info("creating read-write access for region: "
+    	          + this.getName());
+      return new ReadWriteAccess(this);
+    }
+    else if (AccessType.TRANSACTIONAL.equals(accessType)) {
+    	log.info("creating transactional access for region: "
+    	          + this.getName());
+      return new TransactionalAccess(this);
+    }
+    throw new UnsupportedOperationException("Unknown access type: "
+        + accessType);
+  }
+
+  /**
+   * Should this region should register interest in keys.
+   * @return true for client regions with storage
+   */
+  public boolean isRegisterInterestRequired() {
+    return this.isClientRegion && this.region.getAttributes().getDataPolicy().withStorage();
+  }
+  
+  /**
+   * register interest in this key, if not already registered
+   * @param key
+   */
+  public void registerInterest(Object key) {
+    if (!this.registeredKeys.containsKey(key)) {
+      this.region.registerInterest(key);
+      this.registeredKeys.put(key, Boolean.TRUE);
+      log.debug("registered interest in key{}", key);
+    }
+  }
+  
+  public void registerInterest(Collection<?> list) {
+    // build a list of keys for which interest is not
+    // already registered
+    List<Object> interestList = new ArrayList<Object>();
+    for (Object o : list) {
+      if (!this.registeredKeys.containsKey(o)) {
+        interestList.add(o);
+      }
+    }
+    // register interest in this list
+    this.region.registerInterest(interestList);
+    log.debug("registered interest in {} keys", interestList.size());
+  }
+  
+  /**
+   * wraps the keys in {@link KeyWrapper} and calls getAll
+   * on the underlying GemFire region. When the underlying region
+   * is a proxy region, the fetched entries are stored in a local
+   * map.
+   * @param keys
+   */
+  public void getAll(Collection<?> keys) {
+    Set<KeyWrapper> wrappedKeys = new HashSet<KeyWrapper>();
+    for (Object o : keys) {
+      wrappedKeys.add(new KeyWrapper(o));
+    }
+    if (isRegisterInterestRequired()) {
+      registerInterest(wrappedKeys);
+    } else {
+      Map<Object, EntityWrapper> retVal = this.region.getAll(wrappedKeys);
+      putInLocalMap(retVal);
+    }
+  }
+
+  /**
+   * if the underlying gemfire region does not have local storage, put
+   * the pre-fetched entries in {@link #preFetchMap}
+   * @param map map of prefetched entries
+   */
+  private void putInLocalMap(Map<Object, EntityWrapper> map) {
+    if (!this.region.getAttributes().getDataPolicy().withStorage()) {
+      // if the value is null, do not cache in preFetchMap
+      for (Entry<Object, EntityWrapper> e : map.entrySet()) {
+        if (e.getValue() != null) {
+          this.preFetchMap.put(e.getKey(), e.getValue());
+          log.debug("putting key: {} value: {} in local map", e.getKey(), e.getValue());
+        }
+      }
+    }
+  }
+
+  /**
+   * If this key was pre-fetched, get the entity.
+   * @param key
+   * @return the prefetched entity
+   */
+  public EntityWrapper get(Object key) {
+    return this.preFetchMap.remove(key);
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java
new file mode 100644
index 0000000..ce06b85
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/GemFireQueryResultsRegion.java
@@ -0,0 +1,113 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.QueryResultsRegion;
+import org.hibernate.cache.Timestamper;
+import org.hibernate.cache.TimestampsRegion;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.EntryNotFoundException;
+import com.gemstone.gemfire.cache.Region;
+
+public class GemFireQueryResultsRegion implements QueryResultsRegion, TimestampsRegion {
+
+  private final Region region;
+  
+  private Logger log = LoggerFactory.getLogger(getClass());
+  
+  public GemFireQueryResultsRegion(Region region) {
+    this.region = region;
+  }
+  
+  @Override
+  public Object get(Object key) throws CacheException {
+    log.debug("get query results for {} ", key);
+    return this.region.get(key);
+  }
+
+  @Override
+  public void put(Object key, Object value) throws CacheException {
+    log.debug("For key {} putting query results {} ", key, value);
+    this.region.put(key, value);
+  }
+
+  @Override
+  public void evict(Object key) throws CacheException {
+    log.debug("removing query results for key {}", key);
+    this.region.remove(key);
+  }
+
+  @Override
+  public void evictAll() throws CacheException {
+    log.debug("clearing the query cache");
+    this.region.clear();
+  }
+
+  @Override
+  public String getName() {
+    return this.region.getName();
+  }
+
+  @Override
+  public void destroy() throws CacheException {
+    if (!this.region.isDestroyed()) {
+      this.region.destroyRegion();
+    }
+  }
+
+  @Override
+  public boolean contains(Object key) {
+    return this.region.containsKey(key);
+  }
+
+  @Override
+  public long getSizeInMemory() {
+    return -1;
+  }
+
+  @Override
+  public long getElementCountInMemory() {
+    return this.region.size();
+  }
+
+  @Override
+  public long getElementCountOnDisk() {
+    // TODO make this an overflow region
+    return -1;
+  }
+
+  @Override
+  public Map toMap() {
+    return Collections.unmodifiableMap(this.region);
+  }
+
+  @Override
+  public long nextTimestamp() {
+    return Timestamper.next();
+  }
+
+  @Override
+  public int getTimeout() {
+    return 60*1000; // all other cache providers have same value
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java
new file mode 100644
index 0000000..c321076
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/KeyWrapper.java
@@ -0,0 +1,93 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.hibernate.cache.CacheKey;
+
+import com.gemstone.gemfire.DataSerializable;
+import com.gemstone.gemfire.DataSerializer;
+
+/**
+ * wraps {@link CacheKey}, and implements equals and
+ * hashCode. This is required for register interest
+ * operation/prefetching
+ * @author sbawaska
+ *
+ */
+public class KeyWrapper implements DataSerializable {
+  
+  private Serializable key;
+  private String entityName;
+  
+  private static final String separator = "#";
+  
+  public KeyWrapper() {
+  }
+  
+  public KeyWrapper(Object p_key) {
+    if (p_key instanceof String) {
+      String stringKey = (String)p_key;
+      this.key = stringKey.substring(stringKey.indexOf(separator)+1);
+      this.entityName = stringKey.substring(0, stringKey.indexOf(separator));
+    } else {
+      CacheKey cacheKey = (CacheKey)p_key;
+      this.key = cacheKey.getKey();
+      this.entityName = cacheKey.getEntityOrRoleName();
+    }
+  }
+  
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof KeyWrapper) {
+      KeyWrapper other = (KeyWrapper)obj;
+      if (this.key.toString().equals(other.key.toString())
+          && this.entityName.equals(other.entityName)) {
+        return true;
+      }
+    }
+    return false;
+  }
+  
+  @Override
+  public int hashCode() {
+    return this.key.toString().hashCode() + this.entityName.hashCode();
+  }
+  
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(this.entityName).append(separator).append(this.key);
+    return sb.toString();
+  }
+
+  @Override
+  public void toData(DataOutput out) throws IOException {
+    DataSerializer.writeObject(this.key, out);
+    out.writeUTF(this.entityName);
+  }
+
+  @Override
+  public void fromData(DataInput in) throws IOException, ClassNotFoundException {
+    this.key = DataSerializer.readObject(in);
+    this.entityName = in.readUTF();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java
new file mode 100644
index 0000000..ad617e4
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/NonStrictReadWriteAccess.java
@@ -0,0 +1,83 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NonStrictReadWriteAccess extends Access {
+
+  private Logger log = LoggerFactory.getLogger(getClass());
+
+  public NonStrictReadWriteAccess(GemFireEntityRegion region) {
+    super(region);
+  }
+
+  @Override
+  public SoftLock lockItem(Object key, Object version) throws CacheException {
+    log.debug("lock item called for key {}", key);
+    return null;
+  }
+
+  @Override
+  public boolean afterUpdate(Object key, Object value, Object currentVersion,
+      Object previousVersion, SoftLock lock) throws CacheException {
+    log.debug("after update called for key: {} value: {}", key, value);
+    getGemFireRegion().put(getWrappedKey(key), new EntityWrapper(value, -1L));
+    return true;
+  }
+  
+  @Override
+  public boolean update(Object key, Object value, Object currentVersion,
+      Object previousVersion) throws CacheException {
+    log.debug("updating key: {} value: {}", key, value);
+    getGemFireRegion().put(getWrappedKey(key), new EntityWrapper(value, -1L));
+    return true;
+  }
+//  
+//  @Override
+//  public boolean insert(Object key, Object value, Object version)
+//      throws CacheException {
+//    log.debug("inserting key:{} value:{}", key, value);
+//    getGemFireRegion().put(key, new EntityWrapper(value, -1L));
+//    return true;
+//  }
+//  
+//  @Override
+//  public boolean afterInsert(Object key, Object value, Object version)
+//      throws CacheException {
+//    log.debug("after insert called for key:{} value:{}", key, value);
+//    getGemFireRegion().put(key, new EntityWrapper(value, -1L));
+//    return true;
+//  }
+//  
+  @Override
+  public boolean putFromLoad(Object key, Object value, long txTimestamp,
+      Object version) throws CacheException {
+    return putFromLoad(key, value, txTimestamp, version, true);
+  }
+  
+  @Override
+  public boolean putFromLoad(Object key, Object value, long txTimestamp,
+      Object version, boolean minimalPutOverride) throws CacheException {
+    log.debug("putting a new entry from load key:{} value:{}", key, value);
+    getGemFireRegion().put(getWrappedKey(key), new EntityWrapper(value, -1L));
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java
new file mode 100644
index 0000000..6f54067
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadOnlyAccess.java
@@ -0,0 +1,55 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import org.hibernate.cache.CacheException;
+import org.hibernate.cache.access.SoftLock;
+
+public class ReadOnlyAccess extends Access {
+
+  public ReadOnlyAccess(GemFireEntityRegion region) {
+    super(region);
+  }
+
+  @Override
+  public boolean insert(Object key, Object value, Object version)
+      throws CacheException {
+    throw new UnsupportedOperationException(
+        "insert not supported on read only access");
+  }
+
+  @Override
+  public boolean update(Object key, Object value, Object currentVersion,
+      Object previousVersion) throws CacheException {
+    throw new UnsupportedOperationException(
+        "update not supported on read only access");
+  }
+
+  @Override
+  public boolean afterInsert(Object key, Object value, Object version)
+      throws CacheException {
+    throw new UnsupportedOperationException(
+        "insert not supported on read only access");
+  }
+
+  @Override
+  public boolean afterUpdate(Object key, Object value, Object currentVersion,
+      Object previousVersion, SoftLock lock) throws CacheException {
+    throw new UnsupportedOperationException(
+        "update not supported on read only access");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java
new file mode 100644
index 0000000..3c80174
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/ReadWriteAccess.java
@@ -0,0 +1,36 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import org.hibernate.cache.CacheException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReadWriteAccess extends Access {
+
+  private Logger log = LoggerFactory.getLogger(getClass());
+
+  public ReadWriteAccess(GemFireEntityRegion region) {
+    super(region);
+  }
+
+  @Override
+  public boolean update(Object key, Object value, Object currentVersion,
+      Object previousVersion) throws CacheException {
+    return super.update(key, value, currentVersion, previousVersion);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java
new file mode 100644
index 0000000..76fdf77
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/RegionFactoryDelegate.java
@@ -0,0 +1,153 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+import java.util.Iterator;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.DataPolicy;
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.RegionShortcut;
+import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
+import com.gemstone.gemfire.cache.execute.FunctionService;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.modules.hibernate.GemFireCacheProvider;
+import com.gemstone.gemfire.modules.util.BootstrappingFunction;
+import com.gemstone.gemfire.modules.util.CreateRegionFunction;
+import com.gemstone.gemfire.modules.util.RegionConfiguration;
+
+public class RegionFactoryDelegate  {
+
+  private static final String LOG_FILE = "log-file";
+
+  private static final String CACHE_XML_FILE = "cache-xml-file";
+
+  private static final String DEFAULT_REGION_TYPE = RegionShortcut.REPLICATE_HEAP_LRU.name();
+
+  private static final String CLIENT_DEFAULT_REGION_TYPE = ClientRegionShortcut.PROXY.name();
+
+  protected final Properties gemfireProperties;
+  protected final Properties regionProperties;
+
+  protected Logger log = LoggerFactory.getLogger(getClass());
+  
+  private Cache cache;
+  
+  public RegionFactoryDelegate(Properties gemfireProperties, Properties regionProperties) {
+    this.gemfireProperties = gemfireProperties;
+    this.regionProperties = regionProperties;
+  }
+  
+  public GemFireCache startCache() {
+    log.info("Creating a GemFire cache");
+    checkExistingCache();
+    cache = new CacheFactory(gemfireProperties).create();
+    log.debug("GemFire cache creation completed");
+    FunctionService.onMembers(this.cache.getDistributedSystem()).execute(new BootstrappingFunction()).getResult();
+    FunctionService.registerFunction(new CreateRegionFunction(cache));
+    return cache;
+  }
+
+  /**
+   * When hibernate module is running within servlet container, we should
+   * check if http module is being used and make sure that we use 
+   * same cache-xml and log-file properties.
+   */
+  protected void checkExistingCache() {
+    Cache existingCache = GemFireCacheImpl.getInstance();
+    if (existingCache == null) {
+      return;
+    }
+    Properties existingProps = existingCache.getDistributedSystem().getProperties();
+    String cacheXML = existingProps.getProperty(CACHE_XML_FILE);
+    String logFile = existingProps.getProperty(LOG_FILE, "");
+    this.gemfireProperties.setProperty(CACHE_XML_FILE, cacheXML);
+    this.gemfireProperties.setProperty(LOG_FILE, logFile);
+    log.info("Existing GemFire cache detected. Using same "+CACHE_XML_FILE+":"+cacheXML+
+    " and "+LOG_FILE+":"+logFile+" as existing cache");
+  }
+  
+  public Region<Object, EntityWrapper> createRegion(String regionName) {
+    Region<Object, EntityWrapper> r = cache.getRegion(regionName);
+    if (r != null) {
+      // for  the peer-to-peer case, for now we assume that
+      // cache.xml will be the same for all peers
+      // TODO validate regions without this assumption
+      return r;
+    }
+    String regionType = getRegionType(regionName);
+    boolean isLocalRegion = regionType.contains("LOCAL") ? true : false;
+    RegionConfiguration regionConfig = new RegionConfiguration();
+    regionConfig.setRegionName(regionName);
+    regionConfig.setRegionAttributesId(regionType);
+    regionConfig.setCacheWriterName(EntityRegionWriter.class.getCanonicalName());
+    com.gemstone.gemfire.cache.RegionFactory<Object, EntityWrapper> rFactory = this.cache
+        .createRegionFactory(RegionShortcut.valueOf(regionType));
+    rFactory.setCacheWriter(new EntityRegionWriter());
+    if (isLocalRegion) {
+      rFactory.setDataPolicy(DataPolicy.REPLICATE);
+    }
+    r = rFactory.create(regionName);
+    // create same region on peers
+    if (!isLocalRegion) {
+      FunctionService.onMembers(this.cache.getDistributedSystem())
+          .withArgs(regionConfig).execute(CreateRegionFunction.ID).getResult();
+    }
+    return r;
+  }
+
+  /**
+   * returns the type of region to create by consulting the properties specified
+   * in hibernate.cfg.xml
+   * 
+   * @see #createRegion(String)
+   * @param regionName
+   * @return string representation of {@link RegionShortcut}
+   * @see GemFireCacheProvider
+   */
+  protected String getRegionType(String regionName) {
+    String rType = getOverridenRegionType(regionName);
+    if (rType != null) {
+      return rType.toUpperCase();
+    }
+    rType = regionProperties
+        .getProperty("gemfire.default-region-attributes-id");
+    if (rType == null) {
+      rType =  DEFAULT_REGION_TYPE;
+    }
+    return rType.toUpperCase();
+  }
+
+  private String getOverridenRegionType(String regionName) {
+    String rType = null;
+    Iterator<Object> it = regionProperties.keySet().iterator();
+    while (it.hasNext()) {
+      String current = (String)it.next();
+      if (current.contains(regionName)) {
+        rType = regionProperties.getProperty(current);
+        break;
+      }
+    }
+    return rType;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java
new file mode 100644
index 0000000..f12eab9
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/main/java/com/gemstone/gemfire/modules/hibernate/internal/TransactionalAccess.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 com.gemstone.gemfire.modules.hibernate.internal;
+
+public class TransactionalAccess extends Access {
+
+  public TransactionalAccess(GemFireEntityRegion region) {
+    super(region);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java
new file mode 100644
index 0000000..962c083
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Event.java
@@ -0,0 +1,67 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules;
+
+import java.util.Date;
+
+public class Event {
+    private Long id;
+
+    private String title;
+    private Date date;
+    private int i;
+
+    public Event() {}
+
+    public Long getId() {
+        return id;
+    }
+
+    private void setId(Long id) {
+        this.id = id;
+    }
+
+    public Date getDate() {
+        return date;
+    }
+
+    public Integer getVersion() {
+    	return i;
+    }
+    
+    public void setVersion(int i) {
+    	this.i = i;
+    }
+    
+    public void setDate(Date date) {
+        this.date = date;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+    @Override
+    public String toString() {
+    	StringBuilder b = new StringBuilder();
+    	b.append("Event:id:"+id+" title:"+title+" date:"+date);
+    	return b.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java
new file mode 100644
index 0000000..9a86f10
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/HibernateJUnitTest.java
@@ -0,0 +1,410 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.Region.Entry;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.modules.Owner.Status;
+import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.AnnotationConfiguration;
+import org.hibernate.cfg.Configuration;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.logging.Level;
+
+import static org.junit.Assert.assertEquals;
+
+@Category(IntegrationTest.class)
+public class HibernateJUnitTest {
+
+  private Logger log = LoggerFactory.getLogger(getClass());
+
+  //private static final String jdbcURL = "jdbc:hsqldb:hsql://localhost/test";
+  private static final String jdbcURL = "jdbc:hsqldb:mem:test";
+
+  static File tmpDir;
+
+  static String gemfireLog;
+
+  @Before
+  public void setUp() throws Exception {
+    // Create a per-user scratch directory
+    tmpDir = new File(System.getProperty("java.io.tmpdir"),
+            "gemfire_modules-" + System.getProperty("user.name"));
+    tmpDir.mkdirs();
+    tmpDir.deleteOnExit();
+
+    gemfireLog = tmpDir.getPath() +
+            System.getProperty("file.separator") + "gemfire_modules.log";
+  }
+
+  public static SessionFactory getSessionFactory(Properties overrideProps) {
+    System.setProperty("gemfire.home", "GEMFIREHOME");
+    Configuration cfg = new Configuration();
+    cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+    cfg.setProperty("hibernate.connection.driver_class",
+        "org.hsqldb.jdbcDriver");
+    // cfg.setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test");
+    cfg.setProperty("hibernate.connection.url", jdbcURL);
+    cfg.setProperty("hibernate.connection.username", "sa");
+    cfg.setProperty("hibernate.connection.password", "");
+    cfg.setProperty("hibernate.connection.pool_size", "1");
+    cfg.setProperty("hibernate.connection.autocommit", "true");
+    cfg.setProperty("hibernate.hbm2ddl.auto", "update");
+
+    cfg.setProperty("hibernate.cache.region.factory_class",
+        "com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory");
+    cfg.setProperty("hibernate.show_sql", "true");
+    cfg.setProperty("hibernate.cache.use_query_cache", "true");
+    //cfg.setProperty("gemfire.mcast-port", AvailablePort.getRandomAvailablePort(AvailablePort.JGROUPS)+"");
+    cfg.setProperty("gemfire.mcast-port", "0");
+    cfg.setProperty("gemfire.statistic-sampling-enabled", "true");
+    cfg.setProperty("gemfire.log-file", gemfireLog);
+    cfg.setProperty("gemfire.writable-working-dir", tmpDir.getPath());
+    //cfg.setProperty("gemfire.statistic-archive-file", "plugin-stats-file.gfs");
+    //cfg.setProperty("gemfire.default-client-region-attributes-id", "CACHING_PROXY");
+    //cfg.setProperty("gemfire.cache-topology", "client-server");
+    //cfg.setProperty("gemfire.locators", "localhost[5432]");
+    //cfg.setProperty("gemfire.log-level", "fine");
+    // cfg.setProperty("", "");
+    cfg.addClass(Person.class);
+    cfg.addClass(Event.class);
+    if (overrideProps != null) {
+      Iterator it = overrideProps.keySet().iterator();
+      while (it.hasNext()) {
+        String key = (String)it.next();
+        cfg.setProperty(key, overrideProps.getProperty(key));
+      }
+    }
+    return cfg.buildSessionFactory();
+  }
+
+  @Test
+  public void testpreload() {
+    log.info("SWAP:creating session factory In hibernateTestCase");
+
+    Session session = getSessionFactory(null).openSession();
+    log.info("SWAP:session opened");
+    session.beginTransaction();
+    Event theEvent = new Event();
+    theEvent.setTitle("title");
+    theEvent.setDate(new Date());
+    session.save(theEvent);
+    Long id = theEvent.getId();
+    session.getTransaction().commit();
+    session.beginTransaction();
+    Event ev = (Event)session.get(Event.class, id);
+    log.info("SWAP:load complete: " + ev);
+    session.getTransaction().commit();
+  }
+
+  @Test
+  public void testNothing() throws Exception {
+    java.util.logging.Logger.getLogger("org.hibernate").setLevel(Level.ALL);
+    log.info("SWAP:creating session factory In hibernateTestCase");
+
+    Session session = getSessionFactory(null).openSession();
+    log.info("SWAP:session opened");
+    // session.setFlushMode(FlushMode.COMMIT);
+    session.beginTransaction();
+    Event theEvent = new Event();
+    theEvent.setTitle("title");
+    theEvent.setDate(new Date());
+    //session.save(theEvent);
+    session.persist(theEvent);
+    Long id = theEvent.getId();
+    session.getTransaction().commit();
+    log.info("commit complete...doing load");
+    session.beginTransaction();
+    Event ev = (Event)session.load(Event.class, id);
+    log.info("load complete: " + ev);
+    log.trace("SWAP");
+    ev.setTitle("newTitle");
+    session.save(ev);
+    log.info("commit");
+    session.getTransaction().commit();
+    log.info("save complete " + ev);
+
+    session.beginTransaction();
+    ev = (Event)session.load(Event.class, id);
+    log.info("load complete: " + ev);
+    ev.setTitle("newTitle2");
+    session.save(ev);
+    log.info("commit");
+    session.getTransaction().commit();
+    log.info("save complete " + ev);
+
+    ev = (Event)session.load(Event.class, id);
+    log.info("second load " + ev);
+    session.flush();
+    session.close();
+    log.info("flush complete session:" + session);
+
+    for (int i=0; i<5; i++) {
+      session = getSessionFactory(null).openSession();
+      log.info("doing get "+id);
+      // ev = (Event) session.load(Event.class, id);
+      ev = (Event)session.get(Event.class, id);
+      log.info("third load " + ev);
+    }
+    printExistingDB();
+    Iterator it = GemFireCacheImpl.getInstance().rootRegions().iterator();
+    while (it.hasNext()) {
+      Region r = (Region)it.next();
+      System.out.println("Region:"+r);
+      Iterator enIt = r.entrySet().iterator();
+      while (enIt.hasNext()) {
+        Region.Entry re = (Entry)enIt.next();
+        System.out.println("key:"+re.getKey()+" value:"+re.getValue());
+      }
+    }
+    Thread.sleep(3000);
+     //System.in.read();
+    // try direct data
+
+  }
+
+  public void _testInvalidation() {
+    Session s = getSessionFactory(null).openSession();
+  }
+
+  static Long personId;
+
+  @Test
+  public void testRelationship() throws Exception {
+    //java.util.logging.Logger.getLogger("org.hibernate").setLevel(Level.ALL);
+    Properties props = new Properties();
+    props.put("gemfire.topology", "client-server");
+    Session session = getSessionFactory(null).openSession();
+    session.beginTransaction();
+
+    Person thePerson = new Person();
+    thePerson.setFirstname("foo");
+    thePerson.setLastname("bar");
+    thePerson.setAge(1);
+    thePerson.setId(99L);
+    session.save(thePerson);
+    personId = thePerson.getId();
+    log.info("person saved");
+    
+    Event theEvent = new Event();
+    theEvent.setTitle("title");
+    theEvent.setDate(new Date());
+    session.save(theEvent);
+    Long eventId = theEvent.getId();
+    log.info("event saved");
+    
+    Event theEvent2 = new Event();
+    theEvent2.setTitle("title2");
+    theEvent2.setDate(new Date());
+    session.save(theEvent2);
+    Long eventId2 = theEvent2.getId();
+    log.info("event2 saved");
+    session.getTransaction().commit();
+    
+    session.beginTransaction();
+    Person aPerson = (Person) session.load(Person.class, personId);
+    Event anEvent = (Event) session.load(Event.class, eventId);
+    Event anEvent2 = (Event) session.load(Event.class, eventId2);
+    log.info("adding event to person");
+    aPerson.getE().add(anEvent);
+    aPerson.getE().add(anEvent2);
+    log.info("calling commit");
+
+    session.getTransaction().commit();
+    log.info("commit complete");
+    session.close();
+    log.info("opening new session");
+    session = getSessionFactory(null).openSession();
+    log.info("SWAP:loading person");
+    aPerson = (Person)session.load(Person.class, personId);
+    log.info("loading events");
+    Iterator<Event> e = aPerson.getE().iterator();
+    while (e.hasNext()) {
+      e.next();
+    }
+    session.close();
+    log.info("opening new session");
+    session = getSessionFactory(null).openSession();
+    log.info("SWAP:loading person");
+    aPerson = (Person)session.load(Person.class, personId);
+    log.info("loading events");
+    e = aPerson.getE().iterator();
+    while (e.hasNext()) {
+      e.next();
+    }
+
+    log.info(aPerson.getE()+"");
+    session.close();
+    //System.in.read();
+//    log.info("opening third session");
+//    session = getSessionFactory().openSession();
+//    log.info("loading person");
+//    aPerson = (Person)session.load(Person.class, personId);
+//    log.info("loading events");
+//    log.info(aPerson.getEvents()+"");
+  }
+  
+  public void _testQueryCache() throws Exception {
+    Session session = getSessionFactory(null).openSession();
+    Query q = session.createQuery("from Event");
+    q.setCacheable(true);
+    List l = q.list();
+    log.info("list:"+l);
+//    log.info("Sleeping for 10 seconds");
+//    Thread.sleep(10000);
+    l = q.list();
+    log.info("list2:"+l);
+    log.info("updating an event");
+    session.beginTransaction();
+    Event e = (Event)l.get(0);
+    e.setDate(new Date());
+    session.saveOrUpdate(e);
+    session.getTransaction().commit();
+    l = q.list();
+    log.info("list3:"+l);
+  }
+
+  @Test
+  public void testInsert() {
+    Session session = getSessionFactory(null).openSession();
+    Region r = GemFireCacheImpl.getExisting().getRegion(Person.class.getCanonicalName());
+    int initSize = r.size();
+    session.beginTransaction();
+    log.info("SWAP: Saving Person");
+    Person p = new Person();
+    p.setId(10L);
+    p.setFirstname("foo");
+    p.setLastname("bar");
+    session.saveOrUpdate("Person", p);
+    session.getTransaction().commit();
+    assertEquals(1, session.getStatistics().getEntityCount());
+    assertEquals(initSize+1, r.size());
+
+    session.beginTransaction();
+    p.setAge(1);
+    session.saveOrUpdate(p);
+    session.getTransaction().commit();
+    assertEquals(1, session.getStatistics().getEntityCount());
+  }
+
+  @Test
+  public void testNormalRegion() {
+    Properties props = new Properties();
+    props.setProperty("gemfire.default-region-attributes-id", "LOCAL");
+    Session session = getSessionFactory(props).openSession();
+    session.beginTransaction();
+    Event theEvent = new Event();
+    theEvent.setTitle("title");
+    theEvent.setDate(new Date());
+    session.save(theEvent);
+    Long id = theEvent.getId();
+    session.getTransaction().commit();
+    session.beginTransaction();
+    Event ev = (Event)session.load(Event.class, id);
+    ev.setTitle("newTitle");
+    session.save(ev);
+    session.getTransaction().commit();
+  }
+  
+  private void printExistingDB() throws SQLException {
+    try {
+      Class.forName("org.hsqldb.jdbc.JDBCDriver");
+    }
+    catch (Exception e) {
+      System.err.println("ERROR: failed to load HSQLDB JDBC driver.");
+      e.printStackTrace();
+      return;
+    }
+
+    Connection c = DriverManager.getConnection(jdbcURL, "SA", "");
+    log.info("issuing query...");
+    ResultSet rs = c.createStatement().executeQuery("select * from events");
+    int col = rs.getMetaData().getColumnCount();
+    while (rs.next()) {
+      StringBuilder b = new StringBuilder();
+      for (int i = 1; i <= col; i++) {
+        b.append(" col:" + i + ":" + rs.getString(i));
+      }
+      log.info("Query result:" + b.toString());
+    }
+  }
+
+  @Test
+  public void testEnum() {
+    AnnotationConfiguration cfg = new AnnotationConfiguration();
+    cfg.addAnnotatedClass(Owner.class);
+    cfg.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
+    cfg.setProperty("hibernate.connection.driver_class",
+        "org.hsqldb.jdbcDriver");
+    cfg.setProperty("hibernate.connection.url", jdbcURL);
+    cfg.setProperty("hibernate.connection.username", "sa");
+    cfg.setProperty("hibernate.connection.password", "");
+    cfg.setProperty("hibernate.connection.pool_size", "1");
+    cfg.setProperty("hibernate.connection.autocommit", "true");
+    cfg.setProperty("hibernate.hbm2ddl.auto", "update");
+
+    cfg.setProperty("hibernate.cache.region.factory_class",
+        "com.gemstone.gemfire.modules.hibernate.GemFireRegionFactory");
+    cfg.setProperty("hibernate.show_sql", "true");
+    cfg.setProperty("hibernate.cache.use_query_cache", "true");
+    cfg.setProperty("gemfire.statistic-sampling-enabled", "true");
+    cfg.setProperty("gemfire.log-file", gemfireLog);
+    cfg.setProperty("gemfire.writable-working-dir", tmpDir.getPath());
+    cfg.setProperty("gemfire.mcast-port", "0");
+    //cfg.setProperty("gemfire.cache-topology", "client-server");
+
+    SessionFactory sf = cfg.buildSessionFactory();
+    Session session = sf.openSession();
+    session.beginTransaction();
+    Owner o = new Owner();
+    o.setAddress("addr");
+    o.setCity("pdx");
+    o.setStatus(Status.PREMIUM);
+    session.save(o);
+    long id = o.getId();
+    log.info("testEnum:commiting tx");
+    session.getTransaction().commit();
+    session.close();
+    
+    session = sf.openSession();
+    Owner o1 = (Owner) session.load(Owner.class, id);
+    log.info("loaded:"+o);
+    assertEquals(o.getAddress(), o1.getAddress());
+    assertEquals(o.getCity(), o1.getCity());
+    assertEquals(o.getStatus(), o1.getStatus());
+    o1.setAddress("address2");
+    session.save(o1);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Owner.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Owner.java b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Owner.java
new file mode 100644
index 0000000..92ef56f
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Owner.java
@@ -0,0 +1,186 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+import org.hibernate.annotations.Entity;
+
+
+/**
+ * Simple JavaBean domain object representing an owner.
+ * 
+ * @author Ken Krebs
+ * @author Juergen Hoeller
+ * @author Sam Brannen
+ */
+@javax.persistence.Entity
+@Entity
+public class Owner {
+	private static final long serialVersionUID = 4315791692556052565L;
+
+	@Column(name="address")
+	private String address;
+
+	private String city;
+
+	private String telephone;
+
+//	private Set<Pet> pets;
+	@Id
+	@GeneratedValue
+	private Long id;
+	
+	private long versionNum = -1;
+
+	public enum Status {
+		NORMAL, PREMIUM
+	};
+
+	@Enumerated
+	private Status status = Status.NORMAL;
+
+	  private void setId(Long id) {
+	    this.id = id;
+	  }
+
+	  public Long getId() {
+	    return id;
+	  }
+	  
+	public String getAddress() {
+		return this.address;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+	public String getCity() {
+		return this.city;
+	}
+
+	public void setCity(String city) {
+		this.city = city;
+	}
+
+	public String getTelephone() {
+		return this.telephone;
+	}
+
+	public void setTelephone(String telephone) {
+		this.telephone = telephone;
+	}
+
+	public long getVersionNum() {
+		return versionNum;
+	}
+
+	public void setVersionNum(long versionNum) {
+		this.versionNum = versionNum;
+	}
+
+	public Status getStatus() {
+		return this.status;
+	}
+
+	public void setStatus(Status state) {
+		if (state != null) {
+			this.status = state;
+		}
+	}
+
+//	protected void setPetsInternal(Set<Pet> pets) {
+//		this.pets = pets;
+//	}
+//
+//	protected Set<Pet> getPetsInternal() {
+//		if (this.pets == null) {
+//			this.pets = new HashSet<Pet>();
+//		}
+//		return this.pets;
+//	}
+//
+//	public List<Pet> getPets() {
+//		List<Pet> sortedPets = new ArrayList<Pet>(getPetsInternal());
+//		PropertyComparator.sort(sortedPets, new MutableSortDefinition("name",
+//				true, true));
+//		return Collections.unmodifiableList(sortedPets);
+//	}
+//
+//	public void addPet(Pet pet) {
+//		getPetsInternal().add(pet);
+//		pet.setOwner(this);
+//	}
+//
+//	/**
+//	 * Return the Pet with the given name, or null if none found for this Owner.
+//	 * 
+//	 * @param name
+//	 *            to test
+//	 * @return true if pet name is already in use
+//	 */
+//	public Pet getPet(String name) {
+//		return getPet(name, false);
+//	}
+//
+//	/**
+//	 * Return the Pet with the given name, or null if none found for this Owner.
+//	 * 
+//	 * @param name
+//	 *            to test
+//	 * @return true if pet name is already in use
+//	 */
+//	public Pet getPet(String name, boolean ignoreNew) {
+//		name = name.toLowerCase();
+//		for (Pet pet : getPetsInternal()) {
+//			if (!ignoreNew || !pet.isNew()) {
+//				String compName = pet.getName();
+//				compName = compName.toLowerCase();
+//				if (compName.equals(name)) {
+//					return pet;
+//				}
+//			}
+//		}
+//		return null;
+//	}
+//
+//	@Override
+//	public String toString() {
+//		return new ToStringCreator(this).append("id", this.getId())
+//				.append("new", this.isNew())
+//				.append("lastName", this.getLastName())
+//				.append("firstName", this.getFirstName())
+//				.append("address", this.address).append("city", this.city)
+//				.append("telephone", this.telephone)
+//				.append("version", this.versionNum)
+//				.append("status", this.status)
+//
+//				.toString();
+//	}
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Person.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Person.java b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Person.java
new file mode 100644
index 0000000..559363d
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/Person.java
@@ -0,0 +1,72 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class Person {
+  private Long id;
+  private int age;
+  private String firstname;
+  private String lastname;
+
+  private Set<Event> e = new HashSet<Event>();
+  
+  public Person() {}
+
+  public void setId(Long id) {
+    this.id = id;
+  }
+
+  public Long getId() {
+    return id;
+  }
+
+  public void setAge(int age) {
+    this.age = age;
+  }
+
+  public int getAge() {
+    return age;
+  }
+
+  public void setFirstname(String firstname) {
+    this.firstname = firstname;
+  }
+
+  public String getFirstname() {
+    return firstname;
+  }
+
+  public void setLastname(String lastname) {
+    this.lastname = lastname;
+  }
+
+  public String getLastname() {
+    return lastname;
+  }
+
+  public void setE(Set<Event> events) {
+    this.e = events;
+  }
+
+  public Set<Event> getE() {
+    return e;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/SecondVMTest.java
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/SecondVMTest.java b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/SecondVMTest.java
new file mode 100644
index 0000000..9459acc
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/java/com/gemstone/gemfire/modules/SecondVMTest.java
@@ -0,0 +1,88 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You 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 com.gemstone.gemfire.modules;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.logging.Level;
+
+import junit.framework.TestCase;
+
+import org.hibernate.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gemstone.gemfire.cache.Cache;
+import com.gemstone.gemfire.cache.CacheFactory;
+import com.gemstone.gemfire.cache.GemFireCache;
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.cache.Region.Entry;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+
+public class SecondVMTest extends TestCase {
+
+  private Logger log = LoggerFactory.getLogger(getClass());
+  
+  public void testNoop() {
+    
+  }
+  public void _testStartEmptyVM() throws IOException {
+    Properties gemfireProperties = new Properties();
+    gemfireProperties.setProperty("mcast-port", "5555");
+    gemfireProperties.setProperty("log-level", "fine");
+    Cache cache = new CacheFactory(gemfireProperties).create();
+    System.in.read();
+    Iterator it = cache.rootRegions().iterator();
+    while (it.hasNext()) {
+      Region r = (Region)it.next();
+      System.out.println("Region:"+r);
+      Iterator enIt = r.entrySet().iterator();
+      while (enIt.hasNext()) {
+        Region.Entry re = (Entry)enIt.next();
+        System.out.println("key:"+re.getKey()+" value:"+re.getValue());
+      }
+    }
+  }
+  
+  public void _testStartVM() throws Exception {
+    java.util.logging.Logger.getLogger("org.hibernate").setLevel(Level.ALL);
+    Session session = HibernateJUnitTest.getSessionFactory(null).openSession();
+    log.info("SWAP:new session open");
+    long id = 1;
+    log.info("loading new person:"+(id));
+    GemFireCache cache = GemFireCacheImpl.getInstance();
+    Iterator<Region<?, ?>> rSet = cache.rootRegions().iterator();
+    while (rSet.hasNext()) {
+      Region<?, ?> r = rSet.next();
+      log.info("SWAP:Region "+r);
+      Iterator<?> keySet = r.keySet().iterator();
+      while (keySet.hasNext()) {
+        log.info("key:"+keySet.next());
+      }
+    }
+    log.info("loading new person:"+(id));
+    session.beginTransaction();
+    Person p = (Person)session.load(Person.class, id);
+    p.setFirstname("SecondVMfirstname"+id);
+    log.info("loading events");
+    log.info(p.getE()+"");
+    session.getTransaction().commit();
+    //System.in.read();
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Event.hbm.xml
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Event.hbm.xml b/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Event.hbm.xml
new file mode 100644
index 0000000..3ec08c9
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Event.hbm.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+	Licensed to the Apache Software Foundation (ASF) under one or more
+	contributor license agreements.  See the NOTICE file distributed with
+	this work for additional information regarding copyright ownership.
+	The ASF licenses this file to You 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.
+-->
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="com.gemstone.gemfire.modules">
+	<class name="Event" table="EVENTS">
+		<cache usage="read-write"/>
+		<id name="id" column="EVENT_ID">
+			<generator class="native"/>
+		</id>
+		<version name="version"/>
+		<property name="date" type="timestamp" column="EVENT_DATE"/>
+        <property name="title"/>
+	</class>
+</hibernate-mapping>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Person.hbm.xml
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Person.hbm.xml b/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Person.hbm.xml
new file mode 100644
index 0000000..7c28734
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/resources/com/gemstone/gemfire/modules/Person.hbm.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+	Licensed to the Apache Software Foundation (ASF) under one or more
+	contributor license agreements.  See the NOTICE file distributed with
+	this work for additional information regarding copyright ownership.
+	The ASF licenses this file to You 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.
+-->
+<!DOCTYPE hibernate-mapping PUBLIC
+        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="com.gemstone.gemfire.modules">
+    <class name="Person" table="PERSON">
+        <cache usage="read-write"/>
+        <id name="id" column="PERSON_ID">
+        </id>
+        <property name="age"/>
+        <property name="firstname"/>
+        <property name="lastname"/>
+        <set name="e" table="PERSON_EVENT">
+          <cache usage="read-write"/>
+          <key column="PERSON_ID"/>
+          <many-to-many column="EVENT_ID" class="Event"/>
+        </set>
+    </class>
+</hibernate-mapping>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-hibernate/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-hibernate/src/test/resources/log4j.properties b/extensions/gemfire-modules-hibernate/src/test/resources/log4j.properties
new file mode 100644
index 0000000..c136990
--- /dev/null
+++ b/extensions/gemfire-modules-hibernate/src/test/resources/log4j.properties
@@ -0,0 +1,16 @@
+# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
+# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
+#log4j.rootLogger=DEBUG, stdout, logfile
+log4j.rootLogger=DEBUG, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
+
+#log4j.appender.logfile=org.apache.log4j.RollingFileAppender
+#log4j.appender.logfile.MaxFileSize=512KB
+## Keep three backup files.
+#log4j.appender.logfile.MaxBackupIndex=3
+## Pattern to output: date priority [category] - message
+#log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
+#log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/48552465/extensions/gemfire-modules-session/build.gradle
----------------------------------------------------------------------
diff --git a/extensions/gemfire-modules-session/build.gradle b/extensions/gemfire-modules-session/build.gradle
new file mode 100644
index 0000000..71d59dc
--- /dev/null
+++ b/extensions/gemfire-modules-session/build.gradle
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+dependencies {
+  compile project(':extensions/gemfire-modules')
+  compile project(':gemfire-core')
+
+  testCompile 'javax.servlet:javax.servlet-api:3.1.0'
+  testCompile 'org.slf4j:slf4j-jdk14:1.7.7'
+  testCompile('com.mockrunner:mockrunner-servlet:1.0.8') {
+    exclude group: 'jboss'
+  }
+  testCompile(group: 'org.eclipse.jetty', name: 'jetty-http', version: project.'jetty.version', classifier: 'tests')
+  testCompile(group: 'org.eclipse.jetty', name: 'jetty-servlet', version: project.'jetty.version', classifier: 'tests')
+
+  provided project(path: ':gemfire-junit', configuration: 'testOutput')
+}
+
+jar {
+  include '**/session/filter/**/*'
+  include '**/session/installer/**/*'
+  includeEmptyDirs = false
+  baseName = 'gemfire-modules-session-external'
+
+  manifest {
+    attributes 'Main-Class': 'com.gemstone.gemfire.modules.session.installer.Installer'
+  }
+}
+
+task internalJar(type: Jar) {
+  from sourceSets.main.output
+  include '**/internal/**/*'
+  includeEmptyDirs = false
+  baseName = 'gemfire-modules-session'
+}
+
+assemble.dependsOn(internalJar)