• 510.205.3525

  • hello at getvariant.com

Variant Java SDK

Release 1.3.1, May 2024

1. Overview

Variant Java client is a library which enables a host application written in a JVM language to communicate with the Variant CVM server. It exposes server’s functionality in terms of intuitive native Java classes which can be consumed by any host application, written in Java or any other JVM language. It requires Java runtime 8 or higher. Variant Java client makes no assumptions about the technology stack of the host application: it can be a web application running in a servlet container, or one with an embedded HTTP server like Netty or Akka, or a Kotlin program running on a mobile device.

2. Installation

Download the Variant Java client library: 

% curl -O https://s3.us-west-1.amazonaws.com/com.variant.pub/1.3.1/variant-java-client-1.3.1.jar

Place this JAR file where your host application’s build will find it. Typically, 3rd party jars are added to a company wide Maven repository, such as Artifactory, but you can also add it to your own build as an unmanaged dependency with a system scope.

Variant Java client has four external transitive dependencies, which you may have add to your build tool explicitly:

Group IDArtifact IDVersionComment
com.fasterxml.jackson.corejackson-core2.13 +JSON parser used for marshalling payloads to and from the server.
com.fasterxml.jackson.corejackson-databindDittoDitto
com.fasterxml.jackson.corejackson-annotationsDittoDitto
org.yamlsnakeyaml2.0+YAML parser used to parse experiment schemas.
Transitive dependencies

3. Developing with Variant Java Client

3.1. A Kickstart Example

□ Create a VariantClient instance with the factory build() method:

VariantClient client = VariantClient.build(
  builder -> {
    builder.withSessionIdTrackerClass(MyCustomSessionIdTracker.class);
  });

An implementation of the SessionIdTracker  must be provided. This custom class encapsulates the mechanism for tracking Variant session IDs by the host application — Variant’s only dependency on the host environment. Variant client comes bundled with the Client Standard Library with many pre-built session ID trackers for popular application environments.

You will only need one instance of VariantClient per address space.

□ Connect to an experiment schema on Variant server:

Connection connection =
  client.connectTo("http://myVariantServer.com:5377/myschema");

The host application should hold on to the connection object and reuse it for all user sessions interested in participating in code experiments contained in the given schema. Variant connections are stateless and can be reused even after a restart of the Variant server.

□ Obtain (or create) a Variant session. They are completely distinct from your host application’s sessions.

Session session = connection.getOrCreateSession(userData, Optional.of(appUserId));

The userData argument is an application dependency, as discussed in the next session. 

□ Obtain the experiment schema and the state.

Schema schema = session.getSchema();
State loginPage = schema.getState("loginPage")
  .orElseThrow
   System.out.println("State loginPage is not in the schema. Falling back to control.");
}

□ Target this session for the state and figure out the live experience(s) the session is targeted for.

ServletStateRequest request = session.targetForState(loginPage.get());
request.getLiveExperiences().forEach(e ->
   System.out.println(
      String.format(
         "We're targeted to experience %s in experiment %s",
         e.getName(),
         e.getExperiment().getName()));
);

At this point, the application can take the code path suitable for the combination of live experience it has been targeted for. Note, that the application does not have to know the names of the experiments or experiences to be targeted for a state. 

□ Commit or fail the state request

After the host application’s code path is complete, the state request must be committed or failed. This is the way the application code signals the downstream statistical analysis that a session encountered unrelated problem and should be excluded from analysis.

request.commit(userData);  // or .fail(userData)

Here again the userData argument is a deferred dependency and its meaning is explained in the next section. Committing (or failing) a state request triggers the associated state visited trace event with the corresponding completion status.

3.2. Variant Session ID Tracker

 Variant Java client makes no assumptions about host application’s technology stack or operational details. This generality enables broad applicability: any JVM host application can use it to access Variant server.

Variant maintains its own sessions, independent from those that may be maintained by the host application and regardless of whether the host application even supports the notion of a session. (E.g., many modern web applications are stateless and do not have sessions per se.) Variant server creates and maintains these sessions, but the client must provide a way of relating two consecutive state requests to the same session. Session ID tracker does exactly that. The session state is kept on Variant server, but the host application is responsible for holding on to the session ID between Variant state requests, by which this state can be retrieved.

To fulfill this responsibility, the application developer must supply an implementation of the SessionIdTracker  interface. By contract, an implementation must provide the constructor with the single parameter of type Object. Variant uses this constructor to instantiate an instance within the scope of Connection.getSession(Object) or Connection.getOrCreateSession(Object, Optional) methods by passing it (without interpretation) as the userData parameter.

The implementing class must be placed on the host application’s classpath and configured via the withTargetingTrackerClass() method .

3.3 The Structure of a Variant Session

A typical interaction between the host application and the Variant server goes through the following logic

3.4. Trace Events

Trace events can be triggered implicitly by Variant server or explicitly by client code. The only implicitly triggered trace event is the state visited event, which signifies that a user session visited a particular state. (Refer to the Server User Guide for details on how Variant models interactive applications.) State visited event is created implicitly by the Session.targetForState()  and is triggered implicitly by either the StateRequest.commit() or the StateRequest.fail() method. The host application can add custom event attributes to a pending state visited event. 

3.5 Concurrent API Calls

TBD

Index