ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a.@apache.org
Subject [31/50] [abbrv] ignite git commit: IGNITE-2765 WebSessionFilter doesn't survive client reconnect
Date Mon, 21 Mar 2016 14:20:56 GMT
IGNITE-2765
WebSessionFilter doesn't survive client reconnect


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3130872e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3130872e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3130872e

Branch: refs/heads/ignite-2801
Commit: 3130872ed3805250310f807ffe0b6e1c8e3e3a99
Parents: cb6da11
Author: Anton Vinogradov <av@apache.org>
Authored: Fri Mar 11 19:23:49 2016 +0300
Committer: Anton Vinogradov <av@apache.org>
Committed: Fri Mar 11 19:23:49 2016 +0300

----------------------------------------------------------------------
 .../config/websession/example-cache-base.xml    | 148 +++++++++++++++
 .../config/websession/example-cache-client.xml  |  33 ++++
 .../test/config/websession/example-cache.xml    | 128 +------------
 .../test/config/websession/example-cache2.xml   |  31 +++
 .../cache/websession/WebSessionFilter.java      | 188 ++++++++++++++-----
 .../cache/websession/WebSessionListener.java    |  60 +++---
 .../internal/websession/WebSessionSelfTest.java |  73 +++++++
 7 files changed, 453 insertions(+), 208 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/core/src/test/config/websession/example-cache-base.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/config/websession/example-cache-base.xml b/modules/core/src/test/config/websession/example-cache-base.xml
