Skip to content
Go to file

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Variant Logo

Variant Application Iteration Server Demo Application


This Variant Demo Application demonstrates instrumentation of two simple experience variations: an experiment (A/B test) and a concurrent feature flag in a Java servlet Web application. This demonstration will help you

  • Download, install and deploy Variant AIM Server on your local system;
  • Clone and deploy this demo application on your local system;
  • Step through the instrumented variations;
  • Examine the trace events prodiced by the two variations;
  • Understand the instrumentation details of the two variations.

Note, that this demo application is built on top the popular Pet Clinic webapp, available from the Sprinig MVC project. We are using it to demonstrate Variant's Java client as well as the servlet adapter for Variant Java client. If your application does not run in a servlet container, or in fact, is not even running on a Java virtual machine, much of this demonstration will still be applicable.

1. Start Variant Server

Download and install Variant AIM Server

∎ Start Variant Server

$ /path/to/server/bin/ start

If all went well, the server console output should look something like this:

[info] 15:38:18.475 c.v.s.b.ConfigLoader - Found  config resource [/variant.conf] as [/private/tmp/server/variant-server-0.10.0/conf/variant.conf]
[info] 15:38:20.275 c.v.s.s.SchemaDeployerFileSystem - Mounted schemata directory [/private/tmp/server/variant-server-0.10.0/schemata]
[info] 15:38:20.276 c.v.s.s.SchemaDeployerFileSystem - [432] No schemata found in [/private/tmp/server/variant-server-0.10.0/schemata]
[info] 15:38:20.278 c.v.s.b.VariantServerImpl - [433] Variant AIM Server release 0.10.0 bootstrapped on port [5377] in 3.063s

2. Deploy the Demo Appliction

∎ Clone This Repository

$ git clone

∎ Change Directory to variant-java-demo

$ cd variant-java-demo

∎ Copy the Variation Schema to the Server's schemata/ Directory:

$ cp petclinic.schema /path/to/server/schemata

If all went well, the server console output should look something like this:

[info] 15:43:20.279 c.v.s.s.SchemaDeployerFileSystem - [421] Deploying schema from file [/private/tmp/server/variant-server-0.10.0/schemata/petclinic.schema]
[info] 15:43:20.447 c.v.s.s.ServerFlusherService - Registered event flusher [com.variant.extapi.std.flush.TraceEventFlusherCsv] for schema [petclinic]
[info] 15:43:20.468 c.v.s.s.Schemata - [422] Deployed schema [petclinic] from file [petclinic.schema]
Name: petclinic
   Comment: Optional[Variant schema for the Pet Clinic demo application]
   States: 2
   Variations: 2

∎ Start the Demo Application:

% mvn tomcat7:run

If all went well, you will see the following at the bottom of the console output:

