Skip to content

Commit c06ff2f

Browse files
committed
DOCSP-18711: Explain BsonRepresentation limitation (#549)
* DOCSP-18711: Explain BsonRepresentation limitation * edits * JS feedback * tech review * reduce scroll (cherry picked from commit c4dca6a)
1 parent 657cfd2 commit c06ff2f

File tree

2 files changed

+134
-1
lines changed

2 files changed

+134
-1
lines changed

source/fundamentals/data-formats/pojo-customization.txt

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ package:
287287
- Specifies the BSON type used to store the value when different from the
288288
POJO property.
289289

290+
.. seealso::
291+
292+
:ref:`bsonrepresentation-annotation-code-example`
293+
290294
* - ``BsonId``
291295
- Marks a property to serialize as the _id property.
292296

@@ -441,6 +445,59 @@ following data:
441445
additionalInfo=Document{{dimensions=3x4x5, weight=256g}}
442446
]
443447

448+
.. _bsonrepresentation-annotation-code-example:
449+
450+
BsonRepresentation Error Example
451+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
452+
453+
The ``@BsonRepresentation`` annotation allows you to store a POJO class field
454+
as a different data type in your MongoDB database. The :ref:`Product POJO
455+
<bson-annotation-code-example>` code example in the :ref:`annotations` section
456+
of this page uses ``@BsonRepresentation`` to store ``String`` values as
457+
``ObjectId`` values in the database documents.
458+
459+
However, using the ``@BsonRepresentation`` annotation to convert between data types other
460+
than ``String`` and ``ObjectId`` causes the following error message:
461+
462+
.. code-block::
463+
:copyable: false
464+
465+
Codec must implement RepresentationConfigurable to support BsonRepresentation
466+
467+
For example, the following code adds a ``purchaseDate`` field of type ``Long`` to the
468+
``Product`` POJO. This example attempts to use ``@BsonRepresentation`` to represent ``Long``
469+
values as ``DateTime`` values in the database:
470+
471+
.. code-block:: java
472+
:emphasize-lines: 9-10
473+
474+
public class Product {
475+
@BsonProperty("modelName")
476+
private String name;
477+
478+
@BsonId()
479+
@BsonRepresentation(BsonType.OBJECT_ID)
480+
private String serialNumber;
481+
482+
@BsonRepresentation(BsonType.DATE_TIME)
483+
private Long purchaseDate;
484+
485+
// ...
486+
}
487+
488+
The preceding code results in an error. Instead, you can create a custom Codec to
489+
convert the ``purchaseDate`` values from type ``Long`` to ``DateTime``:
490+
491+
.. literalinclude:: /includes/fundamentals/code-snippets/LongRepresentableCodec.java
492+
:language: java
493+
:start-after: start class
494+
:end-before: end class
495+
496+
Then, add an instance of the ``LongRepresentableCodec`` to your ``CodecRegistry``, which contains
497+
a mapping between your Codec and the Java object type to which it applies. For instructions
498+
on registering your custom Codec with the ``CodecRegistry``, see the :ref:`fundamentals-codecs`
499+
guide.
500+
444501
.. _pojo-discriminators:
445502

446503
Discriminators
@@ -699,4 +756,3 @@ codec registry.
699756

700757
See the documentation on the :ref:`default codec registry <codecs-default-codec-registry>`
701758
For more information about how to register the codecs it includes.
702-
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package fundamentals;
2+
3+
import org.bson.BsonInvalidOperationException;
4+
import org.bson.BsonReader;
5+
import org.bson.BsonType;
6+
import org.bson.BsonWriter;
7+
import org.bson.codecs.Codec;
8+
import org.bson.codecs.DecoderContext;
9+
import org.bson.codecs.EncoderContext;
10+
import org.bson.codecs.RepresentationConfigurable;
11+
import org.bson.codecs.configuration.CodecConfigurationException;
12+
13+
14+
// start class
15+
public class LongRepresentableCodec implements Codec<Long>, RepresentationConfigurable<Long> {
16+
private final BsonType representation;
17+
18+
/**
19+
* Constructs a LongRepresentableCodec with a Int64 representation.
20+
*/
21+
public LongRepresentableCodec() {
22+
representation = BsonType.INT64;
23+
}
24+
25+
private LongRepresentableCodec(final BsonType representation) {
26+
this.representation = representation;
27+
}
28+
29+
@Override
30+
public BsonType getRepresentation() {
31+
return representation;
32+
}
33+
34+
@Override
35+
public Codec<Long> withRepresentation(final BsonType representation) {
36+
if (representation != BsonType.INT64 && representation != BsonType.DATE_TIME) {
37+
throw new CodecConfigurationException(representation
38+
+ " is not a supported representation for LongRepresentableCodec");
39+
}
40+
return new LongRepresentableCodec(representation);
41+
}
42+
43+
44+
@Override
45+
public void encode(final BsonWriter writer, final Long value, final EncoderContext encoderContext) {
46+
switch (representation) {
47+
case INT64:
48+
writer.writeInt64(value);
49+
break;
50+
case DATE_TIME:
51+
writer.writeDateTime(value);
52+
break;
53+
default:
54+
throw new BsonInvalidOperationException("Cannot encode a Long to a "
55+
+ representation);
56+
}
57+
}
58+
59+
@Override
60+
public Long decode(final BsonReader reader, final DecoderContext decoderContext) {
61+
switch (representation) {
62+
case INT64:
63+
return reader.readInt64();
64+
case DATE_TIME:
65+
return reader.readDateTime();
66+
default:
67+
throw new CodecConfigurationException("Cannot decode " + representation
68+
+ " to a Long");
69+
}
70+
}
71+
72+
@Override
73+
public Class<Long> getEncoderClass() {
74+
return Long.class;
75+
}
76+
}
77+
// end class

0 commit comments

Comments
 (0)