From b1aec3703fbfc006e142312ad115533f34debec2 Mon Sep 17 00:00:00 2001 From: norareidy Date: Thu, 30 May 2024 12:29:39 -0400 Subject: [PATCH 1/5] DOCSP-18711: Explain BsonRepresentation limitation --- .../data-formats/pojo-customization.txt | 57 ++++++++++++++++++- .../fundamentals/code-snippets/LongCodec.java | 27 +++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 source/includes/fundamentals/code-snippets/LongCodec.java diff --git a/source/fundamentals/data-formats/pojo-customization.txt b/source/fundamentals/data-formats/pojo-customization.txt index 7cfe25cc8..988f33693 100644 --- a/source/fundamentals/data-formats/pojo-customization.txt +++ b/source/fundamentals/data-formats/pojo-customization.txt @@ -287,6 +287,10 @@ package: - Specifies the BSON type used to store the value when different from the POJO property. + .. seealso:: + + :ref:`BsonRepresentation Annotation Example ` + * - ``BsonId`` - Marks a property to serialize as the _id property. @@ -441,6 +445,58 @@ following data: additionalInfo=Document{{dimensions=3x4x5, weight=256g}} ] +.. _bsonrepresentation-annotation-code-example: + +BsonRepresentation Error Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``@BsonRepresentation`` annotation allows you to store a POJO class field +as a different data type in your MongoDB database. The :ref:`Product POJO +` code example in the :ref:`annotations` section +of this page uses ``@BsonRepresentation`` to store ``serialNumber`` values as +``ObjectId`` values in the database. + +However, using the ``@BsonRepresentation`` annotation to convert between data types other +than ``String`` and ``ObjectId`` causes the following error message: + +.. code-block:: + :copyable: false + + Codec must implement RepresentationConfigurable to support BsonRepresentation + +For example, the following code adds a ``purchaseDate`` field of type ``Long`` to the +``Product`` POJO. This example attempts to represent ``Long`` values as ``DateTime`` +values in the database: + +.. code-block:: java + + public class Product { + @BsonProperty("modelName") + private String name; + + @BsonId() + @BsonRepresentation(BsonType.OBJECT_ID) + private String serialNumber; + + @BsonRepresentation(BsonType.DATE_TIME) + private Long purchaseDate; + + // ... + } + +The preceding code results in an error. Instead, you can create a custom Codec to +convert the ``purchaseDate`` values from type ``Long`` to ``DateTime``: + +.. literalinclude:: /includes/fundamentals/code-snippets/LongCodec.java + :language: java + :start-after: start class + :end-before: end class + +Then, you can add an instance of the ``LongCodec`` to your ``CodecRegistry``, which contains +a mapping between your Codec and the Java object type to which it applies. For instructions +on registering your custom Codec with the ``CodecRegistry``, see the :ref:`fundamentals-codecs` +guide. + .. _pojo-discriminators: Discriminators @@ -699,4 +755,3 @@ codec registry. See the documentation on the :ref:`default codec registry ` For more information about how to register the codecs it includes. - diff --git a/source/includes/fundamentals/code-snippets/LongCodec.java b/source/includes/fundamentals/code-snippets/LongCodec.java new file mode 100644 index 000000000..ddd7dd88e --- /dev/null +++ b/source/includes/fundamentals/code-snippets/LongCodec.java @@ -0,0 +1,27 @@ +import org.bson.BsonReader; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; + +// start class +public class LongCodec implements Codec { + + @Override + public Long decode(BsonReader reader, DecoderContext decoderContext) { + return reader.readDateTime(); + } + + @Override + public void encode(BsonWriter writer, Long value, EncoderContext encoderContext) { + if (value != null) { + writer.writeDateTime(value); + } + } + + @Override + public Class getEncoderClass() { + return Long.class; + } +} +// end class From 2179d31840e9e1de21aedd5edfe316a8e5a82f16 Mon Sep 17 00:00:00 2001 From: norareidy Date: Thu, 30 May 2024 17:04:12 -0400 Subject: [PATCH 2/5] edits --- .../data-formats/pojo-customization.txt | 7 +++--- .../fundamentals/code-snippets/LongCodec.java | 24 ++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/source/fundamentals/data-formats/pojo-customization.txt b/source/fundamentals/data-formats/pojo-customization.txt index 988f33693..34628afc7 100644 --- a/source/fundamentals/data-formats/pojo-customization.txt +++ b/source/fundamentals/data-formats/pojo-customization.txt @@ -289,7 +289,7 @@ package: .. seealso:: - :ref:`BsonRepresentation Annotation Example ` + :ref:`bsonrepresentation-annotation-code-example` * - ``BsonId`` - Marks a property to serialize as the _id property. @@ -453,8 +453,8 @@ BsonRepresentation Error Example The ``@BsonRepresentation`` annotation allows you to store a POJO class field as a different data type in your MongoDB database. The :ref:`Product POJO ` code example in the :ref:`annotations` section -of this page uses ``@BsonRepresentation`` to store ``serialNumber`` values as -``ObjectId`` values in the database. +of this page uses ``@BsonRepresentation`` to store ``String`` values as +``ObjectId`` values in the database documents. However, using the ``@BsonRepresentation`` annotation to convert between data types other than ``String`` and ``ObjectId`` causes the following error message: @@ -469,6 +469,7 @@ For example, the following code adds a ``purchaseDate`` field of type ``Long`` t values in the database: .. code-block:: java + :emphasize-lines: 9-10 public class Product { @BsonProperty("modelName") diff --git a/source/includes/fundamentals/code-snippets/LongCodec.java b/source/includes/fundamentals/code-snippets/LongCodec.java index ddd7dd88e..93ec45121 100644 --- a/source/includes/fundamentals/code-snippets/LongCodec.java +++ b/source/includes/fundamentals/code-snippets/LongCodec.java @@ -1,3 +1,5 @@ +package fundamentals; + import org.bson.BsonReader; import org.bson.BsonWriter; import org.bson.codecs.Codec; @@ -8,20 +10,20 @@ public class LongCodec implements Codec { @Override - public Long decode(BsonReader reader, DecoderContext decoderContext) { - return reader.readDateTime(); - } - - @Override - public void encode(BsonWriter writer, Long value, EncoderContext encoderContext) { + public void encode(BsonWriter writer, Long value, EncoderContext encoderContext) { if (value != null) { writer.writeDateTime(value); } - } + } - @Override - public Class getEncoderClass() { - return Long.class; - } + @Override + public Long decode(BsonReader reader, DecoderContext decoderContext) { + return reader.readDateTime(); + } + + @Override + public Class getEncoderClass() { + return Long.class; + } } // end class From dc016bb2b26b703670c6b1fd6073f0d398cdae17 Mon Sep 17 00:00:00 2001 From: norareidy Date: Mon, 3 Jun 2024 10:03:04 -0400 Subject: [PATCH 3/5] JS feedback --- source/fundamentals/data-formats/pojo-customization.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/fundamentals/data-formats/pojo-customization.txt b/source/fundamentals/data-formats/pojo-customization.txt index 34628afc7..93f0f3410 100644 --- a/source/fundamentals/data-formats/pojo-customization.txt +++ b/source/fundamentals/data-formats/pojo-customization.txt @@ -465,8 +465,8 @@ than ``String`` and ``ObjectId`` causes the following error message: Codec must implement RepresentationConfigurable to support BsonRepresentation For example, the following code adds a ``purchaseDate`` field of type ``Long`` to the -``Product`` POJO. This example attempts to represent ``Long`` values as ``DateTime`` -values in the database: +``Product`` POJO. This example attempts to use ``@BsonRepresentation`` to represent ``Long`` +values as ``DateTime`` values in the database: .. code-block:: java :emphasize-lines: 9-10 @@ -493,7 +493,7 @@ convert the ``purchaseDate`` values from type ``Long`` to ``DateTime``: :start-after: start class :end-before: end class -Then, you can add an instance of the ``LongCodec`` to your ``CodecRegistry``, which contains +Then, add an instance of the ``LongCodec`` to your ``CodecRegistry``, which contains a mapping between your Codec and the Java object type to which it applies. For instructions on registering your custom Codec with the ``CodecRegistry``, see the :ref:`fundamentals-codecs` guide. From 454668d4c7334c6bcc66182829e64d5a72125c3e Mon Sep 17 00:00:00 2001 From: norareidy Date: Fri, 21 Jun 2024 13:24:45 -0400 Subject: [PATCH 4/5] tech review --- .../data-formats/pojo-customization.txt | 4 +- .../fundamentals/code-snippets/LongCodec.java | 29 -------- .../code-snippets/LongRepresentableCodec.java | 74 +++++++++++++++++++ 3 files changed, 76 insertions(+), 31 deletions(-) delete mode 100644 source/includes/fundamentals/code-snippets/LongCodec.java create mode 100644 source/includes/fundamentals/code-snippets/LongRepresentableCodec.java diff --git a/source/fundamentals/data-formats/pojo-customization.txt b/source/fundamentals/data-formats/pojo-customization.txt index 93f0f3410..3011dbeba 100644 --- a/source/fundamentals/data-formats/pojo-customization.txt +++ b/source/fundamentals/data-formats/pojo-customization.txt @@ -488,12 +488,12 @@ values as ``DateTime`` values in the database: The preceding code results in an error. Instead, you can create a custom Codec to convert the ``purchaseDate`` values from type ``Long`` to ``DateTime``: -.. literalinclude:: /includes/fundamentals/code-snippets/LongCodec.java +.. literalinclude:: /includes/fundamentals/code-snippets/LongRepresentableCodec.java :language: java :start-after: start class :end-before: end class -Then, add an instance of the ``LongCodec`` to your ``CodecRegistry``, which contains +Then, add an instance of the ``LongRepresentableCodec`` to your ``CodecRegistry``, which contains a mapping between your Codec and the Java object type to which it applies. For instructions on registering your custom Codec with the ``CodecRegistry``, see the :ref:`fundamentals-codecs` guide. diff --git a/source/includes/fundamentals/code-snippets/LongCodec.java b/source/includes/fundamentals/code-snippets/LongCodec.java deleted file mode 100644 index 93ec45121..000000000 --- a/source/includes/fundamentals/code-snippets/LongCodec.java +++ /dev/null @@ -1,29 +0,0 @@ -package fundamentals; - -import org.bson.BsonReader; -import org.bson.BsonWriter; -import org.bson.codecs.Codec; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.EncoderContext; - -// start class -public class LongCodec implements Codec { - - @Override - public void encode(BsonWriter writer, Long value, EncoderContext encoderContext) { - if (value != null) { - writer.writeDateTime(value); - } - } - - @Override - public Long decode(BsonReader reader, DecoderContext decoderContext) { - return reader.readDateTime(); - } - - @Override - public Class getEncoderClass() { - return Long.class; - } -} -// end class diff --git a/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java b/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java new file mode 100644 index 000000000..61446a723 --- /dev/null +++ b/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java @@ -0,0 +1,74 @@ +package fundamentals; + +import org.bson.BsonInvalidOperationException; +import org.bson.BsonReader; +import org.bson.BsonType; +import org.bson.BsonWriter; +import org.bson.codecs.Codec; +import org.bson.codecs.DecoderContext; +import org.bson.codecs.EncoderContext; +import org.bson.codecs.RepresentationConfigurable; +import org.bson.codecs.configuration.CodecConfigurationException; + + +// start class +public class LongRepresentableCodec implements Codec, RepresentationConfigurable { + private final BsonType representation; + + /** + * Constructs a LongRepresentableCodec with a Int64 representation. + */ + public LongRepresentableCodec() { + representation = BsonType.INT64; + } + + private LongRepresentableCodec(final BsonType representation) { + this.representation = representation; + } + + @Override + public BsonType getRepresentation() { + return representation; + } + + @Override + public Codec withRepresentation(final BsonType representation) { + if (representation != BsonType.INT64 && representation != BsonType.DATE_TIME) { + throw new CodecConfigurationException(representation + " is not a supported representation for LongRepresentableCodec"); + } + return new LongRepresentableCodec(representation); + } + + + @Override + public void encode(final BsonWriter writer, final Long value, final EncoderContext encoderContext) { + switch (representation) { + case INT64: + writer.writeInt64(value); + break; + case DATE_TIME: + writer.writeDateTime(value); + break; + default: + throw new BsonInvalidOperationException("Cannot encode a Long to a " + representation); + } + } + + @Override + public Long decode(final BsonReader reader, final DecoderContext decoderContext) { + switch (representation) { + case INT64: + return reader.readInt64(); + case DATE_TIME: + return reader.readDateTime(); + default: + throw new CodecConfigurationException("Cannot decode " + representation + " to a Long"); + } + } + + @Override + public Class getEncoderClass() { + return Long.class; + } +} +// end class \ No newline at end of file From da7938e73a378fae7bae1a961369db1bce9007dd Mon Sep 17 00:00:00 2001 From: norareidy Date: Fri, 21 Jun 2024 13:30:06 -0400 Subject: [PATCH 5/5] reduce scroll --- .../code-snippets/LongRepresentableCodec.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java b/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java index 61446a723..51bc2cea9 100644 --- a/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java +++ b/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java @@ -34,7 +34,8 @@ public BsonType getRepresentation() { @Override public Codec withRepresentation(final BsonType representation) { if (representation != BsonType.INT64 && representation != BsonType.DATE_TIME) { - throw new CodecConfigurationException(representation + " is not a supported representation for LongRepresentableCodec"); + throw new CodecConfigurationException(representation + + " is not a supported representation for LongRepresentableCodec"); } return new LongRepresentableCodec(representation); } @@ -50,7 +51,8 @@ public void encode(final BsonWriter writer, final Long value, final EncoderConte writer.writeDateTime(value); break; default: - throw new BsonInvalidOperationException("Cannot encode a Long to a " + representation); + throw new BsonInvalidOperationException("Cannot encode a Long to a " + + representation); } } @@ -62,7 +64,8 @@ public Long decode(final BsonReader reader, final DecoderContext decoderContext) case DATE_TIME: return reader.readDateTime(); default: - throw new CodecConfigurationException("Cannot decode " + representation + " to a Long"); + throw new CodecConfigurationException("Cannot decode " + representation + + " to a Long"); } }