INFO: Starting Servlet Engine: Apache Tomcat/7.0.47
INFO  2019-07-01 15:53:12 VariantContext - Connected to Variant URL [variant://localhost:5377/petclinic]

The demo application is now accessible at http://localhost:9966/petclinic/.

∎ Optionally, Configure a Custom Variant Server URL

By default, the demo application looks for Variant server at the default URL http://localhost:5377. If your server is running elsewhere, you must update and restart the demo application.

3. Run the Demo

3.1 User Experiences

The demo consists of two variations:

The feature toggle VetsHourlyRateFeature exposes an early release of a the new feature, which adds the Hourly Rate column to the Veterinarians page below.

The experiment ScheduleVisitTest validates another new feature, designed to improve new appointment bookings by displaying new Availability column on the same same Veterinarians page.

Since the Veterinarians page is shared by both variations, it can have 4 variants:

VetsHourlyRate Feature ScheduleVisitTest
  Control With Availability Column
Control Existing code path. With availability column. (Proper state variant).
With Hourly Rate Column With hourly rate column. (Proper state variant). With both columns. (Hybrid state variant).

If a session is targeted for control experiences in both variations, it is served the existing Veterinarians page with two columns. If a session is targeted for a variant experience in either variation, and to control in the other, it sees either of the two proper variants of the Veterinarians page with one extra column. Finally, if a session is targeted for variant experiences in both variations, it is served the hybrid variant of the Veterinarians page with two extra columns.

Hybrid state variants are optional in Variant: unless explicitly configured in the schema, concurrent variations are treated as disjoint, i.e. Variant server will not target any sessions to variant experiences in both variations. However, in this demo, the more complex conjoint concurrency model is demonstrated. It supports hybrid state variants, when both variations are targeted to the variant experience. This is explained in detain in a subsequent section.

When you first navigate to the Veterinarians page, Variant server targets your session randomly in both variations. This targeting is durable, so reloading the page won't change it. If you want to make Variant to re-target, get a new private browser window or remove all variant-related cookies. (Note that some browsers share cookies between private windows, so be sure that there are no other private windows open.) You may also vary the probability weights by editing the petclinic.schema file in the server's schemata directory.

If your session happened to be targeted to the variant experience in the ScheduleVisitTest and you see the Schedule visit link, clicking it will navigate to the experimental version of the New Visitpage, containing the vet's name:

Control With Availability Column
Existing code path. With availability column.

3.2 Event Tracing

The variation schema for this demo does not specify a tracing event flusher, deferring to the default TraceEventFlusherServerLog, which appends trace events to the server loger file log/variant.log:

[info] 20:03:19.431 c.v.s.e.EventWriter$FlusherThread - Flushed 1 event(s) in 00:00:00.000
[info] 20:03:40.444 c.v.s.a.EventFlusherAppLogger - {event_name:'$STATE_VISIT', created_on:'1538967820228', session_id:'11BAEABC9F08B6F8', event_experiences:[{test_name:'ScheduleVisitTest', experience_name:'noLink', is_control:true}], event_attributes:[{key:'$STATE', value:'vets'}, {key:'HTTP_STATUS', value:'200'}, {key:'$STATUS', value:'Committed'}]}

The STATE-VISIT event is automatically triggered by Variant each time a user session visits an instrumented Web page. Note the delay between the time your session lands on an instrumented page and when the event is flushed to the log. This is due to the asynchronous nature of Variant's event writer. You can reduce the lag by changing the value of the event.writer.max.delay server configuration parameter in the conf/variant.conf file.

You can also configure a different trace event flusher to utilize a persistence mechanism of your choice.

Trace events provide the basis for analyzing variations. Features can be programmatically disabled if trace events indicate an unexpected failure, and experiments can be analyzed for target metrics and statistical significance.

4. Instrumentation

4.1 Instrumentaion Metadata

The variation schema used by this demo application can be found in this repository's petclinic.schema. The two states vets``newVisitcorrespond to the Veterinarians page and the New Visit page.

The VetsHourlyRateFeature variation is instrumented on the single Veterinarians page and has two experiences existing (control) and rateColumn with randomized weights 3:1 in favor of the variant.

The ScheduleVisitTest variation is instrumented on two pages, starting on the Veterinarians page and ending on the New Visit page. Note the conjointVariationsRefs specification, declaring the conjoint concurrence between the two variations. This specification tells Variant that ScheduleVisitTest and VetsHourlyReateFeature are conjointly concurrent, i.e. that it's okay for Variant server to target a session for these two variations completely independently. Note also the UserQualifyingHook lifecycle event hook which disqualifies blacklisted users from this feature. This demonstrates the power of the server-side ExtAPI, which enables such highly reusable components which operate on the operational data but are entirely outside of the host application's code base.

4.2 Instrumentation Code

Most of the instrumentation-related code is isolated in the class VariantContext. It is responsible for instantiating Variant client and a connection to the petclinic schema on Variant server. Additional instrumentation code is found in the respective controllers, e.g. the VetController class.

5. Implementation

The two experience are implemented on the JSP pages, e.g. the vetList.jsp.

Updated for 0.9.3 on 8 October 2018.


Variant Experience Server Demo Application (Java Server Stack)





No packages published