Request and session scoped variables

To create a variable that can safely be accessed in the request or session scope, use the following two classes in the gw.api.web package:

  • RequestVar – Instantiate this class to create a request-scoped variable stored in the web request
  • SessionVar – Instantiate this class to create a session-scoped variable stored in the web session

These classes create a variable with a well-defined life cycle and attachment point of either the request or session. Use the set method to set the variable value. Use the get method to get the variable value.

In the base configuration, these classes do not work in the context of web service implementation or Gosu servlet classes. To enable web services and Gosu servlets as valid sources for variables in a RequestVar object, enable the ScopedVariableSupportedForAllCapturedRequests configuration parameter.

For both objects, Gosu provides a RequestAvailable property. Check the value of this boolean property to see if the RequestVar object has a request or the SessionVar object has a session available in this programming context. For example, if the code was called from a non-web unit test or a batch process, these properties return false. If RequestAvailable returns false, it is unsafe to call either get or set methods on the property. From Java, these properties appear as the isRequestAvailable method on each object.

Warning: Rule sets, plugin code, and other Gosu code can be invoked through various code contexts. You may not encounter contexts other than the user interface until late in system testing. When getting values RequestVar and SessionVar, always use RequestAvailable before trying to access the variable. Always handle the variable not being available or having a value of null.

The recommended pattern for concurrent use is to store the instance of the variable as a class variable declared with the static keyword. By using the static keyword on the class, many programming contexts can access the same session variable or request variable. Use the generics syntax SessionVar<TYPE> when you define the variable. For example, to store a String object, define the type as SessionVar<String>.

For example:

class MyClass {
  static var _varStoredInSession = new SessionVar<String>()

  static property get MySessionVar() : String {
    if (_varStoredInSession.RequestAvailable) {
      return _varStoredInSession.get()
    } else {
      return null // ENSURE THE CALLER CHECKS FOR NULL
    }
  }

  static property set MySessionVar(value: String) {
    if (_varStoredInSession.RequestAvailable) {
      _varStoredInSession.set(value)
    } else {
      // decide what to do if the request is not available
    }
  }
}

In any other part of the application, you can write code that sets this property:

MyClass.MySessionVar = "hello"

In another part of the application, you can write code that gets this property:

print( MyClass.MySessionVar )

This example explicitly checks the RequestAvailable property. In business code, for example to support your batch processes, you must decide what to do if RequestAvailable returns false.

Using RequestVar and SessionVar is strongly recommended, rather than the Java thread local API java.lang.ThreadLocal<TYPE>. Because application servers pool their threads, using ThreadLocal increases the risk of data remaining forever as a memory leak, because the thread to which you attached it never terminates. Also, pooled threads can preserve stale data from a previous request, because the server thread pool reuses the thread for future requests. If you ever use a ThreadLocal, it is critical to be very careful to clean up all code with a try/finally block. Better practise is to convert that code to use RequestVar and SessionVar.

See also