简体   繁体   中英

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?

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>

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM