Learn how to create and work with session data. Expand on this knowledge by using the sessionCache feature to persist session data between servers.
You’ll learn how to set and get session data, about session and session persistence theory, and create an application that will persist a user’s shopping cart data. You will run this application on two servers accessing the same session cache. This guide uses the MicroProfile OpenAPI as a UI for interacting with the servers.
A session is a way to store information to be used across multiple pages.
When you work with a local application (such as a word processor), you open it, make changes, and then you close it. The computer knows that you opened the app, made changes, and closed the app. On the internet, however, the web server does not know who you are, or what you do, because it is just processing stateless HTTP requests.
Session variables store user information like usernames, items in a cart, etc.
By default, session variables will timeout after 30 minutes of being unused.
Session variables are maintained on a web server. Cookies, which also store user
information, are maintained on a clients computer.
The primary use case of session persistence is to be able to handle client requests
being routed to different backends or to handle failover of the backend system.
High traffic websites must support thousands of users in a fast and reliable way. Load balancing requires running several instances of the same service in parallel so that traffic can be routed to servers to maximize speed and reliability.
This poses a problem when each server keeps an isolated copy of their session data. In this case, a user is tied to a particular server, and if that server crashes then that server’s session data will be lost.
Session persistence using a session cache, as illustrated above, solves this
problem by allowing all server instances to share caches amongst each other. This
eliminates the need to always route a user to the same server instance, and also
helps in failover situations by distributing the cache.
The finish directory in the root of this guide contains the finished application.
Give it a try before you proceed.
To try out the application, first navigate to the finish directory and then run
the following Maven goal to build the application and run it inside Open Liberty:
cd finish
mvn install
mvn liberty:start-server -DserverName=server1Point your browser to the http://localhost:9080/openapi/ui/ URL. This will
display the available REST endpoints on the server1 server.
First, make a POST request to /sessions/session/cart/{item}&{price}.
The POST request will add a user specified item and price to a session
that represents data in a user’s cart.
Then, make a GET request to /sessions/session/cart. The GET request
will return all the items from your session and display it as a string.
When you are ready to continue stop your server and navigate to the start directory.
mvn liberty:stop-server -DserverName=server1
cd ../startFor security reasons, using sessions is preferred over using cookies for
sensitive data. Sessions hide data from users. Cookies store data on the clients
computer, and can be manipulated by a savvy user to make fake requests to your site.
You will create an application to store and retrieve session data.
Create the SessionApplication class in the
src/main/java/io/openliberty/guides/sessions/SessionApplication.java file.
link:finish/src/main/java/io/openliberty/guides/sessions/SessionApplication.java[role=include]This class extends the generic JAX-RS application class needed to run the application.
Create the SessionResource class in the
src/main/java/io/openliberty/guides/sessions/SessionResource.java file:
link:finish/src/main/java/io/openliberty/guides/sessions/SessionResource.java[role=include]The SessionResource class defines the REST endpoints at which a user can make
a HTTP request.
The addToCart and getCart methods have a number of annotations most of which
are used by the myOpenAPI-1.0 and jaxrs-2.0 features to provide context to
the user interface and map java objects to web resources.
More information about these annotations can be found in the
Documenting RESTful APIs
and
Creating a RESTful web service
guides.
The @PathParam annotation injects a custom item and price from the POST
request into the method parameter.
The addToCart method gets the current session and sets a new attribute
stored as the key-value pair {item}:{price}. A response is then built and
returned to confirm that an item has been added to your cart/session.
The getCart method will get the current session. Iterate through all key-value
pairs stored in the current session and create a String response that is returned
to confirm the value of the item(s) in your cart/session.
The sessionCache-1.0 feature is only valuable when it is connected to at least
one other member. There are two different ways session caching can behave in a
server environment:
-
Client-Server Model: A Liberty server can act as the JCache client and connect to a dedicated JCache server.
-
Peer-to-Peer Model: A Liberty server can connect with other Liberty servers that are also running with the
sessionCache-1.0feature and configured to be part of the same cluster.
You will use the peer-to-peer model for this application.
JCache stands for Java Caching and is an interface to standardize distributed
caching on the Java platform. The sessionCache-1.0 feature makes use of JCache
which allows for session persistence by providing a common cache of session data
between servers.
The sessionCache-1.0 feature does not include a JCache implementation.
For this guide you will use Hazelcast as an open source JCache provider.
Hazelcast is a JCache provider. OpenLiberty needs to be configured to use
HazelCast once the sessionCache-1.0 feature is enabled.
Create the server.xml config in the src/main/liberty/config/server.xml file.
link:finish/src/main/liberty/config/server.xml[role=include]The library tag lets the server know where the Hazelcast implementation of
JCache is located by including a library reference. When the maven build is run
the hazelcast.jar file is downloaded as a dependency and then copied to the
predefined {shared.resource.dir} directory.
By default, all OpenLiberty servers running sessionCache, the SessionApplication
you have created, and Hazelcast will be connected using a peer-to-peer model.
You can limit the Hazelcast instances that have access to session data by making them join a cluster with the correct username/password. This is accomplished by creating a Hazelcast configuration file.
Create a new hazelcast-config.xml config in the
/src/main/liberty/config/hazelcast-config.xml file.
link:finish/src/main/liberty/config/hazelcast-config.xml[role=include]In the server.xml file a reference to the Hazelcast config file is made using
the httpSessionCache tag. When the maven build is run the hazelcast-config.xml
file is copied to the predefined {shared.resource.dir} directory.
There are more configuration settings you can explore in the Hazelcast Documentation.
To build the application, run the Maven install phase from the command line in the start directory:
mvn installThis command builds the application and creates a .war file in the target directory. It also
configures and installs Open Liberty into the target/liberty/wlp directory.
Next, run the Maven liberty:start-server goal for both servers:
mvn liberty:start-server -DserverName=server1
mvn liberty:start-server -DserverName=server2This goal starts an Open Liberty server instance. Your Maven pom.xml is already configured to start
the application in this server instance.
Create a SessionResourceTest class in the
/src/test/java/it/io/openliberty/guides/sessions/SessionResourceTest.java file:
link:finish/src/test/java/it/io/openliberty/guides/sessions/SessionResourceTest.java[role=include]The testEmptyCart test makes sure that the getCart endpoint returns
empty when you first start the application. Otherwise, additional tests may cause
errors if you are unable to access this endpoint or if data is already stored in
this session.
The testOneServer test first makes a POST request to the addToCart endpoint
and ensures that the expected response is returned. Then, it makes a GET request
to the getCart endpoint and ensures that the expected response is returned.
This test uses the same server.
The testTwoServers test makes the same checks as the previous test, but the
addToCart endpoint is on the server at port 9080, and the getCart endpoint
is on the server at port 9081.
Although REST endpoints are generally stateless, they are used for simplicity in
this guide. The testOneServer and testTwoServers tests use a cookie
to ensure that the same person’s session data is being used for the addToCart
and getCart requests.
Verify that the tests pass using the Maven verify goal:
mvn verifyIf the tests pass, you will see a similar output to the following:
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running it.io.openliberty.guides.sessions.SessionResourceTest
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 10.259 sec
Results :
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0You developed and tested a Java application using HTTP session caching and Open Liberty.