diff --git a/client/src/main/java/com/aerospike/client/sdk/Cluster.java b/client/src/main/java/com/aerospike/client/sdk/Cluster.java index 1e91593e..e52e9033 100644 --- a/client/src/main/java/com/aerospike/client/sdk/Cluster.java +++ b/client/src/main/java/com/aerospike/client/sdk/Cluster.java @@ -190,6 +190,27 @@ public Session createSession(Behavior behavior) { return new Session(this, behavior); } + /** + * Creates a new session of a custom type using the provided {@link SessionExtension}. + * + *
The extension is responsible for constructing the session subtype. The return type + * is inferred from the extension's type parameter, providing compile-time safety.
+ * + *Example:
+ *{@code
+ * MappingSession session = cluster.createSession(behavior, mappingExtension);
+ * }
+ *
+ * @param This is a convenience for {@code getCluster().createSession(behavior)}. + * The receiver is not modified.
+ * + *Subclasses (e.g. session types created via {@link SessionExtension}) should + * override this method to return the correct subtype.
+ * + * @param behavior the behavior configuration for the new session + * @return a new {@code Session} with the specified behavior + * @see Cluster#createSession(Behavior) + */ + public Session sessionFor(Behavior behavior) { + return cluster.createSession(behavior); + } + /** * Remove records in specified namespace/set efficiently. This method is many orders of magnitude * faster than deleting records one at a time. diff --git a/client/src/main/java/com/aerospike/client/sdk/SessionExtension.java b/client/src/main/java/com/aerospike/client/sdk/SessionExtension.java new file mode 100644 index 00000000..a631c425 --- /dev/null +++ b/client/src/main/java/com/aerospike/client/sdk/SessionExtension.java @@ -0,0 +1,42 @@ +package com.aerospike.client.sdk; + +import com.aerospike.client.sdk.policy.Behavior; + +/** + * Factory interface for creating custom {@link Session} subtypes. + * + *Implement this interface to define how a specific session subtype is constructed. + * The type parameter {@code S} ensures compile-time safety: the return type of + * {@link Cluster#createSession(Behavior, SessionExtension)} is inferred from the + * extension's {@code S}.
+ * + *Example usage (from an extension module):
+ *{@code
+ * public class MySessionExtension implements SessionExtension {
+ * @Override
+ * public MySession create(Cluster cluster, Behavior behavior) {
+ * return new MySession(cluster, behavior);
+ * }
+ * }
+ *
+ * MySession session = cluster.createSession(behavior, new MySessionExtension());
+ * }
+ *
+ * @param The implementation is responsible for constructing the session subtype, + * typically by calling {@link Session}'s protected constructor via a subclass.
+ * + * @param cluster the cluster this session will operate on + * @param behavior the behavior configuration for the session + * @return a new session instance of type {@code S} + */ + S create(Cluster cluster, Behavior behavior); +} diff --git a/client/src/test/java/com/aerospike/client/sdk/SessionExtensionTest.java b/client/src/test/java/com/aerospike/client/sdk/SessionExtensionTest.java new file mode 100644 index 00000000..0c680a4f --- /dev/null +++ b/client/src/test/java/com/aerospike/client/sdk/SessionExtensionTest.java @@ -0,0 +1,145 @@ +/* + * Copyright 2012-2026 Aerospike, Inc. + * + * Portions may be licensed to Aerospike, Inc. under one or more contributor + * license agreements WHICH ARE COMPATIBLE WITH THE APACHE LICENSE, VERSION 2.0. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.aerospike.client.sdk; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import com.aerospike.client.sdk.policy.Behavior; + +class SessionExtensionTest extends ClusterTest { + + static class CustomSession extends Session { + private final String label; + + protected CustomSession(Cluster cluster, Behavior behavior, String label) { + super(cluster, behavior); + this.label = label; + } + + String getLabel() { + return label; + } + } + + static class AnotherSession extends Session { + protected AnotherSession(Cluster cluster, Behavior behavior) { + super(cluster, behavior); + } + } + + static class CustomSessionExtension implements SessionExtension