0

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?

mr.tarsa
  • 6,386
  • 3
  • 25
  • 42

2 Answers2

1

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>
Neil Stevenson
  • 3,060
  • 9
  • 11
  • Ty for your help, it worked as you said. However, I didn't totally understood why I am supposed to create another Hz instance. It worked perfectly fine with default instance without specifying `init-param` for `instance-name`. I simply added `entry-listener` to `hazelcast-default.xml`. Will soon add another answer with concrete explanation of how it could be done. – mr.tarsa Jul 25 '16 at 23:46
0

As Neil Stevenson mentioned, Hazelcast instance should be preconfigured with EntryListener for my-sessions map. With filter for session replication as in my case, I added

<map name="my-sessions">
  <entry-listeners>
    <entry-listener local="true" include-value="true">path.to.NewOrderSessionListener</entry-listener>
    </entry-listeners>
</map>

to hazelcast.xml (which is located in the right place).

Implementation of EntryRemovedListener<String, SessionState> to listen for Hz session delete event will be like

public class NewOrderSessionListener implements EntryRemovedListener<String, SessionState> {
  @Override
  public void entryRemoved(EntryEvent<String, SessionState> event) {
    SessionState state = event.getOldValue();
    Map<String, Data> map = state.getAttributes();
    Data orderData = map.get("order");
    if (orderData != null) {
      // Backup all data processed by order
    }

Actually, Hazelcast provides a solution for any event.

mr.tarsa
  • 6,386
  • 3
  • 25
  • 42