Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DATAMONGO-1142 - Subclass Repository returns also Superclass objects. #266

Open
wants to merge 1 commit into
base: 3.4.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 the original author or authors.
* Copyright 2010-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -131,6 +131,7 @@
* @author Thomas Darimont
* @author Chuong Ngo
* @author Christoph Strobl
* @author Mateusz Rasiñski
*/
@SuppressWarnings("deprecation")
public class MongoTemplate implements MongoOperations, ApplicationContextAware {
Expand Down Expand Up @@ -1809,7 +1810,10 @@ private <T> List<T> executeFindMultiInternal(CollectionCallback<DBCursor> collec

while (cursor.hasNext()) {
DBObject object = cursor.next();
result.add(objectCallback.doWith(object));
T instantiatedObject = objectCallback.doWith(object);
if (instantiatedObject != null) {
result.add(instantiatedObject);
}
}

return result;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2014 by the original author(s).
* Copyright 2011-2015 by the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -74,6 +74,7 @@
* @author Patrik Wasik
* @author Thomas Darimont
* @author Christoph Strobl
* @author Mateusz Rasiñski
*/
public class MappingMongoConverter extends AbstractMongoConverter implements ApplicationContextAware, ValueResolver {

Expand Down Expand Up @@ -221,6 +222,10 @@ private <S extends Object> S read(TypeInformation<S> type, DBObject dbo, ObjectP
throw new MappingException(String.format(INCOMPATIBLE_TYPES, dbo, BasicDBList.class, typeToUse.getType(), path));
}

if (isTypeSubclassOfDbo(type.getType(), dbo)) {
return null;
}

// Retrieve persistent entity info
MongoPersistentEntity<S> persistentEntity = (MongoPersistentEntity<S>) mappingContext
.getPersistentEntity(typeToUse);
Expand All @@ -231,6 +236,22 @@ private <S extends Object> S read(TypeInformation<S> type, DBObject dbo, ObjectP
return read(persistentEntity, dbo, path);
}

private boolean isTypeSubclassOfDbo(Class<?> type, DBObject object) {
TypeInformation<?> typeInformation = typeMapper.readType(object);
if (typeInformation == null) {
return false;
}
Class<?> objectType = typeInformation.getType();
if (objectType == null) {
return false;
}
return isSubclass(type, objectType);
}

private boolean isSubclass(Class<?> testedClass, Class<?> possibleSuperclass) {
return !possibleSuperclass.equals(testedClass) && possibleSuperclass.isAssignableFrom(testedClass);
}

private ParameterValueProvider<MongoPersistentProperty> getParameterProvider(MongoPersistentEntity<?> entity,
DBObject source, DefaultSpELExpressionEvaluator evaluator, ObjectPath path) {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.repository;

import org.springframework.data.mongodb.core.mapping.Document;

/**
* Sample Candidate domain class extending {@link Person}.
* Candidate objects are stored in the {@link Person} collection.
*
* @author Mateusz Rasiñski
*/
@Document(collection = "person")
public class Candidate extends Person {

private String title;

public Candidate() {
}

public Candidate(String firstName, String lastName) {
super(firstName, lastName);
}

public Candidate(String firstName, String lastName, String title) {
super(firstName, lastName);
this.title = title;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.repository;

/**
* Simple repository interface managing {@link Candidate}s.
*
* @author Mateusz Rasiñski
*/
public interface CandidateRepository extends MongoRepository<Candidate, String> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.repository;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.util.List;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

/**
* Integration tests for {@link CandidateRepository}.
*
* @author Mateusz Rasiñski
*/
public class CandidateRepositoryIntegrationTests extends PersonRepositoryIntegrationTests {

@Autowired protected CandidateRepository candidateRepository;

/**
* @see DATAMONGO-1142
*/
@Test
public void personRepositoryCanSaveAndFindCandidate() {
Candidate candidate = repository.save(new Candidate("Jan", "Kowalski", "Mr."));

Person result = repository.findOne(candidate.getId());

assertThat(result, notNullValue());
assertThat(result, equalTo((Person) candidate));
assertThat(result, instanceOf(Candidate.class));
assertThat(((Candidate) result).getTitle(), is("Mr."));
}

/**
* @see DATAMONGO-1142
*/
@Test
public void personRepositoryReturnsAlsoCandidates() {
Candidate candidate = candidateRepository.save(new Candidate("Jan", "Kowalski"));

List<Person> persons = repository.findAll();

assertThat(persons, hasSize(greaterThan(1)));
assertThat(persons.contains(candidate), is(true));
}

/**
* @see DATAMONGO-1142
*/
@Test
public void candidateRepositoryReturnsOnlyCandidates() {
Candidate candidate = candidateRepository.save(new Candidate("Jan", "Kowalski"));

List<Candidate> candidates = candidateRepository.findAll();

assertThat(candidates, hasSize(1));
assertThat(candidates, contains(candidate));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<mongo:db-factory dbname="repositories" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg ref="mongoDbFactory" />
<property name="writeConcern">
Expand All @@ -28,4 +28,9 @@
</property>
</bean>

<bean class="org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean">
<property name="mongoOperations" ref="mongoTemplate"/>
<property name="repositoryInterface" value="org.springframework.data.mongodb.repository.CandidateRepository"/>
</bean>

</beans>