Global context
Scripts in IBM® WebSphere® sMash run in the context of an HTTP request; the request zone, therefore, provides access to the HTTP request data. All of the information with which the application has been configured (including port numbers, directory locations and dependencies) is provided through the config zone. APIs for the global context are available for Java™, Groovy and PHP.
The zones
The global context forms a namespace rooted at /. WebSphere sMash provides a default set of zones that are identified by prefixes. As an example, the app zone is rooted at /app and the storage is rooted at /storage. The global context delegates the behavior of zones to classes known as zone handlers. Each zone handler handles a specific zone and provides different lifetime and scope behavior.
The location /config/zoneHandlers in the WebSphere sMash configuration contains a hash table that maps zone handlers to zone prefixes. WebSphere sMash provides a standard set of zones including config, request, event, tmp, app, user and storage.
The global context can be extended with additional zone handlers. As an example, a new zone memcache can be created which stores data in a memcached server. This zone can serve as a distributed cache. For more information about adding zone handlers, see the Extending the global context article.
Persistent zones are those that persist data and make it available across JVM restarts. Data is serialized and persisted to the file system or an external store. Non-persistent zones are those in which data is only held in memory. The following sections provide examples of persistent and non-persistent zones.
Non-persistent zones
Non-persistent zones are not serialized. When a particular URI is requested, for example "/tmp/table" , and it contains a hash table, a reference to the hash table is returned. All threads of an application accessing "/tmp/table" access the same object.
Any modifications done to the object by one thread are immediately visible to the other threads. The modifications to these zones do not cross a JVM boundary.
- Config zone
- Data in the
/configzone is loaded from configuration files. This data is globally visible and is available for the lifetime of the application. The config zone can be modified, however the changes are lost on JVM restart when the contents are reinitialized from configuration files. - Request zone
- Data in the
/requestzone is visible to the thread that is processing a request. For an HTTP or HTTPS request, this zone includes access to incoming data (request parameters, headers, cookies, POST body, input stream) and outgoing data (outgoing headers, outgoing cookies and output steam). The request zone is available from the time a request enters the system until the response is sent out. This zone is non-persistent. - Event zone
- Data in the
/eventzone is visible to the thread that is processing the event for the duration of that event. WebSphere sMash provides an event processing framework to enable loosely coupled components that publish and subscribe to these events. If an event is delivered to multiple event handlers, all the event handlers have access to the original event data from the event zone. This zone is non-persistent. - Tmp zone
- Data in the
/tmpzone is visible globally to all threads of an application. It provides a scratch pad area that the application can use to store any objects. This zone is non-persistent. - Connection zone
- Data in the
/connectionzone is visible to a thread only while it is processing a connection request made using theConnectionAPI. The/connectionzone is used in the implementation of connection handlers and protocol transports. Each connection request has a separate view of the/connectionzone. For more information, see Using the connection infrastructure. This zone is non-persistent.
Persistent zones
Persistent zones are serialized to the file system or an outside data store.
The location /config/zoneSerializers in the WebSphere sMash configuration contains a hash table that maps zone serializers to zone prefixes.
IBM sMash provides a Java and a Json serializer. The serialization behavior of a particular zone is controlled by modifying the /config/zoneSerializers hash table.
When a particular URI is requested, for example "/app/table" , a deep copy of the hash table is returned. All threads accessing "/app/table" access their own copy of the original object. Any modifications made to the object by one thread are visible to the other threads only after a zput ( is run by that thread.
"/app/table" , table)
- User zone
- Data in the
/userzone is visible to all threads of an HTTP session. HTTP session is identified by the value of the zsessionid cookie found on the request. The user zone is preserved across server recycles. The contents of this zone are serialized using Java serialization, therefore only objects that can be serialized should be placed in it.
An HTTP session is expired if it exceeds its invalidation timeout. The invalidation timeout is configured by setting/config/userZone/invalidationTimeoutin zero.config. The default invalidation timeout is 60 minutes. An HTTP session may also expire if it is unused for a period of time. The idle timeout is configured by setting/config/userZone/idleTimeoutin zero.config. The session is also invalidated after thezsessionidcookie expires. The invalidation timeout will never be less than the idle timeout. - App zone
- Data in the
/appzone is visible globally to all threads of an application. It provides a scratch pad area that the application can use to store objects that can be serialized. This zone is persistent across server recycles. - Storage zone
- Data in the
/storagezone is visible globally to all threads of an application. It provides a scratch pad area that the application can use to store json objects that can be serialized, including Lists, Maps, String, Double, Long and Boolean objects. If an integer is placed in the zone, it is converted to a Long after recycle/restart. Similarly, a Float is converted to Double, all Maps are converted to Hashmap and all Lists are converted to ArrayList. This zone is persistent across server recycles and restarts.
The choice of zone serializer is not always transparent to the user code. Java serialization is generic and therefore any object that is
serializable can be stored and retrieved. JSON serializer can only safely serialize JSON friendly data types as explained in
the preceding Storage zone section. As an example, the following code originally written to use the App zone using Java serializer works.
public class Customer implements Serializable{
private static final long serialVersionUID = 5260444438917831704L;
String name;
String address;
public Customer (String n, String a)
{ name = n; address=a;}
}
.
.
.
Customer c1 = new Customer ("Customer1", "Cary, NC");
zput ("/app/customer1", c1);
Customer c2 = zget("/app/customer1")
If the App zone is changed to use the Json serializer, it throws an UnSupportedDataTypeException exception during zput ("/app/customer1", c1). Java serialization is more generic and very well suited for Java. Json serialization is more portable and human readable. Choose the serialization that best fits your needs.
Accessing the global context
The global context is available from all parts of an application. The method of access depends on the language being used. Java API to the GlobalContext defines the access characteristics. Bindings are provided to this API through Groovy and PHP. The global context looks like a map with access through key-value pairs. You can get, put, list and delete different keys from the global context. For more information, see the Accessing the global context article.
Global context commands
Global context commands are special objects placed in the global context. These command expose a similar interface to that of the global context itself. An access on a key where a command is stored is delegated to the command itself. For more information, see the Global context commands article.
Concurrent access to the global context
Locking the global context
A locking mechanism is provided by the global context for persistent zones.
namely the /user, /app and /storage zones.
The lock and unlock functions are provided by a command stored at the root key in these zones
and their behavior is dictated by the zone implementation.
The default behavior for all the zones is for lock requests to be a blocking write; only one thread at a time may hold the lock.
All threads requesting a lock while the lock is held by another thread will block until the holding thread releases the lock via
an unlock call.
- Note that only a thread holding a lock may call
unlockfor that lock. - The locks for the persistent zones span not only threads but also processes and so work when using the parallel recycle mechanism.
- Applications should be written to explicitly unlock any locks that are taken, minimising the period of locking for performance reasons. However if due to an error or a bug in the application a lock is left in place then the zero runtime will remove the lock at the end of the request.
The lock and unlock functions provide a lock that operates on the entire zone
or specific URIs.
The following Groovy code example uses the lock for the /user zone:
// lock user zone
// zpost ("/user#lock", [URI to lock relative to user zone] )
zpost ("/user#lock", "/cnt") // This type of lock command is used to lock a specific URI
def cnt = zget ("/user/cnt", 0)
cnt++
zput ("/user/cnt", cnt)
// unlock zone
zpost ("/user#unlock", "/cnt")
// if cnt > 10 zone will be invalidated
if (cnt>10) {
zpost ("/user#invalidate", true)
}
Invalidating the global context
In addition to locking, the global context provides a command to allow invalidation of an entire zone.
The invalidate command clears the contents of the zone. A lock is automatically obtained by the calling thread
on the entire zone when invoking the invalidate command.
Locking is not supported by non-persistent zones
/tmp and /config)
Since the zones are in-memory, user code should use the appropriate locking functionality provided by
the programming language.
Extending the global context
The global context can be extended by creating new zones and providing new zone handlers for those zones, or providing new zone handlers for existing zones. For more information, see the Extending the global context article.