Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-4001

Automatic / package based PojoCodecs require fields

    • Type: Icon: Improvement Improvement
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: POJO
    • Labels:

      The following check that classModels have properties may be false.

      if (automatic || (clazz.getPackage() != null && packages.contains(clazz.getPackage().getName()))) {
                  try {
                      classModel = createClassModel(clazz, conventions);
                      if (clazz.isInterface() || !classModel.getPropertyModels().isEmpty()) {
                          discriminatorLookup.addClassModel(classModel);
                          return new AutomaticPojoCodec<T>(new PojoCodecImpl<T>(classModel, registry, propertyCodecProviders,
                                  discriminatorLookup));
                      }
                  } catch (Exception e) {
                      LOGGER.warn(format("Cannot use '%s' with the PojoCodec.", clazz.getSimpleName()), e);
                      return null;
                  }
              }
      

      [1]: https://github.com/mongodb/mongo-java-driver/blob/r4.2.0/bson/src/main/org/bson/codecs/pojo/PojoCodecProvider.java#L82-L87

      This causes issues when fields (properties) use a base class.

      public abstract class AbstractBaseModel {
      }
      
      public class SettingModel extends AbstractBaseModel {
      
          @BsonId
          String id;
          SettingValueModel value;
      
          public SettingModel() {
          }
      
          public SettingModel(final String id, final SettingValueModel value) {
              this.id = id;
              this.value = value;
          }
      
          public String getId() {
              return id;
          }
      
          public SettingModel setId(final String id) {
              this.id = id;
              return this;
          }
      
          public SettingValueModel getValue() {
              return value;
          }
      
          public SettingModel setValue(final SettingValueModel value) {
              this.value = value;
              return this;
          }
      
          @Override
          public boolean equals(final Object o) {
              if (this == o) {
                  return true;
              }
              if (o == null || getClass() != o.getClass()) {
                  return false;
              }
              final SettingModel that = (SettingModel) o;
              return Objects.equals(id, that.id) && Objects.equals(value, that.value);
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(id, value);
          }
      }
      @BsonDiscriminator
      public class SettingValueModel extends AbstractBaseModel {
      
          public SettingValueModel() {
          }
      
      }
      
      @BsonDiscriminator("setting_value_sub_class_model")
      public class SettingValueSubClassModel extends SettingValueModel {
      
          @BsonProperty("integer_field")
          Integer intField;
      
          public SettingValueSubClassModel() {
          }
      
          public SettingValueSubClassModel(final Integer intField) {
              this.intField = intField;
          }
      
          public Integer getIntField() {
              return intField;
          }
      
          public SettingValueSubClassModel setIntField(final Integer intField) {
              this.intField = intField;
              return this;
          }
      
          @Override
          public boolean equals(final Object o) {
              if (this == o) {
                  return true;
              }
              if (o == null || getClass() != o.getClass()) {
                  return false;
              }
              final SettingValueSubClassModel that = (SettingValueSubClassModel) o;
              return Objects.equals(intField, that.intField);
          }
      
          @Override
          public int hashCode() {
              return Objects.hash(intField);
          }
      }
      
          @Test
          public void testAutomaticNoPropertiesField() {
              PojoCodecProvider pojoCodecProvider = PojoCodecProvider.builder().automatic(true).build();
              CodecRegistry codecRegistry = fromProviders(asList(new ValueCodecProvider(),
                      new BsonValueCodecProvider(),
                      pojoCodecProvider));
      
              Codec<SettingModel> codec = codecRegistry.get(SettingModel.class);
      
              SettingModel settingModel = new SettingModel("id", new SettingValueSubClassModel(1));
              RawBsonDocument rawBsonDocument = new RawBsonDocument(settingModel, codec);
              SettingModel decodedSettingsModel = rawBsonDocument.decode(codec);
      
              assertEquals(settingModel, decodedSettingsModel);
          }
      
      

            Assignee:
            Unassigned Unassigned
            Reporter:
            ross@mongodb.com Ross Lawley
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: