You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2016/03/15 11:41:40 UTC
[11/22] ignite git commit: IGNITE-2765 WebSessionFilter doesn't
survive client reconnect
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/0ad4f395
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0ad4f395
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0ad4f395
Branch: refs/heads/ignite-1786
Commit: 0ad4f395a4b18a5cb1cba4926261cf5dd56e606d
Parents: ed030e5
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:34:23 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 | 72 +++++++
7 files changed, 452 insertions(+), 208 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/0ad4f395/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/0ad4f395/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/0ad4f395/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/0ad4f395/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/0ad4f395/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 42de43b..f718035 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())
@@ -455,7 +523,7 @@ public class WebSessionFilter implements Filter {
break;
}
- catch (CacheException | IgniteException e) {
+ catch (CacheException | IgniteException | IllegalStateException e) {
if (log.isDebugEnabled())
log.debug(e.getMessage());
@@ -465,29 +533,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/0ad4f395/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/0ad4f395/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 298baf1..8706e1f 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
@@ -37,6 +37,7 @@ import javax.servlet.http.HttpSession;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.events.Event;
+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;
@@ -83,6 +84,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.