diff --git a/bson/src/main/org/bson/codecs/pojo/ConventionAnnotationImpl.java b/bson/src/main/org/bson/codecs/pojo/ConventionAnnotationImpl.java index 1cde97945ab..f27e025cd2b 100644 --- a/bson/src/main/org/bson/codecs/pojo/ConventionAnnotationImpl.java +++ b/bson/src/main/org/bson/codecs/pojo/ConventionAnnotationImpl.java @@ -166,6 +166,12 @@ private void processCreatorAnnotation(final ClassModelBuilder classModelB PropertyModelBuilder propertyModelBuilder = null; if (isIdProperty) { + if (classModelBuilder.getIdPropertyName() == null) { + throw new CodecConfigurationException("A @BsonId annotation has been used with @BsonCreator " + + "but there is no known Id property.\n" + + "Please either use the @BsonProperty annotation in the creator or " + + "annotate the corresponding property in the class with the @BsonId."); + } propertyModelBuilder = classModelBuilder.getProperty(classModelBuilder.getIdPropertyName()); } else { BsonProperty bsonProperty = properties.get(i); diff --git a/bson/src/test/unit/org/bson/codecs/pojo/ConventionsTest.java b/bson/src/test/unit/org/bson/codecs/pojo/ConventionsTest.java index da7be914caa..d750d25f34e 100644 --- a/bson/src/test/unit/org/bson/codecs/pojo/ConventionsTest.java +++ b/bson/src/test/unit/org/bson/codecs/pojo/ConventionsTest.java @@ -29,6 +29,7 @@ import org.bson.codecs.pojo.entities.conventions.AnnotationWithObjectIdModel; import org.bson.codecs.pojo.entities.conventions.AnnotationWriteCollision; import org.bson.codecs.pojo.entities.conventions.BsonIgnoreDuplicatePropertyMultipleTypes; +import org.bson.codecs.pojo.entities.conventions.CreatorConstructorNoKnownIdModel; import org.bson.codecs.pojo.entities.conventions.CreatorInvalidConstructorModel; import org.bson.codecs.pojo.entities.conventions.CreatorInvalidMethodModel; import org.bson.codecs.pojo.entities.conventions.CreatorInvalidMethodReturnTypeModel; @@ -226,6 +227,12 @@ public void testCreatorInvalidTypeMethodModel() { .conventions(singletonList(ANNOTATION_CONVENTION)).build(); } + @Test(expected = CodecConfigurationException.class) + public void testCreatorConstructorNoKnownIdModel() { + ClassModel.builder(CreatorConstructorNoKnownIdModel.class) + .conventions(singletonList(ANNOTATION_CONVENTION)).build(); + } + @Test(expected = CodecConfigurationException.class) public void testBsonIgnoreDuplicatePropertyMultipleTypesModel() { ClassModel.builder(BsonIgnoreDuplicatePropertyMultipleTypes.class) diff --git a/bson/src/test/unit/org/bson/codecs/pojo/entities/conventions/CreatorConstructorNoKnownIdModel.java b/bson/src/test/unit/org/bson/codecs/pojo/entities/conventions/CreatorConstructorNoKnownIdModel.java new file mode 100644 index 00000000000..2027aefd605 --- /dev/null +++ b/bson/src/test/unit/org/bson/codecs/pojo/entities/conventions/CreatorConstructorNoKnownIdModel.java @@ -0,0 +1,69 @@ +/* + * Copyright 2008-present MongoDB, Inc. + * + * 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.bson.codecs.pojo.entities.conventions; + +import org.bson.codecs.pojo.annotations.BsonCreator; +import org.bson.codecs.pojo.annotations.BsonId; +import org.bson.codecs.pojo.annotations.BsonProperty; + +import java.util.Objects; + +public class CreatorConstructorNoKnownIdModel { + private final String stringField; + private final long longField; + + @BsonCreator + public CreatorConstructorNoKnownIdModel( + @BsonId final String stringField, + @BsonProperty("longField") final long longField) { + this.stringField = stringField; + this.longField = longField; + } + + public String getStringField() { + return stringField; + } + + public long getLongField() { + return longField; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final CreatorConstructorNoKnownIdModel that = (CreatorConstructorNoKnownIdModel) o; + return longField == that.longField && Objects.equals(stringField, that.stringField); + } + + @Override + public int hashCode() { + return Objects.hash(stringField, longField); + } + + @Override + public String toString() { + return "CreatorConstructorNoKnownIdModel{" + + ", stringField='" + stringField + '\'' + + ", longField=" + longField + + '}'; + } +}