diff --git a/source/fundamentals/data-formats/pojo-customization.txt b/source/fundamentals/data-formats/pojo-customization.txt index 7cfe25cc8..3011dbeba 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-code-example` + * - ``BsonId`` - Marks a property to serialize as the _id property. @@ -441,6 +445,59 @@ 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 ``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: + +.. 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 use ``@BsonRepresentation`` to represent ``Long`` +values as ``DateTime`` values in the database: + +.. code-block:: java + :emphasize-lines: 9-10 + + 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/LongRepresentableCodec.java + :language: java + :start-after: start class + :end-before: end class + +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. + .. _pojo-discriminators: Discriminators @@ -699,4 +756,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/LongRepresentableCodec.java b/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java new file mode 100644 index 000000000..51bc2cea9 --- /dev/null +++ b/source/includes/fundamentals/code-snippets/LongRepresentableCodec.java @@ -0,0 +1,77 @@ +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