From f947a76fcefd2aa57c1f1f7ae6f29a4b2355e49c Mon Sep 17 00:00:00 2001 From: rbygrave Date: Sat, 9 May 2015 01:11:56 +1200 Subject: [PATCH] No effective change - change newline char --- .../server/transaction/BeanDelta.java | 206 +++---- .../server/transaction/BeanDeltaList.java | 84 +-- .../server/transaction/BeanDeltaMap.java | 96 +-- .../server/transaction/BeanDeltaProperty.java | 72 +-- .../server/transaction/BeanPathUpdate.java | 48 +- .../server/transaction/BeanPathUpdateIds.java | 288 ++++----- .../server/transaction/BeanPersistIdMap.java | 100 +-- .../server/transaction/BeanPersistIds.java | 576 +++++++++--------- .../DefaultPersistenceContext.java | 420 ++++++------- .../DefaultTransactionThreadLocal.java | 256 ++++---- .../server/transaction/DeleteByIdMap.java | 152 ++--- .../ExternalTransactionScopeManager.java | 96 +-- .../server/transaction/JtaTransaction.java | 234 +++---- .../transaction/JtaTransactionManager.java | 458 +++++++------- .../transaction/PostCommitProcessing.java | 326 +++++----- .../transaction/RemoteTransactionEvent.java | 282 ++++----- .../server/transaction/TransactionMap.java | 236 +++---- 17 files changed, 1965 insertions(+), 1965 deletions(-) diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDelta.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDelta.java index c5ee4b37c..320b0620b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDelta.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDelta.java @@ -1,103 +1,103 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.DataInput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.avaje.ebean.bean.EntityBean; -import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.server.cluster.BinaryMessage; -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.deploy.BeanProperty; - -public class BeanDelta { - - private final List properties; - - private final BeanDescriptor beanDescriptor; - - private final Object id; - - public BeanDelta(BeanDescriptor beanDescriptor, Object id) { - this.beanDescriptor = beanDescriptor; - this.id = id; - this.properties = new ArrayList(); - } - - public BeanDescriptor getBeanDescriptor() { - return beanDescriptor; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("BeanDelta["); - sb.append(beanDescriptor.getName()).append(":"); - sb.append(properties); - sb.append("]"); - return sb.toString(); - } - - public Object getId() { - return id; - } - - public void add(BeanProperty beanProperty, Object value) { - this.properties.add(new BeanDeltaProperty(beanProperty, value)); - } - - public void add(BeanDeltaProperty propertyDelta) { - this.properties.add(propertyDelta); - } - - public void apply(EntityBean bean) { - - for (int i = 0; i < properties.size(); i++) { - properties.get(i).apply(bean); - } - } - - /** - * Read and return a BeanDelta from the binary input. - */ - public static BeanDelta readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException { - - String descriptorId = dataInput.readUTF(); - BeanDescriptor desc = server.getBeanDescriptorById(descriptorId); - Object id = desc.getIdBinder().readData(dataInput); - BeanDelta bp = new BeanDelta(desc, id); - - int count = dataInput.readInt(); - for (int i = 0; i < count; i++) { - String propName = dataInput.readUTF(); - BeanProperty beanProperty = desc.getBeanProperty(propName); - Object value = beanProperty.getScalarType().readData(dataInput); - bp.add(beanProperty, value); - } - return bp; - } - - /** - * Write this bean delta in binary message format. - */ - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - - BinaryMessage m = new BinaryMessage(50); - - DataOutputStream os = m.getOs(); - os.writeInt(BinaryMessage.TYPE_BEANDELTA); - os.writeUTF(beanDescriptor.getDescriptorId()); - - beanDescriptor.getIdBinder().writeData(os, id); - os.writeInt(properties.size()); - - for (int i = 0; i < properties.size(); i++) { - properties.get(i).writeBinaryMessage(m); - } - - os.flush(); - msgList.add(m); - } -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebeaninternal.api.SpiEbeanServer; +import com.avaje.ebeaninternal.server.cluster.BinaryMessage; +import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.ebeaninternal.server.deploy.BeanProperty; + +public class BeanDelta { + + private final List properties; + + private final BeanDescriptor beanDescriptor; + + private final Object id; + + public BeanDelta(BeanDescriptor beanDescriptor, Object id) { + this.beanDescriptor = beanDescriptor; + this.id = id; + this.properties = new ArrayList(); + } + + public BeanDescriptor getBeanDescriptor() { + return beanDescriptor; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("BeanDelta["); + sb.append(beanDescriptor.getName()).append(":"); + sb.append(properties); + sb.append("]"); + return sb.toString(); + } + + public Object getId() { + return id; + } + + public void add(BeanProperty beanProperty, Object value) { + this.properties.add(new BeanDeltaProperty(beanProperty, value)); + } + + public void add(BeanDeltaProperty propertyDelta) { + this.properties.add(propertyDelta); + } + + public void apply(EntityBean bean) { + + for (int i = 0; i < properties.size(); i++) { + properties.get(i).apply(bean); + } + } + + /** + * Read and return a BeanDelta from the binary input. + */ + public static BeanDelta readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException { + + String descriptorId = dataInput.readUTF(); + BeanDescriptor desc = server.getBeanDescriptorById(descriptorId); + Object id = desc.getIdBinder().readData(dataInput); + BeanDelta bp = new BeanDelta(desc, id); + + int count = dataInput.readInt(); + for (int i = 0; i < count; i++) { + String propName = dataInput.readUTF(); + BeanProperty beanProperty = desc.getBeanProperty(propName); + Object value = beanProperty.getScalarType().readData(dataInput); + bp.add(beanProperty, value); + } + return bp; + } + + /** + * Write this bean delta in binary message format. + */ + public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { + + BinaryMessage m = new BinaryMessage(50); + + DataOutputStream os = m.getOs(); + os.writeInt(BinaryMessage.TYPE_BEANDELTA); + os.writeUTF(beanDescriptor.getDescriptorId()); + + beanDescriptor.getIdBinder().writeData(os, id); + os.writeInt(properties.size()); + + for (int i = 0; i < properties.size(); i++) { + properties.get(i).writeBinaryMessage(m); + } + + os.flush(); + msgList.add(m); + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaList.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaList.java index 1cdbb7f52..6b6dccca7 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaList.java @@ -1,42 +1,42 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; - -public class BeanDeltaList { - - private final BeanDescriptor beanDescriptor; - - private final List deltaBeans = new ArrayList(); - - public BeanDeltaList(BeanDescriptor beanDescriptor) { - this.beanDescriptor = beanDescriptor; - } - - public String toString() { - return deltaBeans.toString(); - } - - public BeanDescriptor getBeanDescriptor() { - return beanDescriptor; - } - - public void add(BeanDelta b) { - deltaBeans.add(b); - } - - public List getDeltaBeans() { - return deltaBeans; - } - - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - for (int i = 0; i < deltaBeans.size(); i++) { - deltaBeans.get(i).writeBinaryMessage(msgList); - } - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; + +public class BeanDeltaList { + + private final BeanDescriptor beanDescriptor; + + private final List deltaBeans = new ArrayList(); + + public BeanDeltaList(BeanDescriptor beanDescriptor) { + this.beanDescriptor = beanDescriptor; + } + + public String toString() { + return deltaBeans.toString(); + } + + public BeanDescriptor getBeanDescriptor() { + return beanDescriptor; + } + + public void add(BeanDelta b) { + deltaBeans.add(b); + } + + public List getDeltaBeans() { + return deltaBeans; + } + + public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { + for (int i = 0; i < deltaBeans.size(); i++) { + deltaBeans.get(i).writeBinaryMessage(msgList); + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaMap.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaMap.java index 444d84dd1..0987c2cf6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaMap.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaMap.java @@ -1,48 +1,48 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; - -public class BeanDeltaMap { - - private Map deltaMap = new HashMap(); - - public BeanDeltaMap() { - } - - public BeanDeltaMap(List deltaBeans) { - if (deltaBeans != null){ - for (int i = 0; i < deltaBeans.size(); i++) { - BeanDelta deltaBean = deltaBeans.get(i); - addBeanDelta(deltaBean); - } - } - } - - public String toString() { - return deltaMap.values().toString(); - } - - public void addBeanDelta(BeanDelta beanDelta){ - BeanDescriptor d = beanDelta.getBeanDescriptor(); - BeanDeltaList list = getDeltaBeanList(d); - list.add(beanDelta); - } - - public Collection deltaLists() { - return deltaMap.values(); - } - - private BeanDeltaList getDeltaBeanList(BeanDescriptor d) { - BeanDeltaList deltaList = deltaMap.get(d.getFullName()); - if (deltaList == null){ - deltaList = new BeanDeltaList(d); - deltaMap.put(d.getFullName(), deltaList); - } - return deltaList; - } -} +package com.avaje.ebeaninternal.server.transaction; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; + +public class BeanDeltaMap { + + private Map deltaMap = new HashMap(); + + public BeanDeltaMap() { + } + + public BeanDeltaMap(List deltaBeans) { + if (deltaBeans != null){ + for (int i = 0; i < deltaBeans.size(); i++) { + BeanDelta deltaBean = deltaBeans.get(i); + addBeanDelta(deltaBean); + } + } + } + + public String toString() { + return deltaMap.values().toString(); + } + + public void addBeanDelta(BeanDelta beanDelta){ + BeanDescriptor d = beanDelta.getBeanDescriptor(); + BeanDeltaList list = getDeltaBeanList(d); + list.add(beanDelta); + } + + public Collection deltaLists() { + return deltaMap.values(); + } + + private BeanDeltaList getDeltaBeanList(BeanDescriptor d) { + BeanDeltaList deltaList = deltaMap.get(d.getFullName()); + if (deltaList == null){ + deltaList = new BeanDeltaList(d); + deltaMap.put(d.getFullName(), deltaList); + } + return deltaList; + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaProperty.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaProperty.java index 316c33f1a..2085af801 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaProperty.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanDeltaProperty.java @@ -1,36 +1,36 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.DataOutputStream; -import java.io.IOException; - -import com.avaje.ebean.bean.EntityBean; -import com.avaje.ebeaninternal.server.cluster.BinaryMessage; -import com.avaje.ebeaninternal.server.deploy.BeanProperty; - -public class BeanDeltaProperty { - - private final BeanProperty beanProperty; - - private final Object value; - - public BeanDeltaProperty(BeanProperty beanProperty, Object value) { - this.beanProperty = beanProperty; - this.value = value; - } - - public String toString() { - return beanProperty.getName()+":"+value; - } - - public void apply(EntityBean bean) { - beanProperty.setValue(bean, value); - } - - public void writeBinaryMessage(BinaryMessage m) throws IOException { - - DataOutputStream os = m.getOs(); - os.writeUTF(beanProperty.getName()); - beanProperty.getScalarType().writeData(os, value); - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.DataOutputStream; +import java.io.IOException; + +import com.avaje.ebean.bean.EntityBean; +import com.avaje.ebeaninternal.server.cluster.BinaryMessage; +import com.avaje.ebeaninternal.server.deploy.BeanProperty; + +public class BeanDeltaProperty { + + private final BeanProperty beanProperty; + + private final Object value; + + public BeanDeltaProperty(BeanProperty beanProperty, Object value) { + this.beanProperty = beanProperty; + this.value = value; + } + + public String toString() { + return beanProperty.getName()+":"+value; + } + + public void apply(EntityBean bean) { + beanProperty.setValue(bean, value); + } + + public void writeBinaryMessage(BinaryMessage m) throws IOException { + + DataOutputStream os = m.getOs(); + os.writeUTF(beanProperty.getName()); + beanProperty.getScalarType().writeData(os, value); + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdate.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdate.java index 922e048b1..519ddb8ed 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdate.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdate.java @@ -1,24 +1,24 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.Serializable; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; - -public class BeanPathUpdate { - - private final Map map = new LinkedHashMap(); - - public void add(BeanDescriptor desc, String path, Object id) { - - String key = desc.getFullName()+":"+path; - BeanPathUpdateIds pathIds = map.get(key); - if (pathIds == null){ - pathIds = new BeanPathUpdateIds(desc, path); - map.put(key, pathIds); - } - pathIds.addId((Serializable)id); - - } -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.Serializable; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; + +public class BeanPathUpdate { + + private final Map map = new LinkedHashMap(); + + public void add(BeanDescriptor desc, String path, Object id) { + + String key = desc.getFullName()+":"+path; + BeanPathUpdateIds pathIds = map.get(key); + if (pathIds == null){ + pathIds = new BeanPathUpdateIds(desc, path); + map.put(key, pathIds); + } + pathIds.addId((Serializable)id); + + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdateIds.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdateIds.java index 59f2176e0..1f861162c 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdateIds.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPathUpdateIds.java @@ -1,144 +1,144 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.DataInput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.server.cluster.BinaryMessage; -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.deploy.id.IdBinder; - -public class BeanPathUpdateIds { - - private transient BeanDescriptor beanDescriptor; - - private final String descriptorId; - - private String path; - - private ArrayList ids; - - /** - * Create the payload. - */ - public BeanPathUpdateIds(BeanDescriptor desc, String path) { - this.beanDescriptor = desc; - this.descriptorId = desc.getDescriptorId(); - this.path = path; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - if (beanDescriptor != null) { - sb.append(beanDescriptor.getFullName()); - } else { - sb.append("descId:").append(descriptorId); - } - sb.append(" path:").append(path); - sb.append(" ids:").append(ids); - return sb.toString(); - } - - public static BeanPathUpdateIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException { - - String descriptorId = dataInput.readUTF(); - String path = dataInput.readUTF(); - BeanDescriptor desc = server.getBeanDescriptorById(descriptorId); - BeanPathUpdateIds bp = new BeanPathUpdateIds(desc, path); - bp.read(dataInput); - return bp; - } - - private void read(DataInput dataInput) throws IOException { - - IdBinder idBinder = beanDescriptor.getIdBinder(); - ids = readIdList(dataInput, idBinder); - } - - - private ArrayList readIdList(DataInput dataInput, IdBinder idBinder) throws IOException { - - int count = dataInput.readInt(); - if (count < 1) { - return null; - } - ArrayList idList = new ArrayList(count); - for (int i = 0; i < count; i++) { - Object id = idBinder.readData(dataInput); - idList.add((Serializable) id); - } - return idList; - } - - /** - * Write the contents into a BinaryMessage form. - *

- * For a RemoteBeanPersist with a large number of id's note that this is - * broken up into many BinaryMessages each with a maximum of 100 ids. This - * enables the contents of a large RemoteTransactionEvent to be split up - * across multiple Packets. - *

- */ - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - - IdBinder idBinder = beanDescriptor.getIdBinder(); - - int count = ids == null ? 0 : ids.size(); - if (count > 0) { - int loop = 0; - int i = 0; - int eof = ids.size(); - do { - ++loop; - int endOfLoop = Math.min(eof, loop * 100); - - BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20); - - DataOutputStream os = m.getOs(); - os.writeInt(BinaryMessage.TYPE_BEANPATHUPDATE); - os.writeUTF(descriptorId); - os.writeUTF(path); - os.writeInt(count); - - for (; i < endOfLoop; i++) { - Serializable idValue = ids.get(i); - idBinder.writeData(os, idValue); - } - - os.flush(); - msgList.add(m); - - } while (i < eof); - } - } - - public void addId(Serializable id) { - ids.add(id); - } - - - public BeanDescriptor getBeanDescriptor() { - return beanDescriptor; - } - - /** - * Return the Descriptor Id. A more compact alternative to using the - * beanType. - */ - public String getDescriptorId() { - return descriptorId; - } - - public String getPath() { - return path; - } - - public List getIds() { - return ids; - } -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import com.avaje.ebeaninternal.api.SpiEbeanServer; +import com.avaje.ebeaninternal.server.cluster.BinaryMessage; +import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.ebeaninternal.server.deploy.id.IdBinder; + +public class BeanPathUpdateIds { + + private transient BeanDescriptor beanDescriptor; + + private final String descriptorId; + + private String path; + + private ArrayList ids; + + /** + * Create the payload. + */ + public BeanPathUpdateIds(BeanDescriptor desc, String path) { + this.beanDescriptor = desc; + this.descriptorId = desc.getDescriptorId(); + this.path = path; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + if (beanDescriptor != null) { + sb.append(beanDescriptor.getFullName()); + } else { + sb.append("descId:").append(descriptorId); + } + sb.append(" path:").append(path); + sb.append(" ids:").append(ids); + return sb.toString(); + } + + public static BeanPathUpdateIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException { + + String descriptorId = dataInput.readUTF(); + String path = dataInput.readUTF(); + BeanDescriptor desc = server.getBeanDescriptorById(descriptorId); + BeanPathUpdateIds bp = new BeanPathUpdateIds(desc, path); + bp.read(dataInput); + return bp; + } + + private void read(DataInput dataInput) throws IOException { + + IdBinder idBinder = beanDescriptor.getIdBinder(); + ids = readIdList(dataInput, idBinder); + } + + + private ArrayList readIdList(DataInput dataInput, IdBinder idBinder) throws IOException { + + int count = dataInput.readInt(); + if (count < 1) { + return null; + } + ArrayList idList = new ArrayList(count); + for (int i = 0; i < count; i++) { + Object id = idBinder.readData(dataInput); + idList.add((Serializable) id); + } + return idList; + } + + /** + * Write the contents into a BinaryMessage form. + *

+ * For a RemoteBeanPersist with a large number of id's note that this is + * broken up into many BinaryMessages each with a maximum of 100 ids. This + * enables the contents of a large RemoteTransactionEvent to be split up + * across multiple Packets. + *

+ */ + public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { + + IdBinder idBinder = beanDescriptor.getIdBinder(); + + int count = ids == null ? 0 : ids.size(); + if (count > 0) { + int loop = 0; + int i = 0; + int eof = ids.size(); + do { + ++loop; + int endOfLoop = Math.min(eof, loop * 100); + + BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20); + + DataOutputStream os = m.getOs(); + os.writeInt(BinaryMessage.TYPE_BEANPATHUPDATE); + os.writeUTF(descriptorId); + os.writeUTF(path); + os.writeInt(count); + + for (; i < endOfLoop; i++) { + Serializable idValue = ids.get(i); + idBinder.writeData(os, idValue); + } + + os.flush(); + msgList.add(m); + + } while (i < eof); + } + } + + public void addId(Serializable id) { + ids.add(id); + } + + + public BeanDescriptor getBeanDescriptor() { + return beanDescriptor; + } + + /** + * Return the Descriptor Id. A more compact alternative to using the + * beanType. + */ + public String getDescriptorId() { + return descriptorId; + } + + public String getPath() { + return path; + } + + public List getIds() { + return ids; + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIdMap.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIdMap.java index 0f295bdad..b92ed0e6d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIdMap.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIdMap.java @@ -1,50 +1,50 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.Serializable; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; - -import com.avaje.ebeaninternal.server.core.PersistRequest; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; - -/** - * Organises the individual bean persist requests by type. - */ -public final class BeanPersistIdMap { - - private final Map beanMap = new LinkedHashMap(); - - public String toString() { - return beanMap.toString(); - } - - public boolean isEmpty() { - return beanMap.isEmpty(); - } - - public Collection values() { - return beanMap.values(); - } - - /** - * Add a Insert Update or Delete payload. - */ - public void add(BeanDescriptor desc, PersistRequest.Type type, Object id) { - - BeanPersistIds r = getPersistIds(desc); - r.addId(type, (Serializable)id); - } - - private BeanPersistIds getPersistIds(BeanDescriptor desc) { - String beanType = desc.getFullName(); - BeanPersistIds r = beanMap.get(beanType); - if (r == null){ - r = new BeanPersistIds(desc); - beanMap.put(beanType, r); - } - return r; - } - - -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.Serializable; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.avaje.ebeaninternal.server.core.PersistRequest; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; + +/** + * Organises the individual bean persist requests by type. + */ +public final class BeanPersistIdMap { + + private final Map beanMap = new LinkedHashMap(); + + public String toString() { + return beanMap.toString(); + } + + public boolean isEmpty() { + return beanMap.isEmpty(); + } + + public Collection values() { + return beanMap.values(); + } + + /** + * Add a Insert Update or Delete payload. + */ + public void add(BeanDescriptor desc, PersistRequest.Type type, Object id) { + + BeanPersistIds r = getPersistIds(desc); + r.addId(type, (Serializable)id); + } + + private BeanPersistIds getPersistIds(BeanDescriptor desc) { + String beanType = desc.getFullName(); + BeanPersistIds r = beanMap.get(beanType); + if (r == null){ + r = new BeanPersistIds(desc); + beanMap.put(beanType, r); + } + return r; + } + + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIds.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIds.java index 57626e88c..d4d242cb4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIds.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/BeanPersistIds.java @@ -1,288 +1,288 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.DataInput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import com.avaje.ebean.event.BeanPersistListener; -import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.server.cluster.BinaryMessage; -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; -import com.avaje.ebeaninternal.server.core.PersistRequest; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.deploy.id.IdBinder; - -/** - * Wraps the information representing a Inserted Updated or Deleted Bean. - *

- * This information is broadcast across the cluster so that remote BeanListeners - * are notified of the inserts updates and deletes that occured. - *

- *

- * You control it the data is broadcast and what data is broadcast by the - * BeanListener.getClusterData() method. It is guessed that often just the Id - * property or perhaps a few properties in a Map will be broadcast to reduce the - * size of data sent around the network. - *

- */ -public class BeanPersistIds implements Serializable { - - private static final long serialVersionUID = 8389469180931531409L; - - private transient BeanDescriptor beanDescriptor; - - private final String descriptorId; - - private ArrayList insertIds; - private ArrayList updateIds; - private ArrayList deleteIds; - - /** - * Create the payload. - */ - public BeanPersistIds(BeanDescriptor desc) { - this.beanDescriptor = desc; - this.descriptorId = desc.getDescriptorId(); - } - - public static BeanPersistIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException { - - String descriptorId = dataInput.readUTF(); - BeanDescriptor desc = server.getBeanDescriptorById(descriptorId); - BeanPersistIds bp = new BeanPersistIds(desc); - bp.read(dataInput); - return bp; - } - - private void read(DataInput dataInput) throws IOException { - - IdBinder idBinder = beanDescriptor.getIdBinder(); - - int iudType = dataInput.readInt(); - ArrayList idList = readIdList(dataInput, idBinder); - - switch (iudType) { - case 0: - insertIds = idList; - break; - case 1: - updateIds = idList; - break; - case 2: - deleteIds = idList; - break; - - default: - throw new RuntimeException("Invalid iudType "+iudType); - } - } - - /** - * Write the contents into a BinaryMessage form. - *

- * For a RemoteBeanPersist with a large number of id's note that this is - * broken up into many BinaryMessages each with a maximum of 100 ids. This - * enables the contents of a large RemoteTransactionEvent to be split up - * across multiple Packets. - *

- */ - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - - writeIdList(beanDescriptor, 0, insertIds, msgList); - writeIdList(beanDescriptor, 1, updateIds, msgList); - writeIdList(beanDescriptor, 2, deleteIds, msgList); - - } - - private ArrayList readIdList(DataInput dataInput, IdBinder idBinder) throws IOException { - - int count = dataInput.readInt(); - if (count < 1) { - return null; - } - ArrayList idList = new ArrayList(count); - for (int i = 0; i < count; i++) { - Object id = idBinder.readData(dataInput); - idList.add((Serializable) id); - } - return idList; - } - - /** - * Write a BinaryMessage containing the descriptorId, iudType and list of Id - * values. - *

- * Note that a given BinaryMessage has a maximum of 100 Ids. This is due to - * the limit of UDP packet sizes. We break up the RemoteBeanPersist into - * potentially many smaller BinaryMessages which may be put into multiple - * Packets. - *

- */ - private void writeIdList(BeanDescriptor desc, int iudType, ArrayList idList, - BinaryMessageList msgList) throws IOException { - - IdBinder idBinder = desc.getIdBinder(); - - int count = idList == null ? 0 : idList.size(); - if (count > 0) { - int loop = 0; - int i = 0; - int eof = idList.size(); - do { - ++loop; - int endOfLoop = Math.min(eof, loop * 100); - - BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20); - - DataOutputStream os = m.getOs(); - os.writeInt(BinaryMessage.TYPE_BEANIUD); - os.writeUTF(descriptorId); - os.writeInt(iudType); - os.writeInt(count); - - for (; i < endOfLoop; i++) { - Serializable idValue = idList.get(i); - idBinder.writeData(os, idValue); - } - - os.flush(); - msgList.add(m); - - } while (i < eof); - } - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - if (beanDescriptor != null) { - sb.append(beanDescriptor.getFullName()); - } else { - sb.append("descId:").append(descriptorId); - } - if (insertIds != null) { - sb.append(" insertIds:").append(insertIds); - } - if (updateIds != null) { - sb.append(" updateIds:").append(updateIds); - } - if (deleteIds != null) { - sb.append(" deleteIds:").append(deleteIds); - } - return sb.toString(); - } - - public void addId(PersistRequest.Type type, Serializable id) { - switch (type) { - case INSERT: - addInsertId(id); - break; - case UPDATE: - addUpdateId(id); - break; - case DELETE: - addDeleteId(id); - break; - - default: - break; - } - } - - private void addInsertId(Serializable id) { - if (insertIds == null) { - insertIds = new ArrayList(); - } - insertIds.add(id); - } - - private void addUpdateId(Serializable id) { - if (updateIds == null) { - updateIds = new ArrayList(); - } - updateIds.add(id); - } - - private void addDeleteId(Serializable id) { - if (deleteIds == null) { - deleteIds = new ArrayList(); - } - deleteIds.add(id); - } - - public BeanDescriptor getBeanDescriptor() { - return beanDescriptor; - } - - /** - * Return the Descriptor Id. A more compact alternative to using the - * beanType. - */ - public String getDescriptorId() { - return descriptorId; - } - - public List getInsertIds() { - return insertIds; - } - - public List getUpdateIds() { - return updateIds; - } - - public List getDeleteIds() { - return deleteIds; - } - - public void setBeanDescriptor(BeanDescriptor beanDescriptor) { - this.beanDescriptor = beanDescriptor; - } - - /** - * Notify the cache and local BeanPersistListener of this event that came - * from another server in the cluster. - */ - public void notifyCacheAndListener() { - - BeanPersistListener listener = beanDescriptor.getPersistListener(); - - // any change invalidates the query cache - beanDescriptor.queryCacheClear(); - - if (insertIds != null) { - if (listener != null) { - // notify listener - for (int i = 0; i < insertIds.size(); i++) { - listener.remoteInsert(insertIds.get(i)); - } - } - } - if (updateIds != null) { - for (int i = 0; i < updateIds.size(); i++) { - Serializable id = updateIds.get(i); - - // remove from cache - beanDescriptor.cacheBeanRemove(id); - if (listener != null) { - // notify listener - listener.remoteInsert(id); - } - } - } - if (deleteIds != null) { - for (int i = 0; i < deleteIds.size(); i++) { - Serializable id = deleteIds.get(i); - - // remove from cache - beanDescriptor.cacheBeanRemove(id); - if (listener != null) { - // notify listener - listener.remoteInsert(id); - } - } - } - - } -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import com.avaje.ebean.event.BeanPersistListener; +import com.avaje.ebeaninternal.api.SpiEbeanServer; +import com.avaje.ebeaninternal.server.cluster.BinaryMessage; +import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; +import com.avaje.ebeaninternal.server.core.PersistRequest; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.ebeaninternal.server.deploy.id.IdBinder; + +/** + * Wraps the information representing a Inserted Updated or Deleted Bean. + *

+ * This information is broadcast across the cluster so that remote BeanListeners + * are notified of the inserts updates and deletes that occured. + *

+ *

+ * You control it the data is broadcast and what data is broadcast by the + * BeanListener.getClusterData() method. It is guessed that often just the Id + * property or perhaps a few properties in a Map will be broadcast to reduce the + * size of data sent around the network. + *

+ */ +public class BeanPersistIds implements Serializable { + + private static final long serialVersionUID = 8389469180931531409L; + + private transient BeanDescriptor beanDescriptor; + + private final String descriptorId; + + private ArrayList insertIds; + private ArrayList updateIds; + private ArrayList deleteIds; + + /** + * Create the payload. + */ + public BeanPersistIds(BeanDescriptor desc) { + this.beanDescriptor = desc; + this.descriptorId = desc.getDescriptorId(); + } + + public static BeanPersistIds readBinaryMessage(SpiEbeanServer server, DataInput dataInput) throws IOException { + + String descriptorId = dataInput.readUTF(); + BeanDescriptor desc = server.getBeanDescriptorById(descriptorId); + BeanPersistIds bp = new BeanPersistIds(desc); + bp.read(dataInput); + return bp; + } + + private void read(DataInput dataInput) throws IOException { + + IdBinder idBinder = beanDescriptor.getIdBinder(); + + int iudType = dataInput.readInt(); + ArrayList idList = readIdList(dataInput, idBinder); + + switch (iudType) { + case 0: + insertIds = idList; + break; + case 1: + updateIds = idList; + break; + case 2: + deleteIds = idList; + break; + + default: + throw new RuntimeException("Invalid iudType "+iudType); + } + } + + /** + * Write the contents into a BinaryMessage form. + *

+ * For a RemoteBeanPersist with a large number of id's note that this is + * broken up into many BinaryMessages each with a maximum of 100 ids. This + * enables the contents of a large RemoteTransactionEvent to be split up + * across multiple Packets. + *

+ */ + public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { + + writeIdList(beanDescriptor, 0, insertIds, msgList); + writeIdList(beanDescriptor, 1, updateIds, msgList); + writeIdList(beanDescriptor, 2, deleteIds, msgList); + + } + + private ArrayList readIdList(DataInput dataInput, IdBinder idBinder) throws IOException { + + int count = dataInput.readInt(); + if (count < 1) { + return null; + } + ArrayList idList = new ArrayList(count); + for (int i = 0; i < count; i++) { + Object id = idBinder.readData(dataInput); + idList.add((Serializable) id); + } + return idList; + } + + /** + * Write a BinaryMessage containing the descriptorId, iudType and list of Id + * values. + *

+ * Note that a given BinaryMessage has a maximum of 100 Ids. This is due to + * the limit of UDP packet sizes. We break up the RemoteBeanPersist into + * potentially many smaller BinaryMessages which may be put into multiple + * Packets. + *

+ */ + private void writeIdList(BeanDescriptor desc, int iudType, ArrayList idList, + BinaryMessageList msgList) throws IOException { + + IdBinder idBinder = desc.getIdBinder(); + + int count = idList == null ? 0 : idList.size(); + if (count > 0) { + int loop = 0; + int i = 0; + int eof = idList.size(); + do { + ++loop; + int endOfLoop = Math.min(eof, loop * 100); + + BinaryMessage m = new BinaryMessage(endOfLoop * 4 + 20); + + DataOutputStream os = m.getOs(); + os.writeInt(BinaryMessage.TYPE_BEANIUD); + os.writeUTF(descriptorId); + os.writeInt(iudType); + os.writeInt(count); + + for (; i < endOfLoop; i++) { + Serializable idValue = idList.get(i); + idBinder.writeData(os, idValue); + } + + os.flush(); + msgList.add(m); + + } while (i < eof); + } + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + if (beanDescriptor != null) { + sb.append(beanDescriptor.getFullName()); + } else { + sb.append("descId:").append(descriptorId); + } + if (insertIds != null) { + sb.append(" insertIds:").append(insertIds); + } + if (updateIds != null) { + sb.append(" updateIds:").append(updateIds); + } + if (deleteIds != null) { + sb.append(" deleteIds:").append(deleteIds); + } + return sb.toString(); + } + + public void addId(PersistRequest.Type type, Serializable id) { + switch (type) { + case INSERT: + addInsertId(id); + break; + case UPDATE: + addUpdateId(id); + break; + case DELETE: + addDeleteId(id); + break; + + default: + break; + } + } + + private void addInsertId(Serializable id) { + if (insertIds == null) { + insertIds = new ArrayList(); + } + insertIds.add(id); + } + + private void addUpdateId(Serializable id) { + if (updateIds == null) { + updateIds = new ArrayList(); + } + updateIds.add(id); + } + + private void addDeleteId(Serializable id) { + if (deleteIds == null) { + deleteIds = new ArrayList(); + } + deleteIds.add(id); + } + + public BeanDescriptor getBeanDescriptor() { + return beanDescriptor; + } + + /** + * Return the Descriptor Id. A more compact alternative to using the + * beanType. + */ + public String getDescriptorId() { + return descriptorId; + } + + public List getInsertIds() { + return insertIds; + } + + public List getUpdateIds() { + return updateIds; + } + + public List getDeleteIds() { + return deleteIds; + } + + public void setBeanDescriptor(BeanDescriptor beanDescriptor) { + this.beanDescriptor = beanDescriptor; + } + + /** + * Notify the cache and local BeanPersistListener of this event that came + * from another server in the cluster. + */ + public void notifyCacheAndListener() { + + BeanPersistListener listener = beanDescriptor.getPersistListener(); + + // any change invalidates the query cache + beanDescriptor.queryCacheClear(); + + if (insertIds != null) { + if (listener != null) { + // notify listener + for (int i = 0; i < insertIds.size(); i++) { + listener.remoteInsert(insertIds.get(i)); + } + } + } + if (updateIds != null) { + for (int i = 0; i < updateIds.size(); i++) { + Serializable id = updateIds.get(i); + + // remove from cache + beanDescriptor.cacheBeanRemove(id); + if (listener != null) { + // notify listener + listener.remoteInsert(id); + } + } + } + if (deleteIds != null) { + for (int i = 0; i < deleteIds.size(); i++) { + Serializable id = deleteIds.get(i); + + // remove from cache + beanDescriptor.cacheBeanRemove(id); + if (listener != null) { + // notify listener + listener.remoteInsert(id); + } + } + } + + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java index f6e7bb320..1112084ed 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultPersistenceContext.java @@ -1,210 +1,210 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import javax.persistence.Entity; - -import com.avaje.ebean.bean.PersistenceContext; -import com.avaje.ebeaninternal.api.Monitor; - -/** - * Default implementation of PersistenceContext. - *

- * Ensures only one instance of a bean is used according to its type and unique - * id. - *

- *

- * PersistenceContext lives on a Transaction and as such is expected to only - * have a single thread accessing it at a time. This is not expected to be used - * concurrently. - *

- *

- * Duplicate beans are ones having the same type and unique id value. These are - * considered duplicates and replaced by the bean instance that was already - * loaded into the PersistanceContext. - *

- */ -public final class DefaultPersistenceContext implements PersistenceContext { - - /** - * Map used hold caches. One cache per bean type. - */ - private final HashMap typeCache = new HashMap(); - - private final Monitor monitor = new Monitor(); - - /** - * Create a new PersistanceContext. - */ - public DefaultPersistenceContext() { - } - - /** - * Set an object into the PersistanceContext. - */ - public void put(Object id, Object bean) { - synchronized (monitor) { - getClassContext(bean.getClass()).put(id, bean); - } - } - - public Object putIfAbsent(Object id, Object bean) { - synchronized (monitor) { - return getClassContext(bean.getClass()).putIfAbsent(id, bean); - } - } - - /** - * Return an object given its type and unique id. - */ - public Object get(Class beanType, Object id) { - synchronized (monitor) { - return getClassContext(beanType).get(id); - } - } - - public WithOption getWithOption(Class beanType, Object id) { - synchronized (monitor) { - return getClassContext(beanType).getWithOption(id); - } - } - - /** - * Return the number of beans of the given type in the persistence context. - */ - public int size(Class beanType) { - synchronized (monitor) { - ClassContext classMap = typeCache.get(beanType.getName()); - return classMap == null ? 0 : classMap.size(); - } - } - - /** - * Clear the PersistenceContext. - */ - public void clear() { - synchronized (monitor) { - typeCache.clear(); - } - } - - public void clear(Class beanType) { - synchronized (monitor) { - ClassContext classMap = typeCache.get(beanType.getName()); - if (classMap != null) { - classMap.clear(); - } - } - } - - public void deleted(Class beanType, Object id) { - synchronized (monitor) { - ClassContext classMap = typeCache.get(beanType.getName()); - if (classMap != null && id != null) { - classMap.deleted(id); - } - } - } - - public void clear(Class beanType, Object id) { - synchronized (monitor) { - ClassContext classMap = typeCache.get(beanType.getName()); - if (classMap != null && id != null) { - classMap.remove(id); - } - } - } - - public String toString() { - synchronized (monitor) { - return typeCache.toString(); - } - } - - private ClassContext getClassContext(Class beanType) { - - String clsName = getBeanBaseType(beanType).getName(); - ClassContext classMap = typeCache.get(clsName); - if (classMap == null) { - classMap = new ClassContext(); - typeCache.put(clsName, classMap); - } - return classMap; - } - - private Class getBeanBaseType(Class beanType) { - Class parent = beanType.getSuperclass(); - - while (parent != null && parent.isAnnotationPresent(Entity.class)) { - beanType = parent; - parent = parent.getSuperclass(); - } - return beanType; - } - - private static class ClassContext { - - private final Map map = new HashMap(); - - private Set deleteSet; - - private ClassContext() { - } - - public String toString() { - return "size:" + map.size(); - } - - private WithOption getWithOption(Object id) { - if (deleteSet != null && deleteSet.contains(id)) { - return WithOption.DELETED; - } - Object bean = map.get(id); - return (bean == null) ? null : new WithOption(bean); - } - - private Object get(Object id) { - return map.get(id); - } - - private Object putIfAbsent(Object id, Object bean) { - - Object existingValue = map.get(id); - if (existingValue != null) { - // it is not absent - return existingValue; - } - // put the new value and return null indicating the put was successful - map.put(id, bean); - return null; - } - - private void put(Object id, Object b) { - map.put(id, b); - } - - private int size() { - return map.size(); - } - - private void clear() { - map.clear(); - } - - private Object remove(Object id) { - return map.remove(id); - } - - private void deleted(Object id) { - if (deleteSet == null) { - deleteSet = new HashSet(); - } - deleteSet.add(id); - map.remove(id); - } - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.persistence.Entity; + +import com.avaje.ebean.bean.PersistenceContext; +import com.avaje.ebeaninternal.api.Monitor; + +/** + * Default implementation of PersistenceContext. + *

+ * Ensures only one instance of a bean is used according to its type and unique + * id. + *

+ *

+ * PersistenceContext lives on a Transaction and as such is expected to only + * have a single thread accessing it at a time. This is not expected to be used + * concurrently. + *

+ *

+ * Duplicate beans are ones having the same type and unique id value. These are + * considered duplicates and replaced by the bean instance that was already + * loaded into the PersistanceContext. + *

+ */ +public final class DefaultPersistenceContext implements PersistenceContext { + + /** + * Map used hold caches. One cache per bean type. + */ + private final HashMap typeCache = new HashMap(); + + private final Monitor monitor = new Monitor(); + + /** + * Create a new PersistanceContext. + */ + public DefaultPersistenceContext() { + } + + /** + * Set an object into the PersistanceContext. + */ + public void put(Object id, Object bean) { + synchronized (monitor) { + getClassContext(bean.getClass()).put(id, bean); + } + } + + public Object putIfAbsent(Object id, Object bean) { + synchronized (monitor) { + return getClassContext(bean.getClass()).putIfAbsent(id, bean); + } + } + + /** + * Return an object given its type and unique id. + */ + public Object get(Class beanType, Object id) { + synchronized (monitor) { + return getClassContext(beanType).get(id); + } + } + + public WithOption getWithOption(Class beanType, Object id) { + synchronized (monitor) { + return getClassContext(beanType).getWithOption(id); + } + } + + /** + * Return the number of beans of the given type in the persistence context. + */ + public int size(Class beanType) { + synchronized (monitor) { + ClassContext classMap = typeCache.get(beanType.getName()); + return classMap == null ? 0 : classMap.size(); + } + } + + /** + * Clear the PersistenceContext. + */ + public void clear() { + synchronized (monitor) { + typeCache.clear(); + } + } + + public void clear(Class beanType) { + synchronized (monitor) { + ClassContext classMap = typeCache.get(beanType.getName()); + if (classMap != null) { + classMap.clear(); + } + } + } + + public void deleted(Class beanType, Object id) { + synchronized (monitor) { + ClassContext classMap = typeCache.get(beanType.getName()); + if (classMap != null && id != null) { + classMap.deleted(id); + } + } + } + + public void clear(Class beanType, Object id) { + synchronized (monitor) { + ClassContext classMap = typeCache.get(beanType.getName()); + if (classMap != null && id != null) { + classMap.remove(id); + } + } + } + + public String toString() { + synchronized (monitor) { + return typeCache.toString(); + } + } + + private ClassContext getClassContext(Class beanType) { + + String clsName = getBeanBaseType(beanType).getName(); + ClassContext classMap = typeCache.get(clsName); + if (classMap == null) { + classMap = new ClassContext(); + typeCache.put(clsName, classMap); + } + return classMap; + } + + private Class getBeanBaseType(Class beanType) { + Class parent = beanType.getSuperclass(); + + while (parent != null && parent.isAnnotationPresent(Entity.class)) { + beanType = parent; + parent = parent.getSuperclass(); + } + return beanType; + } + + private static class ClassContext { + + private final Map map = new HashMap(); + + private Set deleteSet; + + private ClassContext() { + } + + public String toString() { + return "size:" + map.size(); + } + + private WithOption getWithOption(Object id) { + if (deleteSet != null && deleteSet.contains(id)) { + return WithOption.DELETED; + } + Object bean = map.get(id); + return (bean == null) ? null : new WithOption(bean); + } + + private Object get(Object id) { + return map.get(id); + } + + private Object putIfAbsent(Object id, Object bean) { + + Object existingValue = map.get(id); + if (existingValue != null) { + // it is not absent + return existingValue; + } + // put the new value and return null indicating the put was successful + map.put(id, bean); + return null; + } + + private void put(Object id, Object b) { + map.put(id, b); + } + + private int size() { + return map.size(); + } + + private void clear() { + map.clear(); + } + + private Object remove(Object id) { + return map.remove(id); + } + + private void deleted(Object id) { + if (deleteSet == null) { + deleteSet = new HashSet(); + } + deleteSet.add(id); + map.remove(id); + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java index c95a12093..3bb1287f6 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java @@ -1,128 +1,128 @@ -package com.avaje.ebeaninternal.server.transaction; - -import com.avaje.ebeaninternal.api.SpiTransaction; -import com.avaje.ebeaninternal.server.transaction.TransactionMap.State; - -/** - * Used by EbeanMgr to store its Transactions in a ThreadLocal. This way the - * transaction objects don't have to passed around. - */ -public final class DefaultTransactionThreadLocal { - - private static ThreadLocal local = new ThreadLocal() { - protected synchronized TransactionMap initialValue() { - return new TransactionMap(); - } - }; - - /** - * Not allowed. - */ - private DefaultTransactionThreadLocal() { - } - - /** - * Return the current TransactionState for a given serverName. This is for the - * local thread of course. - */ - private static TransactionMap.State getState(String serverName) { - return local.get().getStateWithCreate(serverName); - } - - /** - * Set a new Transaction for this serverName and Thread. - */ - public static void set(String serverName, SpiTransaction trans) { - getState(serverName).set(trans); - } - - /** - * A mechanism to get the transaction out of the thread local by replacing it - * with a 'proxy'. - *

- * Used for background fetching. Replaces the current transaction with a - * 'dummy' transaction. The current transaction is given to the background - * thread so it can continue the fetch. - *

- */ - public static void replace(String serverName, SpiTransaction trans) { - getState(serverName).replace(trans); - } - - /** - * Return the current Transaction for this serverName and Thread. - */ - public static SpiTransaction get(String serverName) { - TransactionMap map = local.get(); - State state = map.getState(serverName); - SpiTransaction t = (state == null) ? null : state.transaction; - if (map.isEmpty()) { - local.remove(); - } - return t; - } - - /** - * Commit the current transaction. - */ - public static void commit(String serverName) { - TransactionMap map = local.get(); - State state = map.removeState(serverName); - if (state == null) { - throw new IllegalStateException("No current transaction for [" + serverName + "]"); - } - state.commit(); - if (map.isEmpty()) { - local.remove(); - } - } - - /** - * Rollback the current transaction. - */ - public static void rollback(String serverName) { - TransactionMap map = local.get(); - State state = map.removeState(serverName); - if (state == null) { - throw new IllegalStateException("No current transaction for [" + serverName + "]"); - } - state.rollback(); - if (map.isEmpty()) { - local.remove(); - } - } - - /** - * If the transaction has not been committed then roll it back. - *

- * Designed to be put in a finally block instead of a rollback() in each catch - * block. - * - *

-   * Ebean.beingTransaction();
-   * try {
-   *   // ... perform some actions in a single transaction
-   * 
-   *   Ebean.commitTransaction();
-   * 
-   * } finally {
-   *   // ensure transaction ended. If some error occurred then rollback()
-   *   Ebean.endTransaction();
-   * }
-   * 
- * - *

- */ - public static void end(String serverName) { - - TransactionMap map = local.get(); - State state = map.removeState(serverName); - if (state != null) { - state.end(); - } - if (map.isEmpty()) { - local.remove(); - } - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import com.avaje.ebeaninternal.api.SpiTransaction; +import com.avaje.ebeaninternal.server.transaction.TransactionMap.State; + +/** + * Used by EbeanMgr to store its Transactions in a ThreadLocal. This way the + * transaction objects don't have to passed around. + */ +public final class DefaultTransactionThreadLocal { + + private static ThreadLocal local = new ThreadLocal() { + protected synchronized TransactionMap initialValue() { + return new TransactionMap(); + } + }; + + /** + * Not allowed. + */ + private DefaultTransactionThreadLocal() { + } + + /** + * Return the current TransactionState for a given serverName. This is for the + * local thread of course. + */ + private static TransactionMap.State getState(String serverName) { + return local.get().getStateWithCreate(serverName); + } + + /** + * Set a new Transaction for this serverName and Thread. + */ + public static void set(String serverName, SpiTransaction trans) { + getState(serverName).set(trans); + } + + /** + * A mechanism to get the transaction out of the thread local by replacing it + * with a 'proxy'. + *

+ * Used for background fetching. Replaces the current transaction with a + * 'dummy' transaction. The current transaction is given to the background + * thread so it can continue the fetch. + *

+ */ + public static void replace(String serverName, SpiTransaction trans) { + getState(serverName).replace(trans); + } + + /** + * Return the current Transaction for this serverName and Thread. + */ + public static SpiTransaction get(String serverName) { + TransactionMap map = local.get(); + State state = map.getState(serverName); + SpiTransaction t = (state == null) ? null : state.transaction; + if (map.isEmpty()) { + local.remove(); + } + return t; + } + + /** + * Commit the current transaction. + */ + public static void commit(String serverName) { + TransactionMap map = local.get(); + State state = map.removeState(serverName); + if (state == null) { + throw new IllegalStateException("No current transaction for [" + serverName + "]"); + } + state.commit(); + if (map.isEmpty()) { + local.remove(); + } + } + + /** + * Rollback the current transaction. + */ + public static void rollback(String serverName) { + TransactionMap map = local.get(); + State state = map.removeState(serverName); + if (state == null) { + throw new IllegalStateException("No current transaction for [" + serverName + "]"); + } + state.rollback(); + if (map.isEmpty()) { + local.remove(); + } + } + + /** + * If the transaction has not been committed then roll it back. + *

+ * Designed to be put in a finally block instead of a rollback() in each catch + * block. + * + *

+   * Ebean.beingTransaction();
+   * try {
+   *   // ... perform some actions in a single transaction
+   * 
+   *   Ebean.commitTransaction();
+   * 
+   * } finally {
+   *   // ensure transaction ended. If some error occurred then rollback()
+   *   Ebean.endTransaction();
+   * }
+   * 
+ * + *

+ */ + public static void end(String serverName) { + + TransactionMap map = local.get(); + State state = map.removeState(serverName); + if (state != null) { + state.end(); + } + if (map.isEmpty()) { + local.remove(); + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/DeleteByIdMap.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/DeleteByIdMap.java index 7a58e12ca..d0760ad14 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/DeleteByIdMap.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/DeleteByIdMap.java @@ -1,76 +1,76 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.io.Serializable; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import com.avaje.ebeaninternal.server.core.PersistRequest; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; - -/** - * Beans deleted by Id used for updating L2 Cache. - */ -public final class DeleteByIdMap { - - private final Map beanMap = new LinkedHashMap(); - - public String toString() { - return beanMap.toString(); - } - - public void notifyCache() { - for (BeanPersistIds deleteIds : beanMap.values()) { - BeanDescriptor d = deleteIds.getBeanDescriptor(); - List idValues = deleteIds.getDeleteIds(); - if (idValues != null){ - d.queryCacheClear(); - for (int i = 0; i < idValues.size(); i++) { - d.cacheBeanRemove(idValues.get(i)); - } - } - } - - } - - public boolean isEmpty() { - return beanMap.isEmpty(); - } - - public Collection values() { - return beanMap.values(); - } - - /** - * Add a Insert Update or Delete payload. - */ - public void add(BeanDescriptor desc, Object id) { - - BeanPersistIds r = getPersistIds(desc); - r.addId(PersistRequest.Type.DELETE, (Serializable)id); - } - - /** - * Add a List of Insert Update or Delete Id's. - */ - public void addList(BeanDescriptor desc, List idList) { - - BeanPersistIds r = getPersistIds(desc); - for (int i = 0; i < idList.size(); i++) { - r.addId(PersistRequest.Type.DELETE, (Serializable) idList.get(i)); - } - } - - private BeanPersistIds getPersistIds(BeanDescriptor desc) { - String beanType = desc.getFullName(); - BeanPersistIds r = beanMap.get(beanType); - if (r == null){ - r = new BeanPersistIds(desc); - beanMap.put(beanType, r); - } - return r; - } - - -} +package com.avaje.ebeaninternal.server.transaction; + +import java.io.Serializable; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.avaje.ebeaninternal.server.core.PersistRequest; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; + +/** + * Beans deleted by Id used for updating L2 Cache. + */ +public final class DeleteByIdMap { + + private final Map beanMap = new LinkedHashMap(); + + public String toString() { + return beanMap.toString(); + } + + public void notifyCache() { + for (BeanPersistIds deleteIds : beanMap.values()) { + BeanDescriptor d = deleteIds.getBeanDescriptor(); + List idValues = deleteIds.getDeleteIds(); + if (idValues != null){ + d.queryCacheClear(); + for (int i = 0; i < idValues.size(); i++) { + d.cacheBeanRemove(idValues.get(i)); + } + } + } + + } + + public boolean isEmpty() { + return beanMap.isEmpty(); + } + + public Collection values() { + return beanMap.values(); + } + + /** + * Add a Insert Update or Delete payload. + */ + public void add(BeanDescriptor desc, Object id) { + + BeanPersistIds r = getPersistIds(desc); + r.addId(PersistRequest.Type.DELETE, (Serializable)id); + } + + /** + * Add a List of Insert Update or Delete Id's. + */ + public void addList(BeanDescriptor desc, List idList) { + + BeanPersistIds r = getPersistIds(desc); + for (int i = 0; i < idList.size(); i++) { + r.addId(PersistRequest.Type.DELETE, (Serializable) idList.get(i)); + } + } + + private BeanPersistIds getPersistIds(BeanDescriptor desc) { + String beanType = desc.getFullName(); + BeanPersistIds r = beanMap.get(beanType); + if (r == null){ + r = new BeanPersistIds(desc); + beanMap.put(beanType, r); + } + return r; + } + + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java index 106a7ef5e..c8b6cf4d8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/ExternalTransactionScopeManager.java @@ -1,48 +1,48 @@ -package com.avaje.ebeaninternal.server.transaction; - -import com.avaje.ebean.config.ExternalTransactionManager; -import com.avaje.ebeaninternal.api.SpiTransaction; - -/** - * A TransactionScopeManager aware of external transaction managers. - */ -public class ExternalTransactionScopeManager extends TransactionScopeManager { - - final ExternalTransactionManager externalManager; - - /** - * Instantiates transaction scope manager. - * - * @param transactionManager the transaction manager - */ - public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) { - super(transactionManager); - this.externalManager = externalManager; - } - - public void commit() { - DefaultTransactionThreadLocal.commit(serverName); - } - - - public void end() { - DefaultTransactionThreadLocal.end(serverName); - } - - public SpiTransaction get() { - - return (SpiTransaction)externalManager.getCurrentTransaction(); - } - - public void replace(SpiTransaction trans) { - DefaultTransactionThreadLocal.replace(serverName, trans); - } - - public void rollback() { - DefaultTransactionThreadLocal.rollback(serverName); - } - - public void set(SpiTransaction trans) { - DefaultTransactionThreadLocal.set(serverName, trans); - } -} +package com.avaje.ebeaninternal.server.transaction; + +import com.avaje.ebean.config.ExternalTransactionManager; +import com.avaje.ebeaninternal.api.SpiTransaction; + +/** + * A TransactionScopeManager aware of external transaction managers. + */ +public class ExternalTransactionScopeManager extends TransactionScopeManager { + + final ExternalTransactionManager externalManager; + + /** + * Instantiates transaction scope manager. + * + * @param transactionManager the transaction manager + */ + public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) { + super(transactionManager); + this.externalManager = externalManager; + } + + public void commit() { + DefaultTransactionThreadLocal.commit(serverName); + } + + + public void end() { + DefaultTransactionThreadLocal.end(serverName); + } + + public SpiTransaction get() { + + return (SpiTransaction)externalManager.getCurrentTransaction(); + } + + public void replace(SpiTransaction trans) { + DefaultTransactionThreadLocal.replace(serverName, trans); + } + + public void rollback() { + DefaultTransactionThreadLocal.rollback(serverName); + } + + public void set(SpiTransaction trans) { + DefaultTransactionThreadLocal.set(serverName, trans); + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransaction.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransaction.java index 6947734ee..aa4d501bf 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransaction.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransaction.java @@ -1,117 +1,117 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.sql.SQLException; - -import javax.persistence.PersistenceException; -import javax.sql.DataSource; -import javax.transaction.Status; -import javax.transaction.UserTransaction; - -/** - * Jta based transaction. - */ -public class JtaTransaction extends JdbcTransaction { - - private UserTransaction userTransaction; - - private DataSource dataSource; - - private boolean commmitted = false; - - private boolean newTransaction = false; - - - /** - * Create the JtaTransaction. - */ - public JtaTransaction(String id, boolean explicit, UserTransaction utx, DataSource ds, TransactionManager manager) { - super(id, explicit, null, manager); - userTransaction = utx; - dataSource = ds; - - try { - newTransaction = userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION; - if (newTransaction) { - userTransaction.begin(); - } - } catch (Exception e) { - throw new PersistenceException(e); - } - - try { - // Open JDBC Connection - this.connection = dataSource.getConnection(); - if (connection == null) { - throw new PersistenceException("The DataSource returned a null connection."); - } - if (connection.getAutoCommit()) { - connection.setAutoCommit(false); - } - - } catch (SQLException e) { - throw new PersistenceException(e); - } - } - - /** - * Commit the transaction. - */ - public void commit() { - if (commmitted) { - throw new PersistenceException("This transaction has already been committed."); - } - try { - try { - if (newTransaction) { - userTransaction.commit(); - } - notifyCommit(); - } finally { - close(); - } - } catch (Exception e) { - throw new PersistenceException(e); - } - commmitted = true; - } - - public void rollback() { - rollback(null); - } - - /** - * Rollback the transaction. - */ - public void rollback(Throwable e) { - if (!commmitted) { - try { - try { - if (userTransaction != null) { - if (newTransaction) { - userTransaction.rollback(); - } else { - userTransaction.setRollbackOnly(); - } - } - notifyRollback(e); - } finally { - closeConnection(); - } - } catch (Exception ex) { - throw new PersistenceException(ex); - } - } - - } - - /** - * Close the underlying connection. - */ - private void closeConnection() throws SQLException { - if (connection != null) { - connection.close(); - connection = null; - } - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import java.sql.SQLException; + +import javax.persistence.PersistenceException; +import javax.sql.DataSource; +import javax.transaction.Status; +import javax.transaction.UserTransaction; + +/** + * Jta based transaction. + */ +public class JtaTransaction extends JdbcTransaction { + + private UserTransaction userTransaction; + + private DataSource dataSource; + + private boolean commmitted = false; + + private boolean newTransaction = false; + + + /** + * Create the JtaTransaction. + */ + public JtaTransaction(String id, boolean explicit, UserTransaction utx, DataSource ds, TransactionManager manager) { + super(id, explicit, null, manager); + userTransaction = utx; + dataSource = ds; + + try { + newTransaction = userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION; + if (newTransaction) { + userTransaction.begin(); + } + } catch (Exception e) { + throw new PersistenceException(e); + } + + try { + // Open JDBC Connection + this.connection = dataSource.getConnection(); + if (connection == null) { + throw new PersistenceException("The DataSource returned a null connection."); + } + if (connection.getAutoCommit()) { + connection.setAutoCommit(false); + } + + } catch (SQLException e) { + throw new PersistenceException(e); + } + } + + /** + * Commit the transaction. + */ + public void commit() { + if (commmitted) { + throw new PersistenceException("This transaction has already been committed."); + } + try { + try { + if (newTransaction) { + userTransaction.commit(); + } + notifyCommit(); + } finally { + close(); + } + } catch (Exception e) { + throw new PersistenceException(e); + } + commmitted = true; + } + + public void rollback() { + rollback(null); + } + + /** + * Rollback the transaction. + */ + public void rollback(Throwable e) { + if (!commmitted) { + try { + try { + if (userTransaction != null) { + if (newTransaction) { + userTransaction.rollback(); + } else { + userTransaction.setRollbackOnly(); + } + } + notifyRollback(e); + } finally { + closeConnection(); + } + } catch (Exception ex) { + throw new PersistenceException(ex); + } + } + + } + + /** + * Close the underlying connection. + */ + private void closeConnection() throws SQLException { + if (connection != null) { + connection.close(); + connection = null; + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransactionManager.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransactionManager.java index a6f3d6a32..6a6f3d4ef 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransactionManager.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/JtaTransactionManager.java @@ -1,229 +1,229 @@ -package com.avaje.ebeaninternal.server.transaction; - -import javax.naming.InitialContext; -import javax.naming.NamingException; -import javax.persistence.PersistenceException; -import javax.sql.DataSource; -import javax.transaction.HeuristicMixedException; -import javax.transaction.HeuristicRollbackException; -import javax.transaction.NotSupportedException; -import javax.transaction.RollbackException; -import javax.transaction.Status; -import javax.transaction.Synchronization; -import javax.transaction.SystemException; -import javax.transaction.TransactionSynchronizationRegistry; -import javax.transaction.UserTransaction; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.avaje.ebean.config.ExternalTransactionManager; -import com.avaje.ebeaninternal.api.SpiTransaction; - -/** - * Hook into external JTA transaction manager. - * - * @author rbygrave - */ -public class JtaTransactionManager implements ExternalTransactionManager { - - private static final Logger logger = LoggerFactory.getLogger(JtaTransactionManager.class); - - private static final String EBEAN_TXN_RESOURCE = "EBEAN_TXN_RESOURCE"; - - /** - * The data source. - */ - private DataSource dataSource; - - /** - * The Ebean transaction manager. - */ - private TransactionManager transactionManager; - - /** - * The EbeanServer name. - */ - private String serverName; - - /** - * Instantiates a new spring aware transaction scope manager. - */ - public JtaTransactionManager() { - } - - /** - * Initialise this with the Ebean internal transaction manager. - */ - public void setTransactionManager(Object txnMgr) { - - // RB: At this stage not exposing TransactionManager to - // the public API and hence the Object type and casting here - - this.transactionManager = (TransactionManager) txnMgr; - this.dataSource = transactionManager.getDataSource(); - this.serverName = transactionManager.getServerName(); - } - - private TransactionSynchronizationRegistry getSyncRegistry() { - try { - InitialContext ctx = new InitialContext(); - return (TransactionSynchronizationRegistry)ctx.lookup("java:comp/TransactionSynchronizationRegistry"); - } catch (NamingException e){ - throw new PersistenceException(e); - } - } - - private UserTransaction getUserTransaction() { - try { - InitialContext ctx = new InitialContext(); - return (UserTransaction) ctx.lookup("java:comp/UserTransaction"); - } catch (NamingException e){ - // assuming CMT - return new DummyUserTransaction(); - } - } - - /** - * Looks for a current Spring managed transaction and wraps/returns that as a Ebean transaction. - *

- * Returns null if there is no current spring transaction (lazy loading outside a spring txn etc). - *

- */ - public Object getCurrentTransaction() { - - TransactionSynchronizationRegistry syncRegistry = getSyncRegistry(); - - SpiTransaction t = (SpiTransaction)syncRegistry.getResource(EBEAN_TXN_RESOURCE); - if (t != null){ - // we have already seen this transaction - return t; - } - - // check current Ebean transaction - SpiTransaction currentEbeanTransaction = DefaultTransactionThreadLocal.get(serverName); - if (currentEbeanTransaction != null){ - // NOT expecting this so log WARNING - String msg = "JTA Transaction - no current txn BUT using current Ebean one "+currentEbeanTransaction.getId(); - logger.warn(msg); - return currentEbeanTransaction; - } - - UserTransaction ut = getUserTransaction(); - if (ut == null){ - // no current JTA transaction - if (logger.isDebugEnabled()){ - logger.debug("JTA Transaction - no current txn"); - } - return null; - } - - // This is a transaction that Ebean has not seen before. - - // "wrap" it in a Ebean specific JtaTransaction - String txnId = String.valueOf(System.currentTimeMillis()); - JtaTransaction newTrans = new JtaTransaction(txnId, true, ut, dataSource, transactionManager); - - // create and register transaction listener - JtaTxnListener txnListener = createJtaTxnListener(newTrans); - - syncRegistry.putResource(EBEAN_TXN_RESOURCE, newTrans); - syncRegistry.registerInterposedSynchronization(txnListener); - - // also put in Ebean ThreadLocal - DefaultTransactionThreadLocal.set(serverName, newTrans); - return newTrans; - } - - - /** - * Create a listener to register with JTA to enable Ebean to be - * notified when transactions commit and rollback. - *

- * This is used by Ebean to notify it's appropriate listeners and maintain it's server - * cache etc. - *

- */ - private JtaTxnListener createJtaTxnListener(SpiTransaction t) { - return new JtaTxnListener(transactionManager, t); - } - - private static class DummyUserTransaction implements UserTransaction { - - public void begin() throws NotSupportedException, SystemException { - } - - public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, - SecurityException, IllegalStateException, SystemException { - } - - public int getStatus() throws SystemException { - return 0; - } - - public void rollback() throws IllegalStateException, SecurityException, SystemException { - } - - public void setRollbackOnly() throws IllegalStateException, SystemException { - } - - public void setTransactionTimeout(int seconds) throws SystemException { - } - } - - /** - * A JTA Transaction Synchronization that we register to get notified when a - * managed transaction has been committed or rolled back. - *

- * When Ebean is notified (of the commit/rollback) it can then manage its - * cache, notify BeanPersistListeners etc. - *

- */ - private static class JtaTxnListener implements Synchronization { - - private final TransactionManager transactionManager; - - private final SpiTransaction transaction; - - private final String serverName; - - private JtaTxnListener(TransactionManager transactionManager, SpiTransaction t){ - this.transactionManager = transactionManager; - this.transaction = t; - this.serverName = transactionManager.getServerName(); - } - - public void beforeCompletion() { - // Future note: for JPA2 locking we will - // have beforeCommit events to fire - } - - public void afterCompletion(int status) { - - switch (status) { - case Status.STATUS_COMMITTED: - if (logger.isDebugEnabled()){ - logger.debug("Jta Txn ["+transaction.getId()+"] committed"); - } - transactionManager.notifyOfCommit(transaction); - // Remove this transaction object as it is completed - DefaultTransactionThreadLocal.replace(serverName, null); - break; - - case Status.STATUS_ROLLEDBACK: - if (logger.isDebugEnabled()){ - logger.debug("Jta Txn ["+transaction.getId()+"] rollback"); - } - transactionManager.notifyOfRollback(transaction, null); - // Remove this transaction object as it is completed - DefaultTransactionThreadLocal.replace(serverName, null); - break; - - default: - logger.debug("Jta Txn ["+transaction.getId()+"] status:"+status); - } - - } - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.persistence.PersistenceException; +import javax.sql.DataSource; +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.Status; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.TransactionSynchronizationRegistry; +import javax.transaction.UserTransaction; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.avaje.ebean.config.ExternalTransactionManager; +import com.avaje.ebeaninternal.api.SpiTransaction; + +/** + * Hook into external JTA transaction manager. + * + * @author rbygrave + */ +public class JtaTransactionManager implements ExternalTransactionManager { + + private static final Logger logger = LoggerFactory.getLogger(JtaTransactionManager.class); + + private static final String EBEAN_TXN_RESOURCE = "EBEAN_TXN_RESOURCE"; + + /** + * The data source. + */ + private DataSource dataSource; + + /** + * The Ebean transaction manager. + */ + private TransactionManager transactionManager; + + /** + * The EbeanServer name. + */ + private String serverName; + + /** + * Instantiates a new spring aware transaction scope manager. + */ + public JtaTransactionManager() { + } + + /** + * Initialise this with the Ebean internal transaction manager. + */ + public void setTransactionManager(Object txnMgr) { + + // RB: At this stage not exposing TransactionManager to + // the public API and hence the Object type and casting here + + this.transactionManager = (TransactionManager) txnMgr; + this.dataSource = transactionManager.getDataSource(); + this.serverName = transactionManager.getServerName(); + } + + private TransactionSynchronizationRegistry getSyncRegistry() { + try { + InitialContext ctx = new InitialContext(); + return (TransactionSynchronizationRegistry)ctx.lookup("java:comp/TransactionSynchronizationRegistry"); + } catch (NamingException e){ + throw new PersistenceException(e); + } + } + + private UserTransaction getUserTransaction() { + try { + InitialContext ctx = new InitialContext(); + return (UserTransaction) ctx.lookup("java:comp/UserTransaction"); + } catch (NamingException e){ + // assuming CMT + return new DummyUserTransaction(); + } + } + + /** + * Looks for a current Spring managed transaction and wraps/returns that as a Ebean transaction. + *

+ * Returns null if there is no current spring transaction (lazy loading outside a spring txn etc). + *

+ */ + public Object getCurrentTransaction() { + + TransactionSynchronizationRegistry syncRegistry = getSyncRegistry(); + + SpiTransaction t = (SpiTransaction)syncRegistry.getResource(EBEAN_TXN_RESOURCE); + if (t != null){ + // we have already seen this transaction + return t; + } + + // check current Ebean transaction + SpiTransaction currentEbeanTransaction = DefaultTransactionThreadLocal.get(serverName); + if (currentEbeanTransaction != null){ + // NOT expecting this so log WARNING + String msg = "JTA Transaction - no current txn BUT using current Ebean one "+currentEbeanTransaction.getId(); + logger.warn(msg); + return currentEbeanTransaction; + } + + UserTransaction ut = getUserTransaction(); + if (ut == null){ + // no current JTA transaction + if (logger.isDebugEnabled()){ + logger.debug("JTA Transaction - no current txn"); + } + return null; + } + + // This is a transaction that Ebean has not seen before. + + // "wrap" it in a Ebean specific JtaTransaction + String txnId = String.valueOf(System.currentTimeMillis()); + JtaTransaction newTrans = new JtaTransaction(txnId, true, ut, dataSource, transactionManager); + + // create and register transaction listener + JtaTxnListener txnListener = createJtaTxnListener(newTrans); + + syncRegistry.putResource(EBEAN_TXN_RESOURCE, newTrans); + syncRegistry.registerInterposedSynchronization(txnListener); + + // also put in Ebean ThreadLocal + DefaultTransactionThreadLocal.set(serverName, newTrans); + return newTrans; + } + + + /** + * Create a listener to register with JTA to enable Ebean to be + * notified when transactions commit and rollback. + *

+ * This is used by Ebean to notify it's appropriate listeners and maintain it's server + * cache etc. + *

+ */ + private JtaTxnListener createJtaTxnListener(SpiTransaction t) { + return new JtaTxnListener(transactionManager, t); + } + + private static class DummyUserTransaction implements UserTransaction { + + public void begin() throws NotSupportedException, SystemException { + } + + public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, + SecurityException, IllegalStateException, SystemException { + } + + public int getStatus() throws SystemException { + return 0; + } + + public void rollback() throws IllegalStateException, SecurityException, SystemException { + } + + public void setRollbackOnly() throws IllegalStateException, SystemException { + } + + public void setTransactionTimeout(int seconds) throws SystemException { + } + } + + /** + * A JTA Transaction Synchronization that we register to get notified when a + * managed transaction has been committed or rolled back. + *

+ * When Ebean is notified (of the commit/rollback) it can then manage its + * cache, notify BeanPersistListeners etc. + *

+ */ + private static class JtaTxnListener implements Synchronization { + + private final TransactionManager transactionManager; + + private final SpiTransaction transaction; + + private final String serverName; + + private JtaTxnListener(TransactionManager transactionManager, SpiTransaction t){ + this.transactionManager = transactionManager; + this.transaction = t; + this.serverName = transactionManager.getServerName(); + } + + public void beforeCompletion() { + // Future note: for JPA2 locking we will + // have beforeCommit events to fire + } + + public void afterCompletion(int status) { + + switch (status) { + case Status.STATUS_COMMITTED: + if (logger.isDebugEnabled()){ + logger.debug("Jta Txn ["+transaction.getId()+"] committed"); + } + transactionManager.notifyOfCommit(transaction); + // Remove this transaction object as it is completed + DefaultTransactionThreadLocal.replace(serverName, null); + break; + + case Status.STATUS_ROLLEDBACK: + if (logger.isDebugEnabled()){ + logger.debug("Jta Txn ["+transaction.getId()+"] rollback"); + } + transactionManager.notifyOfRollback(transaction, null); + // Remove this transaction object as it is completed + DefaultTransactionThreadLocal.replace(serverName, null); + break; + + default: + logger.debug("Jta Txn ["+transaction.getId()+"] status:"+status); + } + + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java index 2243ca4ef..da0e23979 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/PostCommitProcessing.java @@ -1,163 +1,163 @@ -package com.avaje.ebeaninternal.server.transaction; - -import com.avaje.ebeaninternal.api.TransactionEvent; -import com.avaje.ebeaninternal.api.TransactionEventBeans; -import com.avaje.ebeaninternal.api.TransactionEventTable; -import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; -import com.avaje.ebeaninternal.server.cluster.ClusterManager; -import com.avaje.ebeaninternal.server.core.PersistRequestBean; -import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -/** - * Performs post commit processing using a background thread. - *

- * This includes Cluster notification, and BeanPersistListeners. - *

- */ -public final class PostCommitProcessing { - - private static final Logger logger = LoggerFactory.getLogger(PostCommitProcessing.class); - - private final ClusterManager clusterManager; - - private final TransactionEvent event; - - private final String serverName; - - private final TransactionManager manager; - - private final List> persistBeanRequests; - - private final BeanPersistIdMap beanPersistIdMap; - - private final RemoteTransactionEvent remoteTransactionEvent; - - private final DeleteByIdMap deleteByIdMap; - - /** - * Create for a TransactionManager and event. - */ - public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) { - - this.clusterManager = clusterManager; - this.manager = manager; - this.serverName = manager.getServerName(); - this.event = event; - this.deleteByIdMap = event.getDeleteByIdMap(); - this.persistBeanRequests = createPersistBeanRequests(); - this.beanPersistIdMap = createBeanPersistIdMap(); - this.remoteTransactionEvent = createRemoteTransactionEvent(); - } - - public void notifyLocalCacheIndex() { - - // notify cache with bulk insert/update/delete statements - processTableEvents(event.getEventTables()); - - // notify cache with bean changes - event.notifyCache(); - } - - /** - * Table events are where SQL or external tools are used. In this case the - * cache is notified based on the table name (rather than bean type). - */ - private void processTableEvents(TransactionEventTable tableEvents) { - - if (tableEvents != null && !tableEvents.isEmpty()) { - // notify cache with table based changes - BeanDescriptorManager dm = manager.getBeanDescriptorManager(); - for (TableIUD tableIUD : tableEvents.values()) { - dm.cacheNotify(tableIUD); - } - } - } - - public void notifyCluster() { - if (remoteTransactionEvent != null && !remoteTransactionEvent.isEmpty()) { - // send the interesting events to the cluster - if (logger.isDebugEnabled()) { - logger.debug("Cluster Send: {}", remoteTransactionEvent); - } - - clusterManager.broadcast(remoteTransactionEvent); - } - } - - public Runnable notifyPersistListeners() { - return new Runnable() { - public void run() { - localPersistListenersNotify(); - } - }; - } - - private void localPersistListenersNotify() { - if (persistBeanRequests != null) { - for (int i = 0; i < persistBeanRequests.size(); i++) { - persistBeanRequests.get(i).notifyLocalPersistListener(); - } - } - TransactionEventTable eventTables = event.getEventTables(); - if (eventTables != null && !eventTables.isEmpty()) { - BulkEventListenerMap map = manager.getBulkEventListenerMap(); - for (TableIUD tableIUD : eventTables.values()) { - map.process(tableIUD); - } - } - } - - private List> createPersistBeanRequests() { - TransactionEventBeans eventBeans = event.getEventBeans(); - if (eventBeans != null) { - return eventBeans.getRequests(); - } - return null; - } - - private BeanPersistIdMap createBeanPersistIdMap() { - - if (persistBeanRequests == null) { - return null; - } - - BeanPersistIdMap m = new BeanPersistIdMap(); - for (int i = 0; i < persistBeanRequests.size(); i++) { - persistBeanRequests.get(i).addToPersistMap(m); - } - return m; - } - - private RemoteTransactionEvent createRemoteTransactionEvent() { - - if (!clusterManager.isClustering()) { - return null; - } - - RemoteTransactionEvent remoteTransactionEvent = new RemoteTransactionEvent(serverName); - - if (beanPersistIdMap != null) { - for (BeanPersistIds beanPersist : beanPersistIdMap.values()) { - remoteTransactionEvent.addBeanPersistIds(beanPersist); - } - } - - if (deleteByIdMap != null) { - remoteTransactionEvent.setDeleteByIdMap(deleteByIdMap); - } - - TransactionEventTable eventTables = event.getEventTables(); - if (eventTables != null && !eventTables.isEmpty()) { - for (TableIUD tableIUD : eventTables.values()) { - remoteTransactionEvent.addTableIUD(tableIUD); - } - } - - return remoteTransactionEvent; - } - -} +package com.avaje.ebeaninternal.server.transaction; + +import com.avaje.ebeaninternal.api.TransactionEvent; +import com.avaje.ebeaninternal.api.TransactionEventBeans; +import com.avaje.ebeaninternal.api.TransactionEventTable; +import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; +import com.avaje.ebeaninternal.server.cluster.ClusterManager; +import com.avaje.ebeaninternal.server.core.PersistRequestBean; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +/** + * Performs post commit processing using a background thread. + *

+ * This includes Cluster notification, and BeanPersistListeners. + *

+ */ +public final class PostCommitProcessing { + + private static final Logger logger = LoggerFactory.getLogger(PostCommitProcessing.class); + + private final ClusterManager clusterManager; + + private final TransactionEvent event; + + private final String serverName; + + private final TransactionManager manager; + + private final List> persistBeanRequests; + + private final BeanPersistIdMap beanPersistIdMap; + + private final RemoteTransactionEvent remoteTransactionEvent; + + private final DeleteByIdMap deleteByIdMap; + + /** + * Create for a TransactionManager and event. + */ + public PostCommitProcessing(ClusterManager clusterManager, TransactionManager manager, TransactionEvent event) { + + this.clusterManager = clusterManager; + this.manager = manager; + this.serverName = manager.getServerName(); + this.event = event; + this.deleteByIdMap = event.getDeleteByIdMap(); + this.persistBeanRequests = createPersistBeanRequests(); + this.beanPersistIdMap = createBeanPersistIdMap(); + this.remoteTransactionEvent = createRemoteTransactionEvent(); + } + + public void notifyLocalCacheIndex() { + + // notify cache with bulk insert/update/delete statements + processTableEvents(event.getEventTables()); + + // notify cache with bean changes + event.notifyCache(); + } + + /** + * Table events are where SQL or external tools are used. In this case the + * cache is notified based on the table name (rather than bean type). + */ + private void processTableEvents(TransactionEventTable tableEvents) { + + if (tableEvents != null && !tableEvents.isEmpty()) { + // notify cache with table based changes + BeanDescriptorManager dm = manager.getBeanDescriptorManager(); + for (TableIUD tableIUD : tableEvents.values()) { + dm.cacheNotify(tableIUD); + } + } + } + + public void notifyCluster() { + if (remoteTransactionEvent != null && !remoteTransactionEvent.isEmpty()) { + // send the interesting events to the cluster + if (logger.isDebugEnabled()) { + logger.debug("Cluster Send: {}", remoteTransactionEvent); + } + + clusterManager.broadcast(remoteTransactionEvent); + } + } + + public Runnable notifyPersistListeners() { + return new Runnable() { + public void run() { + localPersistListenersNotify(); + } + }; + } + + private void localPersistListenersNotify() { + if (persistBeanRequests != null) { + for (int i = 0; i < persistBeanRequests.size(); i++) { + persistBeanRequests.get(i).notifyLocalPersistListener(); + } + } + TransactionEventTable eventTables = event.getEventTables(); + if (eventTables != null && !eventTables.isEmpty()) { + BulkEventListenerMap map = manager.getBulkEventListenerMap(); + for (TableIUD tableIUD : eventTables.values()) { + map.process(tableIUD); + } + } + } + + private List> createPersistBeanRequests() { + TransactionEventBeans eventBeans = event.getEventBeans(); + if (eventBeans != null) { + return eventBeans.getRequests(); + } + return null; + } + + private BeanPersistIdMap createBeanPersistIdMap() { + + if (persistBeanRequests == null) { + return null; + } + + BeanPersistIdMap m = new BeanPersistIdMap(); + for (int i = 0; i < persistBeanRequests.size(); i++) { + persistBeanRequests.get(i).addToPersistMap(m); + } + return m; + } + + private RemoteTransactionEvent createRemoteTransactionEvent() { + + if (!clusterManager.isClustering()) { + return null; + } + + RemoteTransactionEvent remoteTransactionEvent = new RemoteTransactionEvent(serverName); + + if (beanPersistIdMap != null) { + for (BeanPersistIds beanPersist : beanPersistIdMap.values()) { + remoteTransactionEvent.addBeanPersistIds(beanPersist); + } + } + + if (deleteByIdMap != null) { + remoteTransactionEvent.setDeleteByIdMap(deleteByIdMap); + } + + TransactionEventTable eventTables = event.getEventTables(); + if (eventTables != null && !eventTables.isEmpty()) { + for (TableIUD tableIUD : eventTables.values()) { + remoteTransactionEvent.addTableIUD(tableIUD); + } + } + + return remoteTransactionEvent; + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/RemoteTransactionEvent.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/RemoteTransactionEvent.java index 9618bbac5..eb7f62d57 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/RemoteTransactionEvent.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/RemoteTransactionEvent.java @@ -1,141 +1,141 @@ -package com.avaje.ebeaninternal.server.transaction; - -import com.avaje.ebeaninternal.api.SpiEbeanServer; -import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; -import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -public class RemoteTransactionEvent implements Runnable { - - private List beanPersistList = new ArrayList(); - - private List tableList; - - private List beanDeltaLists; - - private BeanDeltaMap beanDeltaMap; - - private DeleteByIdMap deleteByIdMap; - - private String serverName; - - private transient SpiEbeanServer server; - - public RemoteTransactionEvent(String serverName) { - this.serverName = serverName; - } - - public RemoteTransactionEvent(SpiEbeanServer server) { - this.server = server; - } - - public void run() { - server.remoteTransactionEvent(this); - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - if (beanDeltaMap != null){ - sb.append(beanDeltaMap); - } - sb.append(beanPersistList); - if (tableList != null){ - sb.append(tableList); - } - return sb.toString(); - } - - public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { - - if (tableList != null){ - for (int i = 0; i < tableList.size(); i++) { - tableList.get(i).writeBinaryMessage(msgList); - } - } - - if (deleteByIdMap != null){ - for (BeanPersistIds deleteIds : deleteByIdMap.values()) { - deleteIds.writeBinaryMessage(msgList); - } - } - - if (beanPersistList != null){ - for (int i = 0; i < beanPersistList.size(); i++) { - beanPersistList.get(i).writeBinaryMessage(msgList); - } - } - - if (beanDeltaLists != null){ - for (int i = 0; i < beanDeltaLists.size(); i++) { - beanDeltaLists.get(i).writeBinaryMessage(msgList); - } - } - } - - public boolean isEmpty() { - return beanPersistList.isEmpty() && (tableList == null || tableList.isEmpty()); - } - - public void addBeanPersistIds(BeanPersistIds beanPersist){ - beanPersistList.add(beanPersist); - } - - public void addTableIUD(TableIUD tableIud){ - if (tableList == null){ - tableList = new ArrayList(4); - } - tableList.add(tableIud); - } - - public void addBeanDeltaList(BeanDeltaList deltaList){ - if (beanDeltaLists == null){ - beanDeltaLists = new ArrayList(); - } - beanDeltaLists.add(deltaList); - } - - public void addBeanDelta(BeanDelta beanDelta){ - if (beanDeltaMap == null){ - beanDeltaMap = new BeanDeltaMap(); - } - beanDeltaMap.addBeanDelta(beanDelta); - } - - public String getServerName() { - return serverName; - } - - public SpiEbeanServer getServer() { - return server; - } - - public void setServer(SpiEbeanServer server) { - this.server = server; - } - - public DeleteByIdMap getDeleteByIdMap() { - return deleteByIdMap; - } - - public void setDeleteByIdMap(DeleteByIdMap deleteByIdMap) { - this.deleteByIdMap = deleteByIdMap; - } - - public List getTableIUDList() { - return tableList; - } - - public List getBeanPersistList() { - return beanPersistList; - } - - public List getBeanDeltaLists() { - if (beanDeltaMap != null){ - beanDeltaLists.addAll(beanDeltaMap.deltaLists()); - } - return beanDeltaLists; - } -} +package com.avaje.ebeaninternal.server.transaction; + +import com.avaje.ebeaninternal.api.SpiEbeanServer; +import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD; +import com.avaje.ebeaninternal.server.cluster.BinaryMessageList; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class RemoteTransactionEvent implements Runnable { + + private List beanPersistList = new ArrayList(); + + private List tableList; + + private List beanDeltaLists; + + private BeanDeltaMap beanDeltaMap; + + private DeleteByIdMap deleteByIdMap; + + private String serverName; + + private transient SpiEbeanServer server; + + public RemoteTransactionEvent(String serverName) { + this.serverName = serverName; + } + + public RemoteTransactionEvent(SpiEbeanServer server) { + this.server = server; + } + + public void run() { + server.remoteTransactionEvent(this); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + if (beanDeltaMap != null){ + sb.append(beanDeltaMap); + } + sb.append(beanPersistList); + if (tableList != null){ + sb.append(tableList); + } + return sb.toString(); + } + + public void writeBinaryMessage(BinaryMessageList msgList) throws IOException { + + if (tableList != null){ + for (int i = 0; i < tableList.size(); i++) { + tableList.get(i).writeBinaryMessage(msgList); + } + } + + if (deleteByIdMap != null){ + for (BeanPersistIds deleteIds : deleteByIdMap.values()) { + deleteIds.writeBinaryMessage(msgList); + } + } + + if (beanPersistList != null){ + for (int i = 0; i < beanPersistList.size(); i++) { + beanPersistList.get(i).writeBinaryMessage(msgList); + } + } + + if (beanDeltaLists != null){ + for (int i = 0; i < beanDeltaLists.size(); i++) { + beanDeltaLists.get(i).writeBinaryMessage(msgList); + } + } + } + + public boolean isEmpty() { + return beanPersistList.isEmpty() && (tableList == null || tableList.isEmpty()); + } + + public void addBeanPersistIds(BeanPersistIds beanPersist){ + beanPersistList.add(beanPersist); + } + + public void addTableIUD(TableIUD tableIud){ + if (tableList == null){ + tableList = new ArrayList(4); + } + tableList.add(tableIud); + } + + public void addBeanDeltaList(BeanDeltaList deltaList){ + if (beanDeltaLists == null){ + beanDeltaLists = new ArrayList(); + } + beanDeltaLists.add(deltaList); + } + + public void addBeanDelta(BeanDelta beanDelta){ + if (beanDeltaMap == null){ + beanDeltaMap = new BeanDeltaMap(); + } + beanDeltaMap.addBeanDelta(beanDelta); + } + + public String getServerName() { + return serverName; + } + + public SpiEbeanServer getServer() { + return server; + } + + public void setServer(SpiEbeanServer server) { + this.server = server; + } + + public DeleteByIdMap getDeleteByIdMap() { + return deleteByIdMap; + } + + public void setDeleteByIdMap(DeleteByIdMap deleteByIdMap) { + this.deleteByIdMap = deleteByIdMap; + } + + public List getTableIUDList() { + return tableList; + } + + public List getBeanPersistList() { + return beanPersistList; + } + + public List getBeanDeltaLists() { + if (beanDeltaMap != null){ + beanDeltaLists.addAll(beanDeltaMap.deltaLists()); + } + return beanDeltaLists; + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionMap.java b/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionMap.java index 053c14162..e3cc71f83 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionMap.java +++ b/src/main/java/com/avaje/ebeaninternal/server/transaction/TransactionMap.java @@ -1,118 +1,118 @@ -package com.avaje.ebeaninternal.server.transaction; - -import java.util.HashMap; - -import javax.persistence.PersistenceException; - -import com.avaje.ebeaninternal.api.SpiTransaction; - - -/** - * Current transactions mapped by server name. - */ -public class TransactionMap { - - /** - * Map of State by serverName. - */ - private HashMap map = new HashMap(); - - public String toString() { - return map.toString(); - } - - public boolean isEmpty() { - return map.isEmpty(); - } - - /** - * Return the State for a given serverName. - */ - public State getState(String serverName) { - - return map.get(serverName); - } - - /** - * Return the State for a given serverName. - */ - public State getStateWithCreate(String serverName) { - - State state = map.get(serverName); - if (state == null){ - state = new State(); - map.put(serverName, state); - } - return state; - } - - /** - * Remove and return the State for a given serverName. - */ - public State removeState(String serverName) { - return map.remove(serverName); - } - - /** - * The transaction and whether it is active. - */ - public static class State { - - SpiTransaction transaction; - - public String toString() { - return "txn["+transaction+"]"; - } - - public SpiTransaction get() { - return transaction; - } - - /** - * Set the transaction. This will now be the current transaction. - */ - public void set(SpiTransaction trans) { - - if (transaction != null && transaction.isActive()){ - String m = "The existing transaction is still active?"; - throw new PersistenceException(m); - } - transaction = trans; - } - - - /** - * Commit the transaction. - */ - public void commit() { - transaction.commit(); - transaction = null; - } - - /** - * Rollback the transaction. - */ - public void rollback() { - transaction.rollback(); - transaction = null; - } - - /** - * End the transaction. - */ - public void end() { - if (transaction != null){ - transaction.end(); - transaction = null; - } - } - - /** - * Used to replace transaction with a proxy. - */ - public void replace(SpiTransaction trans) { - transaction = trans; - } - - } -} +package com.avaje.ebeaninternal.server.transaction; + +import java.util.HashMap; + +import javax.persistence.PersistenceException; + +import com.avaje.ebeaninternal.api.SpiTransaction; + + +/** + * Current transactions mapped by server name. + */ +public class TransactionMap { + + /** + * Map of State by serverName. + */ + private HashMap map = new HashMap(); + + public String toString() { + return map.toString(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + /** + * Return the State for a given serverName. + */ + public State getState(String serverName) { + + return map.get(serverName); + } + + /** + * Return the State for a given serverName. + */ + public State getStateWithCreate(String serverName) { + + State state = map.get(serverName); + if (state == null){ + state = new State(); + map.put(serverName, state); + } + return state; + } + + /** + * Remove and return the State for a given serverName. + */ + public State removeState(String serverName) { + return map.remove(serverName); + } + + /** + * The transaction and whether it is active. + */ + public static class State { + + SpiTransaction transaction; + + public String toString() { + return "txn["+transaction+"]"; + } + + public SpiTransaction get() { + return transaction; + } + + /** + * Set the transaction. This will now be the current transaction. + */ + public void set(SpiTransaction trans) { + + if (transaction != null && transaction.isActive()){ + String m = "The existing transaction is still active?"; + throw new PersistenceException(m); + } + transaction = trans; + } + + + /** + * Commit the transaction. + */ + public void commit() { + transaction.commit(); + transaction = null; + } + + /** + * Rollback the transaction. + */ + public void rollback() { + transaction.rollback(); + transaction = null; + } + + /** + * End the transaction. + */ + public void end() { + if (transaction != null){ + transaction.end(); + transaction = null; + } + } + + /** + * Used to replace transaction with a proxy. + */ + public void replace(SpiTransaction trans) { + transaction = trans; + } + + } +}