Browse Source

DATAMONGO-884 - Fix potential NullPointerException for lazy DBRefs.

We now initialize the proxy in case an Object-method is called that is overridden in the traget class. Removed the additional check for initialization and to-DBRef-methods as they're repeated in the target method.

Original pull requests: #152, #153.
1.4.x
Thomas Darimont 12 years ago committed by Oliver Gierke
parent
commit
791938f05d
  1. 17
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java
  2. 126
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java

17
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DefaultDbRefResolver.java

@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
*/
package org.springframework.data.mongodb.core.convert;
import static org.springframework.util.ReflectionUtils.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@ -39,7 +41,6 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; @@ -39,7 +41,6 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
import com.mongodb.DB;
@ -211,15 +212,6 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -211,15 +212,6 @@ public class DefaultDbRefResolver implements DbRefResolver {
*/
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (invocation.getMethod().equals(INITIALIZE_METHOD)) {
return ensureResolved();
}
if (invocation.getMethod().equals(TO_DBREF_METHOD)) {
return this.dbref;
}
return intercept(invocation.getThis(), invocation.getMethod(), invocation.getArguments(), null);
}
@ -238,7 +230,10 @@ public class DefaultDbRefResolver implements DbRefResolver { @@ -238,7 +230,10 @@ public class DefaultDbRefResolver implements DbRefResolver {
return this.dbref;
}
return ReflectionUtils.isObjectMethod(method) ? method.invoke(obj, args) : method.invoke(ensureResolved(), args);
Object target = isObjectMethod(method) && Object.class.equals(method.getDeclaringClass()) ? obj
: ensureResolved();
return method.invoke(target, args);
}
/**

126
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DbRefMappingMongoConverterUnitTests.java

@ -53,6 +53,7 @@ import com.mongodb.DBRef; @@ -53,6 +53,7 @@ import com.mongodb.DBRef;
* Unit tests dor {@link DbRefMappingMongoConverterUnitTests}.
*
* @author Oliver Gierke
* @author Thomas Darimont
*/
@RunWith(MockitoJUnitRunner.class)
public class DbRefMappingMongoConverterUnitTests {
@ -285,6 +286,62 @@ public class DbRefMappingMongoConverterUnitTests { @@ -285,6 +286,62 @@ public class DbRefMappingMongoConverterUnitTests {
assertThat(deserializedResult.dbRefToSerializableTarget.getValue(), is(value));
}
/**
* @see DATAMONGO-884
*/
@Test
public void lazyLoadingProxyForToStringObjectMethodOverridingDbref() {
String id = "42";
String value = "bubu";
MappingMongoConverter converterSpy = spy(converter);
doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any());
BasicDBObject dbo = new BasicDBObject();
WithObjectMethodOverrideLazyDbRefs lazyDbRefs = new WithObjectMethodOverrideLazyDbRefs();
lazyDbRefs.dbRefToToStringObjectMethodOverride = new ToStringObjectMethodOverrideLazyDbRefTarget(id, value);
converterSpy.write(lazyDbRefs, dbo);
WithObjectMethodOverrideLazyDbRefs result = converterSpy.read(WithObjectMethodOverrideLazyDbRefs.class, dbo);
assertThat(result.dbRefToToStringObjectMethodOverride, is(notNullValue()));
assertProxyIsResolved(result.dbRefToToStringObjectMethodOverride, false);
assertThat(result.dbRefToToStringObjectMethodOverride.toString(), is(id + ":" + value));
assertProxyIsResolved(result.dbRefToToStringObjectMethodOverride, true);
}
/**
* @see DATAMONGO-884
*/
@Test
public void lazyLoadingProxyForEqualsAndHashcodeObjectMethodOverridingDbref() {
String id = "42";
String value = "bubu";
MappingMongoConverter converterSpy = spy(converter);
doReturn(new BasicDBObject("_id", id).append("value", value)).when(converterSpy).readRef((DBRef) any());
BasicDBObject dbo = new BasicDBObject();
WithObjectMethodOverrideLazyDbRefs lazyDbRefs = new WithObjectMethodOverrideLazyDbRefs();
lazyDbRefs.dbRefEqualsAndHashcodeObjectMethodOverride1 = new EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget(
id, value);
lazyDbRefs.dbRefEqualsAndHashcodeObjectMethodOverride2 = new EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget(
id, value);
converterSpy.write(lazyDbRefs, dbo);
WithObjectMethodOverrideLazyDbRefs result = converterSpy.read(WithObjectMethodOverrideLazyDbRefs.class, dbo);
assertProxyIsResolved(result.dbRefEqualsAndHashcodeObjectMethodOverride1, false);
assertThat(result.dbRefEqualsAndHashcodeObjectMethodOverride1, is(notNullValue()));
result.dbRefEqualsAndHashcodeObjectMethodOverride1.equals(null);
assertProxyIsResolved(result.dbRefEqualsAndHashcodeObjectMethodOverride1, true);
assertProxyIsResolved(result.dbRefEqualsAndHashcodeObjectMethodOverride2, false);
assertThat(result.dbRefEqualsAndHashcodeObjectMethodOverride2, is(notNullValue()));
result.dbRefEqualsAndHashcodeObjectMethodOverride2.hashCode();
assertProxyIsResolved(result.dbRefEqualsAndHashcodeObjectMethodOverride2, true);
}
private Object transport(Object result) {
return SerializationUtils.deserialize(SerializationUtils.serialize(result));
}
@ -391,4 +448,73 @@ public class DbRefMappingMongoConverterUnitTests { @@ -391,4 +448,73 @@ public class DbRefMappingMongoConverterUnitTests {
private static final long serialVersionUID = 1L;
}
static class ToStringObjectMethodOverrideLazyDbRefTarget extends LazyDbRefTarget {
private static final long serialVersionUID = 1L;
public ToStringObjectMethodOverrideLazyDbRefTarget() {}
public ToStringObjectMethodOverrideLazyDbRefTarget(String id, String value) {
super(id, value);
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.id + ":" + this.value;
}
}
static class EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget extends LazyDbRefTarget {
private static final long serialVersionUID = 1L;
public EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget() {}
public EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget(String id, String value) {
super(id, value);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget other = (EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
if (value == null) {
if (other.value != null)
return false;
} else if (!value.equals(other.value))
return false;
return true;
}
}
static class WithObjectMethodOverrideLazyDbRefs {
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) ToStringObjectMethodOverrideLazyDbRefTarget dbRefToToStringObjectMethodOverride;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget dbRefEqualsAndHashcodeObjectMethodOverride2;
@org.springframework.data.mongodb.core.mapping.DBRef(lazy = true) EqualsAndHashCodeObjectMethodOverrideLazyDbRefTarget dbRefEqualsAndHashcodeObjectMethodOverride1;
}
}

Loading…
Cancel
Save