diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractAttribute.java
index c05c4a322cbff24e7b544dbb92ee13683f86b80f..17a6ca5eb8391f71868c800d6ab241480af6453b 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AbstractAttribute.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractAttribute.java
@@ -19,6 +19,7 @@
 package org.sleuthkit.datamodel;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Attributes are a name-value pairs. Abstract Attribute provides the base
@@ -53,7 +54,7 @@ abstract class AbstractAttribute {
 	 *                                  attribute type is not
 	 *                                  TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER.
 	 */
-	public AbstractAttribute(BlackboardAttribute.Type attributeType, int valueInt) throws IllegalArgumentException {
+	public AbstractAttribute(BlackboardAttribute.Type attributeType, int valueInt) {
 		if (attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER) {
 			throw new IllegalArgumentException("Type mismatched with value type");
 		}
@@ -80,7 +81,7 @@ public AbstractAttribute(BlackboardAttribute.Type attributeType, int valueInt) t
 	 *                                  or
 	 *                                  TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME.
 	 */
-	public AbstractAttribute(BlackboardAttribute.Type attributeType, long valueLong) throws IllegalArgumentException {
+	public AbstractAttribute(BlackboardAttribute.Type attributeType, long valueLong) {
 		if (attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG
 				&& attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME) {
 			throw new IllegalArgumentException("Type mismatched with value type");
@@ -106,7 +107,7 @@ public AbstractAttribute(BlackboardAttribute.Type attributeType, long valueLong)
 	 *                                  attribute type is not
 	 *                                  TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE.
 	 */
-	public AbstractAttribute(BlackboardAttribute.Type attributeType, double valueDouble) throws IllegalArgumentException {
+	public AbstractAttribute(BlackboardAttribute.Type attributeType, double valueDouble) {
 		if (attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE) {
 			throw new IllegalArgumentException("Type mismatched with value type");
 		}
@@ -131,7 +132,7 @@ public AbstractAttribute(BlackboardAttribute.Type attributeType, double valueDou
 	 *                                  attribute type is not
 	 *                                  TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING.
 	 */
-	public AbstractAttribute(BlackboardAttribute.Type attributeType, String valueString) throws IllegalArgumentException {
+	public AbstractAttribute(BlackboardAttribute.Type attributeType, String valueString) {
 		if (attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING
 				&& attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON) {
 			throw new IllegalArgumentException("Type mismatched with value type");
@@ -161,7 +162,7 @@ public AbstractAttribute(BlackboardAttribute.Type attributeType, String valueStr
 	 *                                  attribute type is not
 	 *                                  TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE.
 	 */
-	public AbstractAttribute(BlackboardAttribute.Type attributeType, byte[] valueBytes) throws IllegalArgumentException {
+	public AbstractAttribute(BlackboardAttribute.Type attributeType, byte[] valueBytes) {
 		if (attributeType.getValueType() != BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE) {
 			throw new IllegalArgumentException("Type mismatched with value type");
 		}
@@ -319,11 +320,17 @@ public byte[] getValueBytes() {
 		return Arrays.copyOf(valueBytes, valueBytes.length);
 	}
 
+	/**
+	 * Gets the owner Id of this attribute. An owner is defined as the Object
+	 * to which this attribute is associated with.
+	 * Eg: For a file Attribute, the owner id would be the file object id. 
+	 * @return
+	 */
 	public long getAttributeOwnerId() {
 		return this.attributeOwnerId;
 	}
 
-	SleuthkitCase getSleuthkitCase() {
+	SleuthkitCase getCaseDatabase() {
 		return this.sleuthkitCase;
 	}
 
@@ -375,4 +382,19 @@ static String bytesToHexString(byte[] bytes) {
 	final String replaceNulls(String text) {
 		return text.replace((char) 0x00, (char) 0x1A);
 	}
+
+
+	boolean isAttributeEquals(Object that) {
+		if (that instanceof AbstractAttribute) {
+			AbstractAttribute other = (AbstractAttribute) that;
+			Object[] thisObject = new Object[]{this.getAttributeType(), this.getValueInt(), this.getValueLong(), this.getValueDouble(),
+				this.getValueString(), this.getValueBytes()};
+			Object[] otherObject = new Object[]{other.getAttributeType(), other.getValueInt(), other.getValueLong(), other.getValueDouble(),
+				other.getValueString(), other.getValueBytes()};
+
+			return Objects.deepEquals(thisObject, otherObject);
+		} else {
+			return false;
+		}
+	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
index 62bde247ca59c9ba95918be9c04f75b92438d768..4bd7fedef48a467ab8df73094803dad2aad3f43a 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/AbstractFile.java
@@ -517,7 +517,7 @@ public String getSha256Hash() {
 	 * @return
 	 * @throws TskCoreException 
 	 */
-	public List<Attribute> getAttributes() throws TskCoreException {
+	public synchronized List<Attribute> getAttributes() throws TskCoreException {
 		if (!loadedAttributesCacheFromDb.get()) {
 			ArrayList<Attribute> attributes = getSleuthkitCase().getFileAttributes(this);
 			fileAttributesCache.clear();
@@ -567,8 +567,6 @@ public void addAttributes(Collection<Attribute> attributes, final SleuthkitCase.
 				fileAttributesCache.addAll(attributes);
 			}
 		} catch (SQLException ex) {
-			throw new TskCoreException("Error adding file attributes", ex);
-		} finally {
 			if (isLocalTransaction && null != localTransaction) {
 				try {
 					localTransaction.rollback();
@@ -576,6 +574,7 @@ public void addAttributes(Collection<Attribute> attributes, final SleuthkitCase.
 					LOGGER.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
 				}
 			}
+			throw new TskCoreException("Error adding file attributes", ex);
 		}
 	}
 	
diff --git a/bindings/java/src/org/sleuthkit/datamodel/Attribute.java b/bindings/java/src/org/sleuthkit/datamodel/Attribute.java
index 22de10637c900d57be54cbd0ec3b0c28c848a1bd..ce3afbccded0ab00a1d645aedfd2c3e69d945db4 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/Attribute.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/Attribute.java
@@ -143,13 +143,7 @@ public boolean equals(Object that) {
 		if (this == that) {
 			return true;
 		} else if (that instanceof Attribute) {
-			AbstractAttribute other = (AbstractAttribute) that;
-			Object[] thisObject = new Object[]{this.getAttributeType(), this.getValueInt(), this.getValueLong(), this.getValueDouble(),
-				this.getValueString(), this.getValueBytes()};
-			Object[] otherObject = new Object[]{other.getAttributeType(), other.getValueInt(), other.getValueLong(), other.getValueDouble(),
-				other.getValueString(), other.getValueBytes()};
-
-			return Objects.deepEquals(thisObject, otherObject);
+ 			return isAttributeEquals(that);
 		} else {
 			return false;
 		}
@@ -164,7 +158,7 @@ public String toString() {
 				.add("valueDouble", getValueDouble())
 				.add("valueString", getValueString())
 				.add("valueBytes", Arrays.toString(getValueBytes()) )
-				.add("Case", getSleuthkitCase())
+				.add("Case", getCaseDatabase())
 				.toString();
 	}
 }
\ No newline at end of file
diff --git a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
index 57530d39ed1ea0e19e479edce653a54fa90bc321..3b5f1658062aac227475dadfd8fca345f977aa12 100755
--- a/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/BlackboardAttribute.java
@@ -288,7 +288,7 @@ public List<String> getSources() {
 	 * @throws org.sleuthkit.datamodel.TskCoreException
 	 */
 	public void addSource(String source) throws TskCoreException {
-		this.sources = getSleuthkitCase().addSourceToArtifactAttribute(this, source);
+		this.sources = getCaseDatabase().addSourceToArtifactAttribute(this, source);
 	}
 
 	/**
@@ -304,7 +304,7 @@ public void addSource(String source) throws TskCoreException {
 	 */
 	public BlackboardArtifact getParentArtifact() throws TskCoreException {
 		if (parentArtifact == null) {
-			parentArtifact = getSleuthkitCase().getBlackboardArtifact(getArtifactID());
+			parentArtifact = getCaseDatabase().getBlackboardArtifact(getArtifactID());
 		}
 		return parentArtifact;
 	}
@@ -314,7 +314,7 @@ public BlackboardArtifact getParentArtifact() throws TskCoreException {
 	public int hashCode() {
 		return Objects.hash(
 				this.getAttributeType(), this.getValueInt(), this.getValueLong(), this.getValueDouble(),
-				this.getValueString(), this.getValueBytes(), this.getSources());
+				this.getValueString(), this.getValueBytes(), this.getSources(), getContext());
 	}
 
 	@Override
@@ -323,12 +323,9 @@ public boolean equals(Object that) {
 			return true;
 		} else if (that instanceof BlackboardAttribute) {
 			BlackboardAttribute other = (BlackboardAttribute) that;
-			Object[] thisObject = new Object[]{this.getAttributeType(), this.getValueInt(), this.getValueLong(), this.getValueDouble(),
-				this.getValueString(), this.getValueBytes(), this.getSources()};
-			Object[] otherObject = new Object[]{other.getAttributeType(), other.getValueInt(), other.getValueLong(), other.getValueDouble(),
-				other.getValueString(), other.getValueBytes(), other.getSources()};
-
-			return Objects.deepEquals(thisObject, otherObject);
+			Object[] thisObject = new Object[]{this.getSources(), this.getContext()};
+			Object[] otherObject = new Object[]{other.getSources(), other.getContext()};
+			return isAttributeEquals(that) && Objects.deepEquals(thisObject, otherObject);
 		} else {
 			return false;
 		}
@@ -336,7 +333,7 @@ public boolean equals(Object that) {
 
 	@Override
 	public String toString() {
-		return "BlackboardAttribute{" + "artifactID=" + getArtifactID() + ", attributeType=" + getAttributeType().toString() + ", moduleName=" + getSources() + ", context=" + context + ", valueInt=" + getValueInt() + ", valueLong=" + getValueLong() + ", valueDouble=" + getValueDouble() + ", valueString=" + getValueString() + ", valueBytes=" + Arrays.toString(getValueBytes()) + ", Case=" + getSleuthkitCase() + '}'; //NON-NLS
+		return "BlackboardAttribute{" + "artifactID=" + getArtifactID() + ", attributeType=" + getAttributeType().toString() + ", moduleName=" + getSources() + ", context=" + context + ", valueInt=" + getValueInt() + ", valueLong=" + getValueLong() + ", valueDouble=" + getValueDouble() + ", valueString=" + getValueString() + ", valueBytes=" + Arrays.toString(getValueBytes()) + ", Case=" + getCaseDatabase() + '}'; //NON-NLS
 	}
 
 	/**
@@ -352,7 +349,7 @@ public String getDisplayString() {
 						BlackboardArtifact parent = getParentArtifact();
 						parentDataSourceID = parent.getDataSourceObjectID();
 					}
-					final Content dataSource = getSleuthkitCase().getContentById(parentDataSourceID);
+					final Content dataSource = getCaseDatabase().getContentById(parentDataSourceID);
 					if ((dataSource != null) && (dataSource instanceof Image)) {
 						// return the date/time string in the timezone associated with the datasource,
 						Image image = (Image) dataSource;