Skip to content

Commit ba1cf0b

Browse files
authored
Add Java record support to the default registry
Add dependency in core to bson-record-codec Wrap the RecordCodecProvider with a canary check so support is only added if the JDK version supports it. JAVA-3567
1 parent 3f9eb52 commit ba1cf0b

File tree

7 files changed

+123
-1
lines changed

7 files changed

+123
-1
lines changed

bson-record-codec/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ ext {
2424
dependencies {
2525
api project(path: ':bson', configuration: 'default')
2626
testImplementation project(':bson').sourceSets.test.output
27+
testImplementation project(':driver-core')
2728
}
2829

2930
afterEvaluate {

bson-record-codec/src/test/unit/org/bson/codecs/record/RecordCodecProviderTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.bson.codecs.record.samples.TestRecord;
2020
import org.bson.conversions.Bson;
21+
import com.mongodb.MongoClientSettings;
2122
import org.junit.jupiter.api.Test;
2223

2324
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -47,4 +48,15 @@ public void shouldReturnRecordCodecForRecord() {
4748
var recordCodec = (RecordCodec<TestRecord>) codec;
4849
assertEquals(TestRecord.class, recordCodec.getEncoderClass());
4950
}
51+
52+
@Test
53+
public void shouldReturnRecordCodecForRecordUsingDefaultRegistry() {
54+
// when
55+
var codec = MongoClientSettings.getDefaultCodecRegistry().get(TestRecord.class);
56+
57+
// then
58+
assertTrue(codec instanceof RecordCodec);
59+
var recordCodec = (RecordCodec<TestRecord>) codec;
60+
assertEquals(TestRecord.class, recordCodec.getEncoderClass());
61+
}
5062
}

driver-core/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ configurations {
3939

4040
dependencies {
4141
api project(path: ':bson', configuration: 'default')
42+
implementation project(path: ':bson-record-codec', configuration: 'default')
4243

4344
implementation "com.github.jnr:jnr-unixsocket:$jnrUnixsocketVersion", optional
4445
api "io.netty:netty-buffer:$nettyVersion", optional
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.mongodb;
17+
18+
import com.mongodb.internal.VisibleForTesting;
19+
import com.mongodb.lang.Nullable;
20+
import org.bson.codecs.Codec;
21+
import org.bson.codecs.configuration.CodecProvider;
22+
import org.bson.codecs.configuration.CodecRegistry;
23+
import org.bson.codecs.record.RecordCodecProvider;
24+
25+
import static com.mongodb.internal.VisibleForTesting.AccessModifier.PRIVATE;
26+
27+
28+
/**
29+
* A CodecProvider for Java Records.
30+
*
31+
* <p>Requires java.lang.Record support - eg Java 17 or greater.</p>
32+
*
33+
* @since 4.6
34+
*/
35+
public class Jep395RecordCodecProvider implements CodecProvider {
36+
37+
@Nullable
38+
private static final CodecProvider RECORD_CODEC_PROVIDER;
39+
static {
40+
41+
CodecProvider possibleCodecProvider;
42+
try {
43+
Class.forName("java.lang.Record"); // JEP-395 support canary test.
44+
possibleCodecProvider = new RecordCodecProvider();
45+
} catch (ClassNotFoundException e) {
46+
// No JEP-395 support
47+
possibleCodecProvider = null;
48+
}
49+
RECORD_CODEC_PROVIDER = possibleCodecProvider;
50+
}
51+
52+
@Override
53+
@Nullable
54+
public <T> Codec<T> get(final Class<T> clazz, final CodecRegistry registry) {
55+
return RECORD_CODEC_PROVIDER != null ? RECORD_CODEC_PROVIDER.get(clazz, registry) : null;
56+
}
57+
58+
@VisibleForTesting(otherwise = PRIVATE)
59+
public boolean hasRecordSupport() {
60+
return RECORD_CODEC_PROVIDER != null;
61+
}
62+
}
63+

driver-core/src/main/com/mongodb/MongoClientSettings.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ public final class MongoClientSettings {
7373
new Jsr310CodecProvider(),
7474
new JsonObjectCodecProvider(),
7575
new BsonCodecProvider(),
76-
new EnumCodecProvider()));
76+
new EnumCodecProvider(),
77+
new Jep395RecordCodecProvider()));
7778

7879
private final ReadPreference readPreference;
7980
private final WriteConcern writeConcern;
@@ -119,6 +120,7 @@ public final class MongoClientSettings {
119120
* <li>{@link org.bson.codecs.JsonObjectCodecProvider}</li>
120121
* <li>{@link org.bson.codecs.BsonCodecProvider}</li>
121122
* <li>{@link org.bson.codecs.EnumCodecProvider}</li>
123+
* <li>{@link com.mongodb.Jep395RecordCodecProvider}</li>
122124
* </ul>
123125
*
124126
* <p>
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.mongodb;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.api.condition.EnabledForJreRange;
20+
import org.junit.jupiter.api.condition.JRE;
21+
22+
import static org.junit.jupiter.api.Assertions.assertNull;
23+
import static org.junit.jupiter.api.Assertions.assertTrue;
24+
import static org.junit.jupiter.api.Assertions.fail;
25+
26+
public class Jep395RecordCodecProviderTest {
27+
28+
@Test
29+
@EnabledForJreRange(min = JRE.JAVA_17)
30+
void canSupportJavaRecordsOnJava17() {
31+
assertTrue(new Jep395RecordCodecProvider().hasRecordSupport());
32+
}
33+
34+
@Test
35+
void doesNotErrorWhenCheckingNonRecords() {
36+
try {
37+
assertNull(new Jep395RecordCodecProvider().get(Integer.class, MongoClientSettings.getDefaultCodecRegistry()));
38+
} catch (Exception e) {
39+
fail("Should return null when checking for class");
40+
}
41+
}
42+
}

driver-scala/src/test/scala/org/mongodb/scala/ApiAliasAndCompanionSpec.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class ApiAliasAndCompanionSpec extends BaseSpec {
5555
"DocumentToDBRefTransformer",
5656
"Function",
5757
"FutureResultCallback",
58+
"Jep395RecordCodecProvider",
5859
"KerberosSubjectProvider",
5960
"MongoClients",
6061
"NonNull",

0 commit comments

Comments
 (0)