public class VariantFilter
extends java.lang.Object
The preferred way of instrumenting Variant experiments for host applications written on top of the Java Servlet API.
By using this filter, the application programmer can, in many cases, instrument experiments
with no to very little coding. The filter intercepts HTTP requests for the instrumented
pages, obtains the resolved variant and, if non-control, forwards the request to the path
contained in the resolved state parameter path
.
The application programmer should use this filter if the following assumptions hold:
path
state parameter, so that 1) its base value
denotes the resource path to the this state's control; and 2) its variant value denotes the
resource path to the single point of entry of that state variant.
The filter is configured as following:
<filter>
<filter-name>variantFilter</filter-name>
<filter-class>com.variant.client.servlet.VariantFilter</filter-class>
<init-param>
<param-name>schemaResourceName</param-name>
<param-value>/path/to/schema.json</param-value>
</init-param>
<init-param>
<param-name>propsResourceName</param-name>
<param-value>/path/to/variant.props</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>variantFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The init(FilterConfig)
method looks for two initialization parameters:
schemaResourceName
: Name of the schema file as a classpath resource.
Parsed once during filter initialization. To change a schema, application restart will be required.
(Temporary limitaion to be removed in an upcoming version.)
propsResourceName
: Name of the application properties file as a
classpath resource. Its content will override default properties, but will be overridden
by /varaint.props
, if found on the classpath.
The URL pattern in filter mapping can be something narrower than /*
, of course, so long
as it matches all state path
s listed in the schema.
StateParsedHookListenerImpl
hook listener is registered prior to parsing of the schema,
which checks that each state defines the path
parameter and that its value starts with a
forward slash. If that is not the case, a parser error will be emitted by the listener.
It is assumed that the base path
state parameter, i.e. the one specified at the State
level, denotes the resource path to the control variation of this state. This allows this filter to
identify whether an incoming HTTP request is for an instrumented state or not. If not, the request
is forwarded down the filter chain by calling chain.doFilter(ServletRequest, ServletResponse)
.
If the requested path corresponds to an instrumented state, the session (obtained from
Variant client servlet adapter by calling ServletVariantClient#getOrCreateSession(HttpServletRequest)
)
is targeted for this state with ServletSession.targetForState(State)
. The resulting
ServletStateRequest
object contains information about the outcome of the targeting
operation, including the resulting variant and the resolved state parameters. This
ServletStateRequest
object is added to the current HttpServletRequest
as
an attribute named #VARIANT_REQUEST_ATTRIBUTE_NAME
, should the downstream application code
wish to extend the semantics, e.g. trigger a custom VariantEvent
.
The resolved variant's path
state parameter is interpreted as the request path to the resource which implements the targeted
variant. The request is forwarded to that path with ServletRequestDispatcher.forward()
.
Upon return from either forward or a fall-through down the filter chain, the
doFilter(ServletRequest, ServletResponse, FilterChain)
method below adds the status of the
HTTP response in progress to the pending state visited event and commits the Variant state request
in progress.
Any exceptions due to Variant are caught and logged. Should such an exception occur, an attempt is made to mark the state of the pending state visited event as failed and to allow the request proceed down the filter chain. In other words, should the instrumentation fail due to an internal Varaint exception, the user session will see the control experience.
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
VARIANT_REQUEST_ATTR_NAME |
Constructor and Description |
---|
VariantFilter() |
Modifier and Type | Method and Description |
---|---|
void |
destroy() |
void |
doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
Identify the state, target and commit the state request.
|
void |
init(FilterConfig config)
Initialize the Variant servlet adapter and parse the experiment schema.
|
protected void |
onSession(ServletRequest request,
ServletResponse response,
ServletSession ssn)
On session callback method.
|
protected void |
onStateRequest(ServletRequest request,
ServletResponse response,
ServletStateRequest stateRequest)
On session callback method.
|
public static final java.lang.String VARIANT_REQUEST_ATTR_NAME
protected void onSession(ServletRequest request, ServletResponse response, ServletSession ssn)
ssn
- The newly acquired Variant session object.protected void onStateRequest(ServletRequest request, ServletResponse response, ServletStateRequest stateRequest)
ssn
- The newly acquired Variant session object.public void init(FilterConfig config) throws ServletException
ServletException
Filter#init(FilterConfig)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException
java.io.IOException
ServletException
Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
public void destroy()
Filter#destroy()
Release 0.10.1. Updated 04 Sep 2019.
Copyright © 2019 Variant Inc.