tarashypka tarashypka - 4 months ago 36
Java Question

Custom session Listener with Hazelcast session replication

I have Hazelcast configured for session replication:

<filter>
<filter-name>hazelcast-filter</filter-name>
<filter-class>com.hazelcast.web.WebFilter</filter-class>

<init-param>
<param-name>map-name</param-name>
<param-value>my-sessions</param-value>
</init-param>
<init-param>
<param-name>cookie-name</param-name>
<param-value>hazelcast.sessionId</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hazelcast-filter</filter-name>
<url-pattern>/</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<listener>
<listener-class>com.hazelcast.web.SessionListener</listener-class>
</listener>


In my web application user can make Order which persists in session until it's finished. In case Order was not finished and session was destroyed (user logged out or session expired), I want to backup all data that was processed by that order.

Without Hz session replication, I accomplish this with custom HttpSessionListener implementation like:

@Override
public void sessionDestroyed(HttpSessionEvent se) {
Order order = (Order) se.getSession().getAttribute("order");
if (order != null) {
// Backup all data processed by order
}
}


and it works fine, but with Hz I get 2 different sessions which are not synced:

switch (action) {
case "addOrderItems":
System.out.print("sesId=" + req.getSession().getId());
System.out.println("order=" + req.getSession().getAttribute("order"));


prints
sesId=HZDCDC1C77E7934E03A9FE329AAB7053B0 order=Order@6a5f7445


while

@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.print("sesId=" + se.getSession().getId());
System.out.println("order=" + se.getSession().getAttribute("order"));


prints
sesId=8748D170885C44B425FEEAA94AAB8A86 order=null
.

It seems that Hazelcast creates and destroys it's own session and I can't (or don't know how to) listen on this session events.

Is it possible to keep both sessions in sync or to implement your own Listener for Hz session?

Answer

Two steps should get you there

If you create a Hazelcast instance first, then you can pass the name of that as a parameter,

<init-param>
  <param-name>instance-name</param-name>
  <param-value>whatever</param-value>
</init-param>

so then session replication will use that pre-existing Hazelcast instance rather than spawn a new one.

When you create that instance, you can attach a listener to the session storage map in the normal way.

<map name="my-sessions">
  <entry-listeners>
    <entry-listener local="true" include-value="true">your.entry.Listener</entry-listener>
  </entry-listeners>
</map>