new file mode 100644
index 0000000..d3d5b46
--- /dev/null
+++ b/modules/core/src/test/config/websession/example-cache-base.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+    <bean abstract="true" id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <!-- Set to true to enable distributed class loading for examples, default is
false. -->
+        <property name="peerClassLoadingEnabled" value="true"/>
+
+        <property name="marshaller">
+            <bean class="org.apache.ignite.marshaller.optimized.OptimizedMarshaller">
+                <!-- Set to false to allow non-serializable objects in examples, default
is true. -->
+                <property name="requireSerializable" value="false"/>
+            </bean>
+        </property>
+
+        <!-- Enable cache events for examples. -->
+        <property name="includeEventTypes">
+            <util:constant static-field="org.apache.ignite.events.EventType.EVTS_CACHE"/>
+        </property>
+
+        <!-- Cache configurations (all properties are optional). -->
+        <property name="cacheConfiguration">
+            <list>
+                <!-- Partitioned cache example configuration (Atomic mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="partitioned"/>
+                    <property name="cacheMode" value="PARTITIONED"/>
+                    <property name="atomicityMode" value="ATOMIC"/>
+                    <property name="backups" value="1"/>
+
+                    <property name="indexedTypes">
+                        <list>
+                            <!-- Key and value type for SQL table Long. -->
+                            <value>java.lang.Integer</value>
+                            <value>java.lang.Long</value>
+                        </list>
+                    </property>
+                </bean>
+
+                <!-- Partitioned cache example configuration (Atomic mode, PRIMARY write
order mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="partitioned_primary"/>
+                    <property name="cacheMode" value="PARTITIONED"/>
+                    <property name="atomicityMode" value="ATOMIC"/>
+                    <property name="atomicWriteOrderMode" value="PRIMARY"/>
+                    <property name="backups" value="1"/>
+                </bean>
+
+                <!-- Partitioned cache example configuration (Transactional mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="partitioned_tx"/>
+                    <property name="cacheMode" value="PARTITIONED"/>
+                    <property name="atomicityMode" value="TRANSACTIONAL"/>
+                    <property name="nearConfiguration">
+                        <bean class="org.apache.ignite.configuration.NearCacheConfiguration"/>
+                    </property>
+                    <property name="backups" value="1"/>
+                </bean>
+
+                <!-- Replicated cache example configuration (Atomic mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="replicated"/>
+                    <property name="cacheMode" value="REPLICATED"/>
+                    <property name="atomicityMode" value="ATOMIC"/>
+                    <property name="indexedTypes">
+                        <list>
+                            <!-- Key and value type for SQL table DimStore. -->
+                            <value>java.lang.Integer</value>
+                            <value>java.lang.Integer</value>
+                        </list>
+                    </property>
+                </bean>
+
+                <!-- Replicated cache example configuration (Transactional mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="replicated_tx"/>
+                    <property name="cacheMode" value="REPLICATED"/>
+                    <property name="atomicityMode" value="TRANSACTIONAL"/>
+                </bean>
+
+                <!-- Local cache example configuration (Atomic mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="local"/>
+                    <property name="cacheMode" value="LOCAL"/>
+                    <property name="atomicityMode" value="ATOMIC"/>
+                </bean>
+
+                <!-- Local cache example configuration (Transactional mode). -->
+                <bean parent="cache-template">
+                    <property name="name" value="local_tx"/>
+                    <property name="cacheMode" value="LOCAL"/>
+                    <property name="atomicityMode" value="TRANSACTIONAL"/>
+                </bean>
+            </list>
+        </property>
+
+        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes.
-->
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <!-- In distributed environment, replace with actual host
IP address. -->
+                                <value>127.0.0.1:47500..47509</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+
+    <!-- Template for all example cache configurations. -->
+    <bean id="cache-template" abstract="true" class="org.apache.ignite.configuration.CacheConfiguration">
+        <!-- Initial cache size. -->
+        <property name="startSize" value="3000000"/>
+
+        <!-- Set synchronous rebalancing (default is asynchronous). -->
+        <property name="rebalanceMode" value="SYNC"/>
+
+        <!-- Set to FULL_SYNC for examples, default is PRIMARY_SYNC. -->
+        <property name="writeSynchronizationMode" value="FULL_SYNC"/>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/core/src/test/config/websession/example-cache-client.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/config/websession/example-cache-client.xml b/modules/core/src/test/config/websession/example-cache-client.xml
new file mode 100644
index 0000000..9272e14
--- /dev/null
+++ b/modules/core/src/test/config/websession/example-cache-client.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <!-- Imports Ignite configuration -->
+    <import resource="example-cache-base.xml"/>
+
+    <bean parent="ignite.cfg">
+        <property name="clientMode" value="true"/>
+
+        <property name="gridName" value="client"/>
+    </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/core/src/test/config/websession/example-cache.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/config/websession/example-cache.xml b/modules/core/src/test/config/websession/example-cache.xml
index 0cc0e1e..1090220 100644
--- a/modules/core/src/test/config/websession/example-cache.xml
+++ b/modules/core/src/test/config/websession/example-cache.xml
@@ -28,130 +28,12 @@
 -->
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:util="http://www.springframework.org/schema/util"
-       xsi:schemaLocation="
-        http://www.springframework.org/schema/beans
-        http://www.springframework.org/schema/beans/spring-beans.xsd
-        http://www.springframework.org/schema/util
-        http://www.springframework.org/schema/util/spring-util.xsd">
-    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
-        <!-- Set to true to enable distributed class loading for examples, default is
false. -->
-        <property name="peerClassLoadingEnabled" value="true"/>
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <!-- Imports Ignite configuration -->
+    <import resource="example-cache-base.xml"/>
 
-        <property name="marshaller">
-            <bean class="org.apache.ignite.marshaller.optimized.OptimizedMarshaller">
-                <!-- Set to false to allow non-serializable objects in examples, default
is true. -->
-                <property name="requireSerializable" value="false"/>
-            </bean>
-        </property>
-
-        <!-- Enable cache events for examples. -->
-        <property name="includeEventTypes">
-            <util:constant static-field="org.apache.ignite.events.EventType.EVTS_CACHE"/>
-        </property>
-
-        <!-- Cache configurations (all properties are optional). -->
-        <property name="cacheConfiguration">
-            <list>
-                <!-- Partitioned cache example configuration (Atomic mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="partitioned"/>
-                    <property name="cacheMode" value="PARTITIONED"/>
-                    <property name="atomicityMode" value="ATOMIC"/>
-                    <property name="backups" value="1"/>
-
-                    <property name="indexedTypes">
-                        <list>
-                            <!-- Key and value type for SQL table Long. -->
-                            <value>java.lang.Integer</value>
-                            <value>java.lang.Long</value>
-                        </list>
-                    </property>
-                </bean>
-
-                <!-- Partitioned cache example configuration (Atomic mode, PRIMARY write
order mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="partitioned_primary"/>
-                    <property name="cacheMode" value="PARTITIONED"/>
-                    <property name="atomicityMode" value="ATOMIC"/>
-                    <property name="atomicWriteOrderMode" value="PRIMARY"/>
-                    <property name="backups" value="1"/>
-                </bean>
-
-                <!-- Partitioned cache example configuration (Transactional mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="partitioned_tx"/>
-                    <property name="cacheMode" value="PARTITIONED"/>
-                    <property name="atomicityMode" value="TRANSACTIONAL"/>
-                    <property name="nearConfiguration">
-                        <bean class="org.apache.ignite.configuration.NearCacheConfiguration"/>
-                    </property>
-                    <property name="backups" value="1"/>
-                </bean>
-
-                <!-- Replicated cache example configuration (Atomic mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="replicated"/>
-                    <property name="cacheMode" value="REPLICATED"/>
-                    <property name="atomicityMode" value="ATOMIC"/>
-                    <property name="indexedTypes">
-                        <list>
-                            <!-- Key and value type for SQL table DimStore. -->
-                            <value>java.lang.Integer</value>
-                            <value>java.lang.Integer</value>
-                        </list>
-                    </property>
-                </bean>
-
-                <!-- Replicated cache example configuration (Transactional mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="replicated_tx"/>
-                    <property name="cacheMode" value="REPLICATED"/>
-                    <property name="atomicityMode" value="TRANSACTIONAL"/>
-                </bean>
-
-                <!-- Local cache example configuration (Atomic mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="local"/>
-                    <property name="cacheMode" value="LOCAL"/>
-                    <property name="atomicityMode" value="ATOMIC"/>
-                </bean>
-
-                <!-- Local cache example configuration (Transactional mode). -->
-                <bean parent="cache-template">
-                    <property name="name" value="local_tx"/>
-                    <property name="cacheMode" value="LOCAL"/>
-                    <property name="atomicityMode" value="TRANSACTIONAL"/>
-                </bean>
-            </list>
-        </property>
-
-        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes.
-->
-        <property name="discoverySpi">
-            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
-                <property name="ipFinder">
-                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
-                        <property name="addresses">
-                            <list>
-                                <!-- In distributed environment, replace with actual host
IP address. -->
-                                <value>127.0.0.1:47500..47509</value>
-                            </list>
-                        </property>
-                    </bean>
-                </property>
-            </bean>
-        </property>
+    <bean parent="ignite.cfg">
     </bean>
 
-    <!-- Template for all example cache configurations. -->
-    <bean id="cache-template" abstract="true" class="org.apache.ignite.configuration.CacheConfiguration">
-        <!-- Initial cache size. -->
-        <property name="startSize" value="3000000"/>
-
-        <!-- Set synchronous rebalancing (default is asynchronous). -->
-        <property name="rebalanceMode" value="SYNC"/>
-
-        <!-- Set to FULL_SYNC for examples, default is PRIMARY_SYNC. -->
-        <property name="writeSynchronizationMode" value="FULL_SYNC"/>
-    </bean>
 </beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/core/src/test/config/websession/example-cache2.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/config/websession/example-cache2.xml b/modules/core/src/test/config/websession/example-cache2.xml
new file mode 100644
index 0000000..59a244f
--- /dev/null
+++ b/modules/core/src/test/config/websession/example-cache2.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd">
+    <!-- Imports Ignite configuration -->
+    <import resource="example-cache-base.xml"/>
+
+    <bean parent="ignite.cfg">
+        <property name="gridName" value="grid2"/>
+    </bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
index bd2f25f..02b5f65 100644
--- a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
+++ b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
@@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpSession;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteClientDisconnectedException;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteTransactions;
@@ -123,6 +124,15 @@ import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_REA
  *         </td>
  *         <td>{@code 3}</td>
  *     </tr>
+ *     <tr>
+ *         <td>IgniteWebSessionsRetriesTimeout</td>
+ *         <td>
+ *             Retry timeout. Related to IgniteWebSessionsMaximumRetriesOnFail param.
+ *             <p>
+ *             Further attempts will be cancelled in case timeout was exceeded.
+ *         </td>
+ *         <td>{@code 10000} (10 seconds)</td>
+ *     </tr>
  * </table>
  * These parameters are taken from either filter init parameter list or
  * servlet context parameters. You can specify filter init parameters as follows:
@@ -169,9 +179,15 @@ public class WebSessionFilter implements Filter {
     /** Web sessions caching retry on fail parameter name (valid for ATOMIC cache only).
*/
     public static final String WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM = "IgniteWebSessionsMaximumRetriesOnFail";
 
+    /** Web sessions caching retry on fail timeout parameter name. */
+    public static final String WEB_SES_RETRIES_TIMEOUT_NAME_PARAM = "IgniteWebSessionsRetriesTimeout";
+
     /** Default retry on fail flag value. */
     public static final int DFLT_MAX_RETRIES_ON_FAIL = 3;
 
+    /** Default retry on fail timeout flag value. */
+    public static final int DFLT_RETRIES_ON_FAIL_TIMEOUT = 10000;
+
     /** Cache. */
     private IgniteCache<String, WebSession> cache;
 
@@ -193,9 +209,18 @@ public class WebSessionFilter implements Filter {
     /** Transactions enabled flag. */
     private boolean txEnabled;
 
+    /** Node. */
+    private Ignite webSesIgnite;
+
+    /** Cache name. */
+    private String cacheName;
+
     /** */
     private int retries;
 
+    /** */
+    private int retriesTimeout;
+
     /** {@inheritDoc} */
     @Override public void init(FilterConfig cfg) throws ServletException {
         ctx = cfg.getServletContext();
@@ -204,7 +229,7 @@ public class WebSessionFilter implements Filter {
             cfg.getInitParameter(WEB_SES_NAME_PARAM),
             ctx.getInitParameter(WEB_SES_NAME_PARAM));
 
-        String cacheName = U.firstNotNull(
+        cacheName = U.firstNotNull(
             cfg.getInitParameter(WEB_SES_CACHE_NAME_PARAM),
             ctx.getInitParameter(WEB_SES_CACHE_NAME_PARAM));
 
@@ -219,7 +244,19 @@ public class WebSessionFilter implements Filter {
             throw new IgniteException("Maximum number of retries parameter is invalid: "
+ retriesStr, e);
         }
 
-        Ignite webSesIgnite = G.ignite(gridName);
+        String retriesTimeoutStr = U.firstNotNull(
+            cfg.getInitParameter(WEB_SES_RETRIES_TIMEOUT_NAME_PARAM),
+            ctx.getInitParameter(WEB_SES_RETRIES_TIMEOUT_NAME_PARAM));
+
+        try {
+            retriesTimeout = retriesTimeoutStr != null ?
+                Integer.parseInt(retriesTimeoutStr) : DFLT_RETRIES_ON_FAIL_TIMEOUT;
+        }
+        catch (NumberFormatException e) {
+            throw new IgniteException("Retries timeout parameter is invalid: " + retriesTimeoutStr,
e);
+        }
+
+        webSesIgnite = G.ignite(gridName);
 
         if (webSesIgnite == null)
             throw new IgniteException("Grid for web sessions caching is not started (is it
configured?): " +
@@ -229,35 +266,9 @@ public class WebSessionFilter implements Filter {
 
         log = webSesIgnite.log();
 
-        cache = webSesIgnite.cache(cacheName);
-
-        if (cache == null)
-            throw new IgniteException("Cache for web sessions is not started (is it configured?):
" + cacheName);
-
-        CacheConfiguration cacheCfg = cache.getConfiguration(CacheConfiguration.class);
-
-        if (cacheCfg.getWriteSynchronizationMode() == FULL_ASYNC)
-            throw new IgniteException("Cache for web sessions cannot be in FULL_ASYNC mode:
" + cacheName);
-
-        if (!cacheCfg.isEagerTtl())
-            throw new IgniteException("Cache for web sessions cannot operate with lazy TTL.
" +
-                "Consider setting eagerTtl to true for cache: " + cacheName);
-
-        if (cacheCfg.getCacheMode() == LOCAL)
-            U.quietAndWarn(webSesIgnite.log(), "Using LOCAL cache for web sessions caching
" +
-                "(this is only OK in test mode): " + cacheName);
+        initCache();
 
-        if (cacheCfg.getCacheMode() == PARTITIONED && cacheCfg.getAtomicityMode()
!= ATOMIC)
-            U.quietAndWarn(webSesIgnite.log(), "Using " + cacheCfg.getAtomicityMode() + "
atomicity for web sessions " +
-                "caching (switch to ATOMIC mode for better performance)");
-
-        if (log.isInfoEnabled())
-            log.info("Started web sessions caching [gridName=" + gridName + ", cacheName="
+ cacheName +
-                ", maxRetriesOnFail=" + retries + ']');
-
-        txEnabled = cacheCfg.getAtomicityMode() == TRANSACTIONAL;
-
-        lsnr = new WebSessionListener(webSesIgnite, cache, retries);
+        lsnr = new WebSessionListener(webSesIgnite, this, retries);
 
         String srvInfo = ctx.getServerInfo();
 
@@ -286,6 +297,46 @@ public class WebSessionFilter implements Filter {
                 }
             };
         }
+
+        if (log.isInfoEnabled())
+            log.info("Started web sessions caching [gridName=" + gridName + ", cacheName="
+ cacheName +
+                ", maxRetriesOnFail=" + retries + ']');
+    }
+
+    /**
+     * @return Cache.
+     */
+    IgniteCache<String, WebSession> getCache(){
+        return cache;
+    }
+
+    /**
+     * Init cache.
+     */
+    void initCache() {
+        cache = webSesIgnite.cache(cacheName);
+
+        if (cache == null)
+            throw new IgniteException("Cache for web sessions is not started (is it configured?):
" + cacheName);
+
+        CacheConfiguration cacheCfg = cache.getConfiguration(CacheConfiguration.class);
+
+        if (cacheCfg.getWriteSynchronizationMode() == FULL_ASYNC)
+            throw new IgniteException("Cache for web sessions cannot be in FULL_ASYNC mode:
" + cacheName);
+
+        if (!cacheCfg.isEagerTtl())
+            throw new IgniteException("Cache for web sessions cannot operate with lazy TTL.
" +
+                "Consider setting eagerTtl to true for cache: " + cacheName);
+
+        if (cacheCfg.getCacheMode() == LOCAL)
+            U.quietAndWarn(webSesIgnite.log(), "Using LOCAL cache for web sessions caching
" +
+                "(this is only OK in test mode): " + cacheName);
+
+        if (cacheCfg.getCacheMode() == PARTITIONED && cacheCfg.getAtomicityMode()
!= ATOMIC)
+            U.quietAndWarn(webSesIgnite.log(), "Using " + cacheCfg.getAtomicityMode() + "
atomicity for web sessions " +
+                "caching (switch to ATOMIC mode for better performance)");
+
+        txEnabled = cacheCfg.getAtomicityMode() == TRANSACTIONAL;
     }
 
     /** {@inheritDoc} */
@@ -333,7 +384,7 @@ public class WebSessionFilter implements Filter {
      */
     private String doFilter0(HttpServletRequest httpReq, ServletResponse res, FilterChain
chain) throws IOException,
         ServletException, CacheException {
-        WebSession cached;
+        WebSession cached = null;
 
         String sesId = httpReq.getRequestedSessionId();
 
@@ -341,7 +392,24 @@ public class WebSessionFilter implements Filter {
             if (sesIdTransformer != null)
                 sesId = sesIdTransformer.apply(sesId);
 
-            cached = cache.get(sesId);
+            for (int i = 0; i < retries; i++) {
+                try {
+                    cached = cache.get(sesId);
+                }
+                catch (CacheException | IgniteException | IllegalStateException e) {
+                    if (log.isDebugEnabled())
+                        log.debug(e.getMessage());
+
+                    if (i == retries - 1)
+                        throw new IgniteException("Failed to handle request [session= " +
sesId + "]", e);
+                    else {
+                        if (log.isDebugEnabled())
+                            log.debug("Failed to handle request (will retry): " + sesId);
+
+                        handleCacheOperationException(e);
+                    }
+                }
+            }
 
             if (cached != null) {
                 if (log.isDebugEnabled())
@@ -438,7 +506,7 @@ public class WebSessionFilter implements Filter {
 
                 break;
             }
-            catch (CacheException | IgniteException e) {
+            catch (CacheException | IgniteException | IllegalStateException e) {
                 if (log.isDebugEnabled())
                     log.debug(e.getMessage());
 
@@ -448,29 +516,49 @@ public class WebSessionFilter implements Filter {
                     if (log.isDebugEnabled())
                         log.debug("Failed to save session (will retry): " + sesId);
 
-                    IgniteFuture<?> retryFut = null;
+                    handleCacheOperationException(e);
+                }
+            }
+        }
 
-                    if (X.hasCause(e, ClusterTopologyException.class)) {
-                        ClusterTopologyException cause = X.cause(e, ClusterTopologyException.class);
+        return cached;
+    }
 
-                        assert cause != null : e;
+    /**
+     * Handles cache operation exception.
+     * @param e Exception
+     */
+    void handleCacheOperationException(Exception e){
+        IgniteFuture<?> retryFut = null;
 
-                        retryFut = cause.retryReadyFuture();
-                    }
+        if (e instanceof IllegalStateException) {
+            initCache();
 
-                    if (retryFut != null) {
-                        try {
-                            retryFut.get();
-                        }
-                        catch (IgniteException retryErr) {
-                            throw new IgniteException("Failed to save session: " + sesId,
retryErr);
-                        }
-                    }
-                }
-            }
+            return;
         }
+        else if (X.hasCause(e, IgniteClientDisconnectedException.class)) {
+            IgniteClientDisconnectedException cause = X.cause(e, IgniteClientDisconnectedException.class);
 
-        return cached;
+            assert cause != null : e;
+
+            retryFut = cause.reconnectFuture();
+        }
+        else if (X.hasCause(e, ClusterTopologyException.class)) {
+            ClusterTopologyException cause = X.cause(e, ClusterTopologyException.class);
+
+            assert cause != null : e;
+
+            retryFut = cause.retryReadyFuture();
+        }
+
+        if (retryFut != null) {
+            try {
+                retryFut.get(retriesTimeout);
+            }
+            catch (IgniteException retryErr) {
+                throw new IgniteException("Failed to wait for retry: " + retryErr);
+            }
+        }
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionListener.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionListener.java
b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionListener.java
index 0d7c44e..0d8ffec 100644
--- a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionListener.java
+++ b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionListener.java
@@ -32,12 +32,9 @@ import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.internal.util.typedef.T2;
-import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteFuture;
 
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 
@@ -45,11 +42,8 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
  * Session listener for web sessions caching.
  */
 class WebSessionListener {
-    /** */
-    private static final long RETRY_DELAY = 1000;
-
-    /** Cache. */
-    private final IgniteCache<String, WebSession> cache;
+    /** Filter. */
+    private final WebSessionFilter filter;
 
     /** Maximum retries. */
     private final int retries;
@@ -59,14 +53,14 @@ class WebSessionListener {
 
     /**
      * @param ignite Grid.
-     * @param cache Cache.
+     * @param filter Filter.
      * @param retries Maximum retries.
      */
-    WebSessionListener(Ignite ignite, IgniteCache<String, WebSession> cache, int retries)
{
+    WebSessionListener(Ignite ignite, WebSessionFilter filter, int retries) {
         assert ignite != null;
-        assert cache != null;
+        assert filter != null;
 
-        this.cache = cache;
+        this.filter = filter;
         this.retries = retries > 0 ? retries : 1;
 
         log = ignite.log();
@@ -77,13 +71,22 @@ class WebSessionListener {
      */
     public void destroySession(String sesId) {
         assert sesId != null;
+        for (int i = 0; i < retries; i++) {
+            try {
+                if (filter.getCache().remove(sesId) && log.isDebugEnabled())
+                    log.debug("Session destroyed: " + sesId);
+            }
+            catch (CacheException | IgniteException | IllegalStateException e) {
+                if (i == retries - 1) {
+                    U.warn(log, "Failed to remove session [sesId=" +
+                        sesId + ", retries=" + retries + ']');
+                }
+                else {
+                    U.warn(log, "Failed to remove session (will retry): " + sesId);
 
-        try {
-            if (cache.remove(sesId) && log.isDebugEnabled())
-                log.debug("Session destroyed: " + sesId);
-        }
-        catch (CacheException e) {
-            U.error(log, "Failed to remove session: " + sesId, e);
+                    filter.handleCacheOperationException(e);
+                }
+            }
         }
     }
 
@@ -110,16 +113,16 @@ class WebSessionListener {
 
                         ExpiryPolicy plc = new ModifiedExpiryPolicy(new Duration(MILLISECONDS,
ttl));
 
-                        cache0 = cache.withExpiryPolicy(plc);
+                        cache0 = filter.getCache().withExpiryPolicy(plc);
                     }
                     else
-                        cache0 = cache;
+                        cache0 = filter.getCache();
 
                     cache0.invoke(sesId, new AttributesProcessor(updates));
 
                     break;
                 }
-                catch (CacheException | IgniteException e) {
+                catch (CacheException | IgniteException | IllegalStateException e) {
                     if (i == retries - 1) {
                         U.warn(log, "Failed to apply updates for session (maximum number
of retries exceeded) [sesId=" +
                             sesId + ", retries=" + retries + ']');
@@ -127,20 +130,7 @@ class WebSessionListener {
                     else {
                         U.warn(log, "Failed to apply updates for session (will retry): "
+ sesId);
 
-                        IgniteFuture<?> retryFut = null;
-
-                        if (X.hasCause(e, ClusterTopologyException.class)) {
-                            ClusterTopologyException cause = X.cause(e, ClusterTopologyException.class);
-
-                            assert cause != null : e;
-
-                            retryFut = cause.retryReadyFuture();
-                        }
-
-                        if (retryFut != null)
-                            retryFut.get();
-                        else
-                            U.sleep(RETRY_DELAY);
+                        filter.handleCacheOperationException(e);
                     }
                 }
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3130872e/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
b/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
index 7a321d6..90cb132 100644
--- a/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
+++ b/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
@@ -32,7 +32,9 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
+import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.internal.util.typedef.X;
@@ -76,6 +78,77 @@ public class WebSessionSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testClientReconnectRequest() throws Exception {
+        testClientReconnectRequest("/modules/core/src/test/config/websession/example-cache.xml",
+            "/modules/core/src/test/config/websession/example-cache2.xml",
+            "/modules/core/src/test/config/websession/example-cache-client.xml");
+    }
+
+    /**
+     * Tests single request to a server. Checks the presence of session in cache.
+     *
+     * @param srvCfg Server configuration.
+     * @param clientCfg Client configuration.
+     * @throws Exception If failed.
+     */
+    private void testClientReconnectRequest(String srvCfg, String srvCfg2, String clientCfg)
throws Exception {
+        Server srv = null;
+
+        Ignite ignite = Ignition.start(srvCfg);
+
+        try {
+            srv = startServer(TEST_JETTY_PORT, clientCfg, "client", new SessionCreateServlet());
+
+            URL url = new URL("http://localhost:" + TEST_JETTY_PORT + "/ignitetest/test");
+
+            URLConnection conn = url.openConnection();
+
+            conn.connect();
+
+            try (BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream())))
{
+                String sesId = rdr.readLine();
+
+                assertNotNull(sesId);
+            }
+
+            stopGrid(ignite.name());
+
+            ignite = Ignition.start(srvCfg);
+
+            conn = url.openConnection();
+
+            conn.connect();
+
+            try (BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream())))
{
+                String sesId = rdr.readLine();
+
+                assertNotNull(sesId);
+            }
+
+            Ignite ignite2 = Ignition.start(srvCfg2);
+
+            stopGrid(ignite.name());
+
+            conn = url.openConnection();
+
+            conn.connect();
+
+            try (BufferedReader rdr = new BufferedReader(new InputStreamReader(conn.getInputStream())))
{
+                String sesId = rdr.readLine();
+
+                assertNotNull(sesId);
+            }
+        }
+        finally {
+            stopServer(srv);
+
+            stopAllGrids();
+        }
+    }
+
+    /**
      * Tests single request to a server. Checks the presence of session in cache.
      *
      * @param cfg Configuration.


Mime
View raw message