ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From yzhda...@apache.org
Subject [2/3] incubator-ignite git commit: ignite-45 - rename web component
Date Fri, 20 Mar 2015 15:19:16 GMT
ignite-45 - rename web component


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

Branch: refs/heads/ignite-45
Commit: 2bf5da742228e1001cc0adb6ffed83647e8711fc
Parents: 2272d55
Author: Yakov Zhdanov <yzhdanov@gridgain.com>
Authored: Fri Mar 20 18:18:56 2015 +0300
Committer: Yakov Zhdanov <yzhdanov@gridgain.com>
Committed: Fri Mar 20 18:18:56 2015 +0300

----------------------------------------------------------------------
 .../main/java/org/apache/ignite/Ignition.java   |   2 +-
 .../org/apache/ignite/internal/IgnitionEx.java  |   2 +-
 modules/core/src/test/webapp/WEB-INF/web.xml    |   2 +-
 .../cache/websession/IgniteWebSession.java      | 286 ------------
 .../websession/IgniteWebSessionFilter.java      | 466 ------------------
 .../websession/IgniteWebSessionListener.java    | 196 --------
 .../ignite/cache/websession/WebSession.java     | 286 ++++++++++++
 .../cache/websession/WebSessionFilter.java      | 467 +++++++++++++++++++
 .../cache/websession/WebSessionListener.java    | 196 ++++++++
 .../IgniteServletContextListenerStartup.java    | 181 -------
 .../startup/servlet/IgniteServletStartup.java   | 187 --------
 .../servlet/ServletContextListenerStartup.java  | 181 +++++++
 .../ignite/startup/servlet/ServletStartup.java  | 187 ++++++++
 13 files changed, 1320 insertions(+), 1319 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/core/src/main/java/org/apache/ignite/Ignition.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/Ignition.java b/modules/core/src/main/java/org/apache/ignite/Ignition.java
index 5def17b..3017342 100644
--- a/modules/core/src/main/java/org/apache/ignite/Ignition.java
+++ b/modules/core/src/main/java/org/apache/ignite/Ignition.java
@@ -34,7 +34,7 @@ import java.util.*;
  * {@link org.apache.ignite.startup} package, for example:
  * <ul>
  * <li>{@link org.apache.ignite.startup.cmdline.CommandLineStartup}</li>
- * <li>{@ignitelink org.apache.ignite.startup.servlet.IgniteServletStartup}</li>
+ * <li>{@ignitelink org.apache.ignite.startup.servlet.ServletStartup}</li>
  * </ul>
  * <h1 class="header">Examples</h1>
  * Use {@link #start()} method to start grid with default configuration. You can also use

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
index 48aaaa2..51f7979 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgnitionEx.java
@@ -82,7 +82,7 @@ import static org.apache.ignite.plugin.segmentation.GridSegmentationPolicy.*;
  * {@link org.apache.ignite.startup} package, for example:
  * <ul>
  * <li>{@code CommandLineStartup}</li>
- * <li>{@code IgniteServletStartup}</li>
+ * <li>{@code ServletStartup}</li>
  * </ul>
  * <h1 class="header">Examples</h1>
  * Use {@link #start()} method to start grid with default configuration. You can also use

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/core/src/test/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/modules/core/src/test/webapp/WEB-INF/web.xml b/modules/core/src/test/webapp/WEB-INF/web.xml
index 2710e6e..e9969dc 100644
--- a/modules/core/src/test/webapp/WEB-INF/web.xml
+++ b/modules/core/src/test/webapp/WEB-INF/web.xml
@@ -31,7 +31,7 @@
     <!-- Declare filter for web sessions caching. -->
     <filter>
         <filter-name>IgniteWebSessionsFilter</filter-name>
-        <filter-class>org.apache.ignite.cache.websession.IgniteWebSessionFilter</filter-class>
+        <filter-class>org.apache.ignite.cache.websession.WebSessionFilter</filter-class>
     </filter>
 
     <filter-mapping>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSession.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSession.java b/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSession.java
deleted file mode 100644
index 70c4e27..0000000
--- a/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSession.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.ignite.cache.websession;
-
-import org.apache.ignite.internal.util.tostring.*;
-import org.apache.ignite.internal.util.typedef.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-import org.jetbrains.annotations.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-import java.io.*;
-import java.util.*;
-
-/**
- * Session implementation.
- */
-@SuppressWarnings({"deprecation", "NonSerializableObjectBoundToHttpSession"})
-class IgniteWebSession implements HttpSession, Externalizable {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Empty session context. */
-    private static final HttpSessionContext EMPTY_SES_CTX = new HttpSessionContext() {
-        @Nullable @Override public HttpSession getSession(String id) {
-            return null;
-        }
-
-        @Override public Enumeration<String> getIds() {
-            return Collections.enumeration(Collections.<String>emptyList());
-        }
-    };
-
-    /** Session ID. */
-    private String id;
-
-    /** Creation time. */
-    private long createTime;
-
-    /** Last access time. */
-    private long accessTime;
-
-    /** Maximum inactive interval. */
-    private int maxInactiveInterval;
-
-    /** Attributes. */
-    @GridToStringInclude
-    private Map<String, Object> attrs;
-
-    /** Servlet context. */
-    @GridToStringExclude
-    private transient ServletContext ctx;
-
-    /** Listener. */
-    @GridToStringExclude
-    private transient IgniteWebSessionListener lsnr;
-
-    /** New session flag. */
-    private transient boolean isNew;
-
-    /** Updates list. */
-    private transient Collection<T2<String, Object>> updates;
-
-    /**
-     * Required by {@link Externalizable}.
-     */
-    public IgniteWebSession() {
-        // No-op.
-    }
-
-    /**
-     * @param ses Session.
-     */
-    IgniteWebSession(HttpSession ses) {
-        assert ses != null;
-
-        id = ses.getId();
-        createTime = ses.getCreationTime();
-        accessTime = ses.getLastAccessedTime();
-        maxInactiveInterval = ses.getMaxInactiveInterval();
-        isNew = ses.isNew();
-
-        attrs = new HashMap<>();
-
-        Enumeration<String> names = ses.getAttributeNames();
-
-        while (names.hasMoreElements()) {
-            String name = names.nextElement();
-
-            attrs.put(name, ses.getAttribute(name));
-        }
-    }
-
-    /**
-     * @param ses Session.
-     * @param isNew Is new flag.
-     */
-    IgniteWebSession(HttpSession ses, boolean isNew) {
-        this(ses);
-
-        this.isNew = isNew;
-    }
-
-    /**
-     * @param accessTime Last access time.
-     */
-    void accessTime(long accessTime) {
-        this.accessTime = accessTime;
-    }
-
-    /**
-     * @param ctx Servlet context.
-     */
-    public void servletContext(ServletContext ctx) {
-        assert ctx != null;
-
-        this.ctx = ctx;
-    }
-
-    /**
-     * @param lsnr Listener.
-     */
-    public void listener(IgniteWebSessionListener lsnr) {
-        assert lsnr != null;
-
-        this.lsnr = lsnr;
-    }
-
-    /**
-     * Resets updates list.
-     */
-    public void resetUpdates() {
-        updates = new LinkedList<>();
-    }
-
-    /**
-     * @return Updates list.
-     */
-    public Collection<T2<String, Object>> updates() {
-        Collection<T2<String, Object>> updates0 = updates;
-
-        updates = null;
-
-        return updates0;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String getId() {
-        return id;
-    }
-
-    /** {@inheritDoc} */
-    @Override public ServletContext getServletContext() {
-        return ctx;
-    }
-
-    /** {@inheritDoc} */
-    @Override public long getCreationTime() {
-        return createTime;
-    }
-
-    /** {@inheritDoc} */
-    @Override public long getLastAccessedTime() {
-        return accessTime;
-    }
-
-    /** {@inheritDoc} */
-    @Override public int getMaxInactiveInterval() {
-        return maxInactiveInterval;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setMaxInactiveInterval(int interval) {
-        maxInactiveInterval = interval;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object getAttribute(String name) {
-        return attrs.get(name);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object getValue(String name) {
-        return attrs.get(name);
-    }
-
-    /** {@inheritDoc} */
-    @Override public Enumeration<String> getAttributeNames() {
-        return Collections.enumeration(attrs.keySet());
-    }
-
-    /** {@inheritDoc} */
-    @Override public String[] getValueNames() {
-        return attrs.keySet().toArray(new String[attrs.size()]);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setAttribute(String name, Object val) {
-        attrs.put(name, val);
-
-        if (updates != null)
-            updates.add(new T2<>(name, val));
-    }
-
-    /** {@inheritDoc} */
-    @Override public void putValue(String name, Object val) {
-        setAttribute(name, val);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void removeAttribute(String name) {
-        attrs.remove(name);
-
-        if (updates != null)
-            updates.add(new T2<>(name, null));
-    }
-
-    /** {@inheritDoc} */
-    @Override public void removeValue(String name) {
-        removeAttribute(name);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void invalidate() {
-        attrs.clear();
-
-        updates = null;
-
-        lsnr.destroySession(id);
-    }
-
-    /**
-     * @param isNew New session flag.
-     */
-    void setNew(boolean isNew) {
-        this.isNew = isNew;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean isNew() {
-        return isNew;
-    }
-
-    /** {@inheritDoc} */
-    @Override public HttpSessionContext getSessionContext() {
-        return EMPTY_SES_CTX;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeExternal(ObjectOutput out) throws IOException {
-        U.writeString(out, id);
-        out.writeLong(createTime);
-        out.writeLong(accessTime);
-        out.writeInt(maxInactiveInterval);
-        U.writeMap(out, attrs);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        id = U.readString(in);
-        createTime = in.readLong();
-        accessTime = in.readLong();
-        maxInactiveInterval = in.readInt();
-        attrs = U.readMap(in);
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(IgniteWebSession.class, this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionFilter.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionFilter.java b/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionFilter.java
deleted file mode 100644
index aead242..0000000
--- a/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionFilter.java
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.ignite.cache.websession;
-
-import org.apache.ignite.*;
-import org.apache.ignite.cache.*;
-import org.apache.ignite.configuration.*;
-import org.apache.ignite.internal.util.typedef.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-import org.apache.ignite.lang.*;
-import org.apache.ignite.transactions.*;
-
-import javax.cache.*;
-import javax.cache.expiry.*;
-import javax.servlet.*;
-import javax.servlet.http.*;
-import java.io.*;
-import java.util.*;
-
-import static java.util.concurrent.TimeUnit.*;
-import static org.apache.ignite.cache.CacheAtomicityMode.*;
-import static org.apache.ignite.cache.CacheMode.*;
-import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*;
-import static org.apache.ignite.transactions.TransactionConcurrency.*;
-import static org.apache.ignite.transactions.TransactionIsolation.*;
-
-/**
- * Filter for web sessions caching.
- * <p>
- * This is a request filter, that you need to specify in your {@code web.xml} along
- * with {@link org.apache.ignite.startup.servlet.IgniteServletContextListenerStartup} to enable web sessions caching:
- * <pre name="code" class="xml">
- * &lt;listener&gt;
- *     &lt;listener-class&gt;org.apache.ignite.startup.servlet.IgniteServletContextListenerStartup&lt;/listener-class&gt;
- * &lt;/listener&gt;
- *
- * &lt;filter&gt;
- *     &lt;filter-name&gt;IgniteWebSessionFilter&lt;/filter-name&gt;
- *     &lt;filter-class&gt;org.apache.ignite.cache.websession.IgniteWebSessionFilter&lt;/filter-class&gt;
- * &lt;/filter&gt;
- *
- * &lt;!-- You can also specify a custom URL pattern. --&gt;
- * &lt;filter-mapping&gt;
- *     &lt;filter-name&gt;IgniteWebSessionsFilter&lt;/filter-name&gt;
- *     &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
- * &lt;/filter-mapping&gt;
- * </pre>
- * It is also possible to specify a servlet name in a filter mapping, and a servlet URL pattern will
- * be used in this case:
- * <pre name="code" class="xml">
- * &lt;filter&gt;
- *     &lt;filter-name&gt;IgniteWebSessionFilter&lt;/filter-name&gt;
- *     &lt;filter-class&gt;org.apache.ignite.cache.websession.IgniteWebSessionFilter&lt;/filter-class&gt;
- * &lt;/filter&gt;
- *
- * &lt;filter-mapping&gt;
- *     &lt;filter-name&gt;IgniteWebSessionFilter&lt;/filter-name&gt;
- *     &lt;servlet-name&gt;YourServletName&lt;/servlet-name&gt;
- * &lt;/filter-mapping&gt;
- * </pre>
- * The filter has the following optional configuration parameters:
- * <table class="doctable">
- *     <tr>
- *         <th>Name</th>
- *         <th>Description</th>
- *         <th>Default</th>
- *     </tr>
- *     <tr>
- *         <td>IgniteWebSessionsGridName</td>
- *         <td>Name of the grid that contains cache for web session storage.</td>
- *         <td>{@code null} (default grid)</td>
- *     </tr>
- *     <tr>
- *         <td>IgniteWebSessionsCacheName</td>
- *         <td>Name of the cache for web session storage.</td>
- *         <td>{@code null} (default cache)</td>
- *     </tr>
- *     <tr>
- *         <td>IgniteWebSessionsMaximumRetriesOnFail</td>
- *         <td>
- *             Valid for {@code ATOMIC} caches only. Maximum number of retries for session updates in case
- *             node leaves topology and update fails. If retry is enabled,
- *             some updates can be applied more than once, otherwise some
- *             updates can be lost.
- *             <p>
- *             To disable retries, set this parameter to {@code 0}.
- *         </td>
- *         <td>{@code 3}</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:
- * <pre name="code" class="xml">
- * &lt;filter&gt;
- *     &lt;filter-name&gt;IgniteWebSessionFilter&lt;/filter-name&gt;
- *     &lt;filter-class&gt;org.apache.ignite.cache.websession.IgniteWebSessionFilter&lt;/filter-class&gt;
- *     &lt;init-param&gt;
- *         &lt;param-name&gt;IgniteWebSessionsGridName&lt;/param-name&gt;
- *         &lt;param-value&gt;WebGrid&lt;/param-value&gt;
- *     &lt;/init-param&gt;
- *     &lt;init-param&gt;
- *         &lt;param-name&gt;IgniteWebSessionsCacheName&lt;/param-name&gt;
- *         &lt;param-value&gt;WebCache&lt;/param-value&gt;
- *     &lt;/init-param&gt;
- *
- *     &lt;!-- Valid for ATOMIC caches only. --&gt;
- *     &lt;init-param&gt;
- *         &lt;param-name&gt;IgniteWebSessionsMaximumRetriesOnFail&lt;/param-name&gt;
- *         &lt;param-value&gt;10&lt;/param-value&gt;
- *     &lt;/init-param&gt;
- * &lt;/filter&gt;
- * </pre>
- * <b>Note:</b> filter init parameter has a priority over servlet context
- * parameter; if you specify both, the servlet context parameter will be ignored.
- * <h1 class="header">Web sessions caching and concurrent requests</h1>
- * If your web application can accept concurrent request for one session,
- * consider using {@link org.apache.ignite.cache.CacheAtomicityMode#TRANSACTIONAL} cache
- * instead of {@link org.apache.ignite.cache.CacheAtomicityMode#ATOMIC}. In this case each request
- * be processed inside pessimistic transaction which will guarantee that all
- * updates will be applied in correct order. This is important, for example,
- * if you get some attribute from the session, update its value and set new
- * value back to the session. In case of {@link org.apache.ignite.cache.CacheAtomicityMode#ATOMIC}
- * cache concurrent requests can get equal value, but {@link org.apache.ignite.cache.CacheAtomicityMode#TRANSACTIONAL}
- * cache will always process such updates one after another.
- */
-public class IgniteWebSessionFilter implements Filter {
-    /** Web sessions caching grid name parameter name. */
-    public static final String WEB_SES_NAME_PARAM = "IgniteWebSessionsGridName";
-
-    /** Web sessions caching cache name parameter name. */
-    public static final String WEB_SES_CACHE_NAME_PARAM = "IgniteWebSessionsCacheName";
-
-    /** Web sessions caching retry on fail parameter name (valid for ATOMIC */
-    public static final String WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM = "IgniteWebSessionsMaximumRetriesOnFail";
-
-    /** Default retry on fail flag value. */
-    public static final int DFLT_MAX_RETRIES_ON_FAIL = 3;
-
-    /** Cache. */
-    private IgniteCache<String, IgniteWebSession> cache;
-
-    /** Transactions. */
-    private IgniteTransactions txs;
-
-    /** Listener. */
-    private IgniteWebSessionListener lsnr;
-
-    /** Logger. */
-    private IgniteLogger log;
-
-    /** Servlet context. */
-    private ServletContext ctx;
-
-    /** Session ID transformer. */
-    private IgniteClosure<String, String> sesIdTransformer;
-
-    /** Transactions enabled flag. */
-    private boolean txEnabled;
-
-    /** {@inheritDoc} */
-    @Override public void init(FilterConfig cfg) throws ServletException {
-        ctx = cfg.getServletContext();
-
-        String gridName = U.firstNotNull(
-            cfg.getInitParameter(WEB_SES_NAME_PARAM),
-            ctx.getInitParameter(WEB_SES_NAME_PARAM));
-
-        String cacheName = U.firstNotNull(
-            cfg.getInitParameter(WEB_SES_CACHE_NAME_PARAM),
-            ctx.getInitParameter(WEB_SES_CACHE_NAME_PARAM));
-
-        String retriesStr = U.firstNotNull(
-            cfg.getInitParameter(WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM),
-            ctx.getInitParameter(WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM));
-
-        int retries;
-
-        try {
-            retries = retriesStr != null ? Integer.parseInt(retriesStr) : DFLT_MAX_RETRIES_ON_FAIL;
-        }
-        catch (NumberFormatException e) {
-            throw new IgniteException("Maximum number of retries parameter is invalid: " + retriesStr, e);
-        }
-
-        Ignite webSesIgnite = G.ignite(gridName);
-
-        if (webSesIgnite == null)
-            throw new IgniteException("Grid for web sessions caching is not started (is it configured?): " +
-                gridName);
-
-        txs = webSesIgnite.transactions();
-
-        log = webSesIgnite.log();
-
-        if (webSesIgnite == null)
-            throw new IgniteException("Grid for web sessions caching is not started (is it configured?): " +
-                gridName);
-
-        cache = webSesIgnite.jcache(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)");
-
-        if (log.isInfoEnabled())
-            log.info("Started web sessions caching [gridName=" + gridName + ", cacheName=" + cacheName +
-                ", maxRetriesOnFail=" + retries + ']');
-
-        txEnabled = cacheCfg.getAtomicityMode() == TRANSACTIONAL;
-
-        lsnr = new IgniteWebSessionListener(webSesIgnite, cache, retries);
-
-        String srvInfo = ctx.getServerInfo();
-
-        // Special case for WebLogic, which appends timestamps to session
-        // IDs upon session creation (the created session ID looks like:
-        // pdpTSTcCcG6CVM8BTZWzxjTB1lh3w7zFbYVvwBb4bJGjrBx3TMPl!-508312620!1385045122601).
-        if (srvInfo != null && srvInfo.contains("WebLogic")) {
-            sesIdTransformer = new C1<String, String>() {
-                @Override public String apply(String s) {
-                    // Find first exclamation mark.
-                    int idx = s.indexOf('!');
-
-                    // Return original string if not found.
-                    if (idx < 0 || idx == s.length() - 1)
-                        return s;
-
-                    // Find second exclamation mark.
-                    idx = s.indexOf('!', idx + 1);
-
-                    // Return original string if not found.
-                    if (idx < 0)
-                        return s;
-
-                    // Return the session ID without timestamp.
-                    return s.substring(0, idx);
-                }
-            };
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public void destroy() {
-        // No-op.
-    }
-
-    /** {@inheritDoc} */
-    @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
-        throws IOException, ServletException {
-        assert ctx != null;
-
-        if (req instanceof HttpServletRequest) {
-            HttpServletRequest httpReq = (HttpServletRequest)req;
-
-            String sesId = null;
-
-            try {
-                if (txEnabled) {
-                    try (Transaction tx = txs.txStart(PESSIMISTIC, REPEATABLE_READ)) {
-                        sesId = doFilter0(httpReq, res, chain);
-
-                        tx.commit();
-                    }
-                }
-                else
-                    sesId = doFilter0(httpReq, res, chain);
-            }
-            catch (Exception e) {
-                U.error(log, "Failed to update web session: " + sesId, e);
-            }
-        }
-        else
-            chain.doFilter(req, res);
-    }
-
-    /**
-     * @param httpReq Request.
-     * @param res Response.
-     * @param chain Filter chain.
-     * @return Session ID.
-     * @throws IOException In case of I/O error.
-     * @throws ServletException In case oif servlet error.
-     * @throws CacheException In case of other error.
-     */
-    private String doFilter0(HttpServletRequest httpReq, ServletResponse res, FilterChain chain) throws IOException,
-        ServletException, CacheException {
-        IgniteWebSession cached;
-
-        String sesId = httpReq.getRequestedSessionId();
-
-        if (sesId != null) {
-            cached = cache.get(sesId);
-
-            if (cached != null) {
-                if (log.isDebugEnabled())
-                    log.debug("Using cached session for ID: " + sesId);
-
-                if (cached.isNew())
-                    cached = new IgniteWebSession(cached, false);
-            }
-            else {
-                if (log.isDebugEnabled())
-                    log.debug("Cached session was invalidated and doesn't exist: " + sesId);
-
-                HttpSession ses = httpReq.getSession(false);
-
-                if (ses != null) {
-                    try {
-                        ses.invalidate();
-                    }
-                    catch (IllegalStateException ignore) {
-                        // Session was already invalidated.
-                    }
-                }
-
-                cached = createSession(httpReq);
-            }
-        }
-        else {
-            cached = createSession(httpReq);
-
-            sesId = cached.getId();
-        }
-
-        assert cached != null;
-
-        cached.servletContext(ctx);
-        cached.listener(lsnr);
-        cached.resetUpdates();
-
-        httpReq = new RequestWrapper(httpReq, cached);
-
-        chain.doFilter(httpReq, res);
-
-        HttpSession ses = httpReq.getSession(false);
-
-        if (ses != null && ses instanceof IgniteWebSession) {
-            Collection<T2<String, Object>> updates = ((IgniteWebSession)ses).updates();
-
-            if (updates != null)
-                lsnr.updateAttributes(ses.getId(), updates, ses.getMaxInactiveInterval());
-        }
-
-        return sesId;
-    }
-
-    /**
-     * @param httpReq HTTP request.
-     * @return Cached session.
-     */
-    @SuppressWarnings("unchecked")
-    private IgniteWebSession createSession(HttpServletRequest httpReq) {
-        HttpSession ses = httpReq.getSession(true);
-
-        String sesId = sesIdTransformer != null ? sesIdTransformer.apply(ses.getId()) : ses.getId();
-
-        if (log.isDebugEnabled())
-            log.debug("Session created: " + sesId);
-
-        IgniteWebSession cached = new IgniteWebSession(ses, true);
-
-        try {
-            while (true) {
-                try {
-                    IgniteCache<String, IgniteWebSession> cache0;
-
-                    if (cached.getMaxInactiveInterval() > 0) {
-                        long ttl = cached.getMaxInactiveInterval() * 1000;
-
-                        ExpiryPolicy plc = new ModifiedExpiryPolicy(new Duration(MILLISECONDS, ttl));
-
-                        cache0 = cache.withExpiryPolicy(plc);
-                    }
-                    else
-                        cache0 = cache;
-
-                    IgniteWebSession old = cache0.getAndPutIfAbsent(sesId, cached);
-
-                    if (old != null) {
-                        cached = old;
-
-                        if (cached.isNew())
-                            cached = new IgniteWebSession(cached, false);
-                    }
-
-                    break;
-                }
-                catch (CachePartialUpdateException e) {
-                    if (log.isDebugEnabled())
-                        log.debug(e.getMessage());
-                }
-            }
-        }
-        catch (CacheException e) {
-            throw new IgniteException("Failed to save session: " + sesId, e);
-        }
-
-        return cached;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(IgniteWebSessionFilter.class, this);
-    }
-
-    /**
-     * Request wrapper.
-     */
-    private static class RequestWrapper extends HttpServletRequestWrapper {
-        /** Session. */
-        private final IgniteWebSession ses;
-
-        /**
-         * @param req Request.
-         * @param ses Session.
-         */
-        private RequestWrapper(HttpServletRequest req, IgniteWebSession ses) {
-            super(req);
-
-            assert ses != null;
-
-            this.ses = ses;
-        }
-
-        /** {@inheritDoc} */
-        @Override public HttpSession getSession(boolean create) {
-            return ses;
-        }
-
-        /** {@inheritDoc} */
-        @Override public HttpSession getSession() {
-            return ses;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionListener.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionListener.java b/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionListener.java
deleted file mode 100644
index 06d7a7f..0000000
--- a/modules/web/src/main/java/org/apache/ignite/cache/websession/IgniteWebSessionListener.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.ignite.cache.websession;
-
-import org.apache.ignite.*;
-import org.apache.ignite.cache.*;
-import org.apache.ignite.internal.*;
-import org.apache.ignite.internal.util.typedef.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-
-import javax.cache.*;
-import javax.cache.expiry.*;
-import javax.cache.processor.*;
-import java.io.*;
-import java.util.*;
-
-import static java.util.concurrent.TimeUnit.*;
-
-/**
- * Session listener for web sessions caching.
- */
-class IgniteWebSessionListener {
-    /** */
-    private static final long RETRY_DELAY = 1;
-
-    /** Cache. */
-    private final IgniteCache<String, IgniteWebSession> cache;
-
-    /** Maximum retries. */
-    private final int retries;
-
-    /** Logger. */
-    private final IgniteLogger log;
-
-    /**
-     * @param ignite Grid.
-     * @param cache Cache.
-     * @param retries Maximum retries.
-     */
-    IgniteWebSessionListener(Ignite ignite, IgniteCache<String, IgniteWebSession> cache, int retries) {
-        assert ignite != null;
-        assert cache != null;
-
-        this.cache = cache;
-        this.retries = retries > 0 ? retries : 1;
-
-        log = ignite.log();
-    }
-
-    /**
-     * @param sesId Session ID.
-     */
-    public void destroySession(String sesId) {
-        assert sesId != null;
-
-        try {
-            if (cache.remove(sesId) && log.isDebugEnabled())
-                log.debug("Session destroyed: " + sesId);
-        }
-        catch (CacheException e) {
-            U.error(log, "Failed to remove session: " + sesId, e);
-        }
-    }
-
-    /**
-     * @param sesId Session ID.
-     * @param updates Updates list.
-     * @param maxInactiveInterval Max session inactive interval.
-     */
-    @SuppressWarnings("unchecked")
-    public void updateAttributes(String sesId, Collection<T2<String, Object>> updates, int maxInactiveInterval) {
-        assert sesId != null;
-        assert updates != null;
-
-        if (log.isDebugEnabled())
-            log.debug("Session attributes updated [id=" + sesId + ", updates=" + updates + ']');
-
-        try {
-            for (int i = 0; i < retries; i++) {
-                try {
-                    IgniteCache<String, IgniteWebSession> cache0;
-
-                    if (maxInactiveInterval > 0) {
-                        long ttl = maxInactiveInterval * 1000;
-
-                        ExpiryPolicy plc = new ModifiedExpiryPolicy(new Duration(MILLISECONDS, ttl));
-
-                        cache0 = cache.withExpiryPolicy(plc);
-                    }
-                    else
-                        cache0 = cache;
-
-                    cache0.invoke(sesId, new AttributesProcessor(updates));
-
-                    break;
-                }
-                catch (CachePartialUpdateException ignored) {
-                    if (i == retries - 1) {
-                        U.warn(log, "Failed to apply updates for session (maximum number of retries exceeded) [sesId=" +
-                            sesId + ", retries=" + retries + ']');
-                    }
-                    else {
-                        U.warn(log, "Failed to apply updates for session (will retry): " + sesId);
-
-                        U.sleep(RETRY_DELAY);
-                    }
-                }
-            }
-        }
-        catch (CacheException | IgniteInterruptedCheckedException e) {
-            U.error(log, "Failed to update session attributes [id=" + sesId + ']', e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(IgniteWebSessionListener.class, this);
-    }
-
-    /**
-     * Multiple attributes update transformer.
-     */
-    private static class AttributesProcessor implements EntryProcessor<String, IgniteWebSession, Void>, Externalizable {
-        /** */
-        private static final long serialVersionUID = 0L;
-
-        /** Updates list. */
-        private Collection<T2<String, Object>> updates;
-
-        /**
-         * Required by {@link Externalizable}.
-         */
-        public AttributesProcessor() {
-            // No-op.
-        }
-
-        /**
-         * @param updates Updates list.
-         */
-        AttributesProcessor(Collection<T2<String, Object>> updates) {
-            assert updates != null;
-
-            this.updates = updates;
-        }
-
-        /** {@inheritDoc} */
-        @Override public Void process(MutableEntry<String, IgniteWebSession> entry, Object... args) {
-            if (!entry.exists())
-                return null;
-
-            IgniteWebSession ses = new IgniteWebSession(entry.getValue());
-
-            for (T2<String, Object> update : updates) {
-                String name = update.get1();
-
-                assert name != null;
-
-                Object val = update.get2();
-
-                if (val != null)
-                    ses.setAttribute(name, val);
-                else
-                    ses.removeAttribute(name);
-            }
-
-            entry.setValue(ses);
-
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void writeExternal(ObjectOutput out) throws IOException {
-            U.writeCollection(out, updates);
-        }
-
-        /** {@inheritDoc} */
-        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-            updates = U.readCollection(in);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
new file mode 100644
index 0000000..dac3b1f
--- /dev/null
+++ b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSession.java
@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.cache.websession;
+
+import org.apache.ignite.internal.util.tostring.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.jetbrains.annotations.*;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * Session implementation.
+ */
+@SuppressWarnings({"deprecation", "NonSerializableObjectBoundToHttpSession"})
+class WebSession implements HttpSession, Externalizable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Empty session context. */
+    private static final HttpSessionContext EMPTY_SES_CTX = new HttpSessionContext() {
+        @Nullable @Override public HttpSession getSession(String id) {
+            return null;
+        }
+
+        @Override public Enumeration<String> getIds() {
+            return Collections.enumeration(Collections.<String>emptyList());
+        }
+    };
+
+    /** Session ID. */
+    private String id;
+
+    /** Creation time. */
+    private long createTime;
+
+    /** Last access time. */
+    private long accessTime;
+
+    /** Maximum inactive interval. */
+    private int maxInactiveInterval;
+
+    /** Attributes. */
+    @GridToStringInclude
+    private Map<String, Object> attrs;
+
+    /** Servlet context. */
+    @GridToStringExclude
+    private transient ServletContext ctx;
+
+    /** Listener. */
+    @GridToStringExclude
+    private transient WebSessionListener lsnr;
+
+    /** New session flag. */
+    private transient boolean isNew;
+
+    /** Updates list. */
+    private transient Collection<T2<String, Object>> updates;
+
+    /**
+     * Required by {@link Externalizable}.
+     */
+    public WebSession() {
+        // No-op.
+    }
+
+    /**
+     * @param ses Session.
+     */
+    WebSession(HttpSession ses) {
+        assert ses != null;
+
+        id = ses.getId();
+        createTime = ses.getCreationTime();
+        accessTime = ses.getLastAccessedTime();
+        maxInactiveInterval = ses.getMaxInactiveInterval();
+        isNew = ses.isNew();
+
+        attrs = new HashMap<>();
+
+        Enumeration<String> names = ses.getAttributeNames();
+
+        while (names.hasMoreElements()) {
+            String name = names.nextElement();
+
+            attrs.put(name, ses.getAttribute(name));
+        }
+    }
+
+    /**
+     * @param ses Session.
+     * @param isNew Is new flag.
+     */
+    WebSession(HttpSession ses, boolean isNew) {
+        this(ses);
+
+        this.isNew = isNew;
+    }
+
+    /**
+     * @param accessTime Last access time.
+     */
+    void accessTime(long accessTime) {
+        this.accessTime = accessTime;
+    }
+
+    /**
+     * @param ctx Servlet context.
+     */
+    public void servletContext(ServletContext ctx) {
+        assert ctx != null;
+
+        this.ctx = ctx;
+    }
+
+    /**
+     * @param lsnr Listener.
+     */
+    public void listener(WebSessionListener lsnr) {
+        assert lsnr != null;
+
+        this.lsnr = lsnr;
+    }
+
+    /**
+     * Resets updates list.
+     */
+    public void resetUpdates() {
+        updates = new LinkedList<>();
+    }
+
+    /**
+     * @return Updates list.
+     */
+    public Collection<T2<String, Object>> updates() {
+        Collection<T2<String, Object>> updates0 = updates;
+
+        updates = null;
+
+        return updates0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getId() {
+        return id;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ServletContext getServletContext() {
+        return ctx;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getCreationTime() {
+        return createTime;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long getLastAccessedTime() {
+        return accessTime;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getMaxInactiveInterval() {
+        return maxInactiveInterval;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setMaxInactiveInterval(int interval) {
+        maxInactiveInterval = interval;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getAttribute(String name) {
+        return attrs.get(name);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getValue(String name) {
+        return attrs.get(name);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Enumeration<String> getAttributeNames() {
+        return Collections.enumeration(attrs.keySet());
+    }
+
+    /** {@inheritDoc} */
+    @Override public String[] getValueNames() {
+        return attrs.keySet().toArray(new String[attrs.size()]);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAttribute(String name, Object val) {
+        attrs.put(name, val);
+
+        if (updates != null)
+            updates.add(new T2<>(name, val));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putValue(String name, Object val) {
+        setAttribute(name, val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeAttribute(String name) {
+        attrs.remove(name);
+
+        if (updates != null)
+            updates.add(new T2<>(name, null));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeValue(String name) {
+        removeAttribute(name);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void invalidate() {
+        attrs.clear();
+
+        updates = null;
+
+        lsnr.destroySession(id);
+    }
+
+    /**
+     * @param isNew New session flag.
+     */
+    void setNew(boolean isNew) {
+        this.isNew = isNew;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isNew() {
+        return isNew;
+    }
+
+    /** {@inheritDoc} */
+    @Override public HttpSessionContext getSessionContext() {
+        return EMPTY_SES_CTX;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        U.writeString(out, id);
+        out.writeLong(createTime);
+        out.writeLong(accessTime);
+        out.writeInt(maxInactiveInterval);
+        U.writeMap(out, attrs);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        id = U.readString(in);
+        createTime = in.readLong();
+        accessTime = in.readLong();
+        maxInactiveInterval = in.readInt();
+        attrs = U.readMap(in);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(WebSession.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/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
new file mode 100644
index 0000000..896c987
--- /dev/null
+++ b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionFilter.java
@@ -0,0 +1,467 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.cache.websession;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.startup.servlet.*;
+import org.apache.ignite.transactions.*;
+
+import javax.cache.*;
+import javax.cache.expiry.*;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+import java.util.*;
+
+import static java.util.concurrent.TimeUnit.*;
+import static org.apache.ignite.cache.CacheAtomicityMode.*;
+import static org.apache.ignite.cache.CacheMode.*;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*;
+import static org.apache.ignite.transactions.TransactionConcurrency.*;
+import static org.apache.ignite.transactions.TransactionIsolation.*;
+
+/**
+ * Filter for web sessions caching.
+ * <p>
+ * This is a request filter, that you need to specify in your {@code web.xml} along
+ * with {@link ServletContextListenerStartup} to enable web sessions caching:
+ * <pre name="code" class="xml">
+ * &lt;listener&gt;
+ *     &lt;listener-class&gt;org.apache.ignite.startup.servlet.IgniteServletContextListenerStartup&lt;/listener-class&gt;
+ * &lt;/listener&gt;
+ *
+ * &lt;filter&gt;
+ *     &lt;filter-name&gt;WebSessionFilter&lt;/filter-name&gt;
+ *     &lt;filter-class&gt;org.apache.ignite.cache.websession.WebSessionFilter&lt;/filter-class&gt;
+ * &lt;/filter&gt;
+ *
+ * &lt;!-- You can also specify a custom URL pattern. --&gt;
+ * &lt;filter-mapping&gt;
+ *     &lt;filter-name&gt;IgniteWebSessionsFilter&lt;/filter-name&gt;
+ *     &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+ * &lt;/filter-mapping&gt;
+ * </pre>
+ * It is also possible to specify a servlet name in a filter mapping, and a servlet URL pattern will
+ * be used in this case:
+ * <pre name="code" class="xml">
+ * &lt;filter&gt;
+ *     &lt;filter-name&gt;WebSessionFilter&lt;/filter-name&gt;
+ *     &lt;filter-class&gt;org.apache.ignite.cache.websession.WebSessionFilter&lt;/filter-class&gt;
+ * &lt;/filter&gt;
+ *
+ * &lt;filter-mapping&gt;
+ *     &lt;filter-name&gt;WebSessionFilter&lt;/filter-name&gt;
+ *     &lt;servlet-name&gt;YourServletName&lt;/servlet-name&gt;
+ * &lt;/filter-mapping&gt;
+ * </pre>
+ * The filter has the following optional configuration parameters:
+ * <table class="doctable">
+ *     <tr>
+ *         <th>Name</th>
+ *         <th>Description</th>
+ *         <th>Default</th>
+ *     </tr>
+ *     <tr>
+ *         <td>IgniteWebSessionsGridName</td>
+ *         <td>Name of the grid that contains cache for web session storage.</td>
+ *         <td>{@code null} (default grid)</td>
+ *     </tr>
+ *     <tr>
+ *         <td>IgniteWebSessionsCacheName</td>
+ *         <td>Name of the cache for web session storage.</td>
+ *         <td>{@code null} (default cache)</td>
+ *     </tr>
+ *     <tr>
+ *         <td>IgniteWebSessionsMaximumRetriesOnFail</td>
+ *         <td>
+ *             Valid for {@code ATOMIC} caches only. Maximum number of retries for session updates in case
+ *             node leaves topology and update fails. If retry is enabled,
+ *             some updates can be applied more than once, otherwise some
+ *             updates can be lost.
+ *             <p>
+ *             To disable retries, set this parameter to {@code 0}.
+ *         </td>
+ *         <td>{@code 3}</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:
+ * <pre name="code" class="xml">
+ * &lt;filter&gt;
+ *     &lt;filter-name&gt;WebSessionFilter&lt;/filter-name&gt;
+ *     &lt;filter-class&gt;org.apache.ignite.cache.websession.WebSessionFilter&lt;/filter-class&gt;
+ *     &lt;init-param&gt;
+ *         &lt;param-name&gt;IgniteWebSessionsGridName&lt;/param-name&gt;
+ *         &lt;param-value&gt;WebGrid&lt;/param-value&gt;
+ *     &lt;/init-param&gt;
+ *     &lt;init-param&gt;
+ *         &lt;param-name&gt;IgniteWebSessionsCacheName&lt;/param-name&gt;
+ *         &lt;param-value&gt;WebCache&lt;/param-value&gt;
+ *     &lt;/init-param&gt;
+ *
+ *     &lt;!-- Valid for ATOMIC caches only. --&gt;
+ *     &lt;init-param&gt;
+ *         &lt;param-name&gt;IgniteWebSessionsMaximumRetriesOnFail&lt;/param-name&gt;
+ *         &lt;param-value&gt;10&lt;/param-value&gt;
+ *     &lt;/init-param&gt;
+ * &lt;/filter&gt;
+ * </pre>
+ * <b>Note:</b> filter init parameter has a priority over servlet context
+ * parameter; if you specify both, the servlet context parameter will be ignored.
+ * <h1 class="header">Web sessions caching and concurrent requests</h1>
+ * If your web application can accept concurrent request for one session,
+ * consider using {@link org.apache.ignite.cache.CacheAtomicityMode#TRANSACTIONAL} cache
+ * instead of {@link org.apache.ignite.cache.CacheAtomicityMode#ATOMIC}. In this case each request
+ * be processed inside pessimistic transaction which will guarantee that all
+ * updates will be applied in correct order. This is important, for example,
+ * if you get some attribute from the session, update its value and set new
+ * value back to the session. In case of {@link org.apache.ignite.cache.CacheAtomicityMode#ATOMIC}
+ * cache concurrent requests can get equal value, but {@link org.apache.ignite.cache.CacheAtomicityMode#TRANSACTIONAL}
+ * cache will always process such updates one after another.
+ */
+public class WebSessionFilter implements Filter {
+    /** Web sessions caching grid name parameter name. */
+    public static final String WEB_SES_NAME_PARAM = "IgniteWebSessionsGridName";
+
+    /** Web sessions caching cache name parameter name. */
+    public static final String WEB_SES_CACHE_NAME_PARAM = "IgniteWebSessionsCacheName";
+
+    /** Web sessions caching retry on fail parameter name (valid for ATOMIC */
+    public static final String WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM = "IgniteWebSessionsMaximumRetriesOnFail";
+
+    /** Default retry on fail flag value. */
+    public static final int DFLT_MAX_RETRIES_ON_FAIL = 3;
+
+    /** Cache. */
+    private IgniteCache<String, WebSession> cache;
+
+    /** Transactions. */
+    private IgniteTransactions txs;
+
+    /** Listener. */
+    private WebSessionListener lsnr;
+
+    /** Logger. */
+    private IgniteLogger log;
+
+    /** Servlet context. */
+    private ServletContext ctx;
+
+    /** Session ID transformer. */
+    private IgniteClosure<String, String> sesIdTransformer;
+
+    /** Transactions enabled flag. */
+    private boolean txEnabled;
+
+    /** {@inheritDoc} */
+    @Override public void init(FilterConfig cfg) throws ServletException {
+        ctx = cfg.getServletContext();
+
+        String gridName = U.firstNotNull(
+            cfg.getInitParameter(WEB_SES_NAME_PARAM),
+            ctx.getInitParameter(WEB_SES_NAME_PARAM));
+
+        String cacheName = U.firstNotNull(
+            cfg.getInitParameter(WEB_SES_CACHE_NAME_PARAM),
+            ctx.getInitParameter(WEB_SES_CACHE_NAME_PARAM));
+
+        String retriesStr = U.firstNotNull(
+            cfg.getInitParameter(WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM),
+            ctx.getInitParameter(WEB_SES_MAX_RETRIES_ON_FAIL_NAME_PARAM));
+
+        int retries;
+
+        try {
+            retries = retriesStr != null ? Integer.parseInt(retriesStr) : DFLT_MAX_RETRIES_ON_FAIL;
+        }
+        catch (NumberFormatException e) {
+            throw new IgniteException("Maximum number of retries parameter is invalid: " + retriesStr, e);
+        }
+
+        Ignite webSesIgnite = G.ignite(gridName);
+
+        if (webSesIgnite == null)
+            throw new IgniteException("Grid for web sessions caching is not started (is it configured?): " +
+                gridName);
+
+        txs = webSesIgnite.transactions();
+
+        log = webSesIgnite.log();
+
+        if (webSesIgnite == null)
+            throw new IgniteException("Grid for web sessions caching is not started (is it configured?): " +
+                gridName);
+
+        cache = webSesIgnite.jcache(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)");
+
+        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);
+
+        String srvInfo = ctx.getServerInfo();
+
+        // Special case for WebLogic, which appends timestamps to session
+        // IDs upon session creation (the created session ID looks like:
+        // pdpTSTcCcG6CVM8BTZWzxjTB1lh3w7zFbYVvwBb4bJGjrBx3TMPl!-508312620!1385045122601).
+        if (srvInfo != null && srvInfo.contains("WebLogic")) {
+            sesIdTransformer = new C1<String, String>() {
+                @Override public String apply(String s) {
+                    // Find first exclamation mark.
+                    int idx = s.indexOf('!');
+
+                    // Return original string if not found.
+                    if (idx < 0 || idx == s.length() - 1)
+                        return s;
+
+                    // Find second exclamation mark.
+                    idx = s.indexOf('!', idx + 1);
+
+                    // Return original string if not found.
+                    if (idx < 0)
+                        return s;
+
+                    // Return the session ID without timestamp.
+                    return s.substring(0, idx);
+                }
+            };
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void destroy() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+        throws IOException, ServletException {
+        assert ctx != null;
+
+        if (req instanceof HttpServletRequest) {
+            HttpServletRequest httpReq = (HttpServletRequest)req;
+
+            String sesId = null;
+
+            try {
+                if (txEnabled) {
+                    try (Transaction tx = txs.txStart(PESSIMISTIC, REPEATABLE_READ)) {
+                        sesId = doFilter0(httpReq, res, chain);
+
+                        tx.commit();
+                    }
+                }
+                else
+                    sesId = doFilter0(httpReq, res, chain);
+            }
+            catch (Exception e) {
+                U.error(log, "Failed to update web session: " + sesId, e);
+            }
+        }
+        else
+            chain.doFilter(req, res);
+    }
+
+    /**
+     * @param httpReq Request.
+     * @param res Response.
+     * @param chain Filter chain.
+     * @return Session ID.
+     * @throws IOException In case of I/O error.
+     * @throws ServletException In case oif servlet error.
+     * @throws CacheException In case of other error.
+     */
+    private String doFilter0(HttpServletRequest httpReq, ServletResponse res, FilterChain chain) throws IOException,
+        ServletException, CacheException {
+        WebSession cached;
+
+        String sesId = httpReq.getRequestedSessionId();
+
+        if (sesId != null) {
+            cached = cache.get(sesId);
+
+            if (cached != null) {
+                if (log.isDebugEnabled())
+                    log.debug("Using cached session for ID: " + sesId);
+
+                if (cached.isNew())
+                    cached = new WebSession(cached, false);
+            }
+            else {
+                if (log.isDebugEnabled())
+                    log.debug("Cached session was invalidated and doesn't exist: " + sesId);
+
+                HttpSession ses = httpReq.getSession(false);
+
+                if (ses != null) {
+                    try {
+                        ses.invalidate();
+                    }
+                    catch (IllegalStateException ignore) {
+                        // Session was already invalidated.
+                    }
+                }
+
+                cached = createSession(httpReq);
+            }
+        }
+        else {
+            cached = createSession(httpReq);
+
+            sesId = cached.getId();
+        }
+
+        assert cached != null;
+
+        cached.servletContext(ctx);
+        cached.listener(lsnr);
+        cached.resetUpdates();
+
+        httpReq = new RequestWrapper(httpReq, cached);
+
+        chain.doFilter(httpReq, res);
+
+        HttpSession ses = httpReq.getSession(false);
+
+        if (ses != null && ses instanceof WebSession) {
+            Collection<T2<String, Object>> updates = ((WebSession)ses).updates();
+
+            if (updates != null)
+                lsnr.updateAttributes(ses.getId(), updates, ses.getMaxInactiveInterval());
+        }
+
+        return sesId;
+    }
+
+    /**
+     * @param httpReq HTTP request.
+     * @return Cached session.
+     */
+    @SuppressWarnings("unchecked")
+    private WebSession createSession(HttpServletRequest httpReq) {
+        HttpSession ses = httpReq.getSession(true);
+
+        String sesId = sesIdTransformer != null ? sesIdTransformer.apply(ses.getId()) : ses.getId();
+
+        if (log.isDebugEnabled())
+            log.debug("Session created: " + sesId);
+
+        WebSession cached = new WebSession(ses, true);
+
+        try {
+            while (true) {
+                try {
+                    IgniteCache<String, WebSession> cache0;
+
+                    if (cached.getMaxInactiveInterval() > 0) {
+                        long ttl = cached.getMaxInactiveInterval() * 1000;
+
+                        ExpiryPolicy plc = new ModifiedExpiryPolicy(new Duration(MILLISECONDS, ttl));
+
+                        cache0 = cache.withExpiryPolicy(plc);
+                    }
+                    else
+                        cache0 = cache;
+
+                    WebSession old = cache0.getAndPutIfAbsent(sesId, cached);
+
+                    if (old != null) {
+                        cached = old;
+
+                        if (cached.isNew())
+                            cached = new WebSession(cached, false);
+                    }
+
+                    break;
+                }
+                catch (CachePartialUpdateException e) {
+                    if (log.isDebugEnabled())
+                        log.debug(e.getMessage());
+                }
+            }
+        }
+        catch (CacheException e) {
+            throw new IgniteException("Failed to save session: " + sesId, e);
+        }
+
+        return cached;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(WebSessionFilter.class, this);
+    }
+
+    /**
+     * Request wrapper.
+     */
+    private static class RequestWrapper extends HttpServletRequestWrapper {
+        /** Session. */
+        private final WebSession ses;
+
+        /**
+         * @param req Request.
+         * @param ses Session.
+         */
+        private RequestWrapper(HttpServletRequest req, WebSession ses) {
+            super(req);
+
+            assert ses != null;
+
+            this.ses = ses;
+        }
+
+        /** {@inheritDoc} */
+        @Override public HttpSession getSession(boolean create) {
+            return ses;
+        }
+
+        /** {@inheritDoc} */
+        @Override public HttpSession getSession() {
+            return ses;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/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
new file mode 100644
index 0000000..442f83f
--- /dev/null
+++ b/modules/web/src/main/java/org/apache/ignite/cache/websession/WebSessionListener.java
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+package org.apache.ignite.cache.websession;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+import javax.cache.*;
+import javax.cache.expiry.*;
+import javax.cache.processor.*;
+import java.io.*;
+import java.util.*;
+
+import static java.util.concurrent.TimeUnit.*;
+
+/**
+ * Session listener for web sessions caching.
+ */
+class WebSessionListener {
+    /** */
+    private static final long RETRY_DELAY = 1;
+
+    /** Cache. */
+    private final IgniteCache<String, WebSession> cache;
+
+    /** Maximum retries. */
+    private final int retries;
+
+    /** Logger. */
+    private final IgniteLogger log;
+
+    /**
+     * @param ignite Grid.
+     * @param cache Cache.
+     * @param retries Maximum retries.
+     */
+    WebSessionListener(Ignite ignite, IgniteCache<String, WebSession> cache, int retries) {
+        assert ignite != null;
+        assert cache != null;
+
+        this.cache = cache;
+        this.retries = retries > 0 ? retries : 1;
+
+        log = ignite.log();
+    }
+
+    /**
+     * @param sesId Session ID.
+     */
+    public void destroySession(String sesId) {
+        assert sesId != null;
+
+        try {
+            if (cache.remove(sesId) && log.isDebugEnabled())
+                log.debug("Session destroyed: " + sesId);
+        }
+        catch (CacheException e) {
+            U.error(log, "Failed to remove session: " + sesId, e);
+        }
+    }
+
+    /**
+     * @param sesId Session ID.
+     * @param updates Updates list.
+     * @param maxInactiveInterval Max session inactive interval.
+     */
+    @SuppressWarnings("unchecked")
+    public void updateAttributes(String sesId, Collection<T2<String, Object>> updates, int maxInactiveInterval) {
+        assert sesId != null;
+        assert updates != null;
+
+        if (log.isDebugEnabled())
+            log.debug("Session attributes updated [id=" + sesId + ", updates=" + updates + ']');
+
+        try {
+            for (int i = 0; i < retries; i++) {
+                try {
+                    IgniteCache<String, WebSession> cache0;
+
+                    if (maxInactiveInterval > 0) {
+                        long ttl = maxInactiveInterval * 1000;
+
+                        ExpiryPolicy plc = new ModifiedExpiryPolicy(new Duration(MILLISECONDS, ttl));
+
+                        cache0 = cache.withExpiryPolicy(plc);
+                    }
+                    else
+                        cache0 = cache;
+
+                    cache0.invoke(sesId, new AttributesProcessor(updates));
+
+                    break;
+                }
+                catch (CachePartialUpdateException ignored) {
+                    if (i == retries - 1) {
+                        U.warn(log, "Failed to apply updates for session (maximum number of retries exceeded) [sesId=" +
+                            sesId + ", retries=" + retries + ']');
+                    }
+                    else {
+                        U.warn(log, "Failed to apply updates for session (will retry): " + sesId);
+
+                        U.sleep(RETRY_DELAY);
+                    }
+                }
+            }
+        }
+        catch (CacheException | IgniteInterruptedCheckedException e) {
+            U.error(log, "Failed to update session attributes [id=" + sesId + ']', e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(WebSessionListener.class, this);
+    }
+
+    /**
+     * Multiple attributes update transformer.
+     */
+    private static class AttributesProcessor implements EntryProcessor<String, WebSession, Void>, Externalizable {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Updates list. */
+        private Collection<T2<String, Object>> updates;
+
+        /**
+         * Required by {@link Externalizable}.
+         */
+        public AttributesProcessor() {
+            // No-op.
+        }
+
+        /**
+         * @param updates Updates list.
+         */
+        AttributesProcessor(Collection<T2<String, Object>> updates) {
+            assert updates != null;
+
+            this.updates = updates;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Void process(MutableEntry<String, WebSession> entry, Object... args) {
+            if (!entry.exists())
+                return null;
+
+            WebSession ses = new WebSession(entry.getValue());
+
+            for (T2<String, Object> update : updates) {
+                String name = update.get1();
+
+                assert name != null;
+
+                Object val = update.get2();
+
+                if (val != null)
+                    ses.setAttribute(name, val);
+                else
+                    ses.removeAttribute(name);
+            }
+
+            entry.setValue(ses);
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(ObjectOutput out) throws IOException {
+            U.writeCollection(out, updates);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            updates = U.readCollection(in);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletContextListenerStartup.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletContextListenerStartup.java b/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletContextListenerStartup.java
deleted file mode 100644
index 18d6bc4..0000000
--- a/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletContextListenerStartup.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.ignite.startup.servlet;
-
-import org.apache.ignite.*;
-import org.apache.ignite.configuration.*;
-import org.apache.ignite.internal.*;
-import org.apache.ignite.internal.processors.resource.*;
-import org.apache.ignite.internal.util.typedef.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-import org.apache.ignite.lang.*;
-
-import javax.servlet.*;
-import java.net.*;
-import java.util.*;
-
-/**
- * This class defines Ignite startup based on servlet context listener.
- * This startup can be used to start Ignite inside any web container.
- * <p>
- * This startup must be defined in {@code web.xml} file.
- * <pre name="code" class="xml">
- * &lt;listener&gt;
- *     &lt;listener-class&gt;org.apache.ignite.startup.servlet.IgniteServletContextListenerStartup&lt;/listener-class&gt;
- * &lt;/listener&gt;
- *
- * &lt;context-param&gt;
- *     &lt;param-name&gt;IgniteConfigurationFilePath&lt;/param-name&gt;
- *     &lt;param-value&gt;config/default-config.xml&lt;/param-value&gt;
- * &lt;/context-param&gt;
- * </pre>
- * <p>
- * Servlet context listener based startup may be used in any web container like Tomcat, Jetty and etc.
- * Depending on the way this startup is deployed the Ignite instance can be accessed
- * by either all web applications or by only one. See web container class loading architecture:
- * <ul>
- * <li><a target=_blank href="http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html">http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html</a></li>
- * <li><a target=_blank href="http://docs.codehaus.org/display/JETTY/Classloading">http://docs.codehaus.org/display/JETTY/Classloading</a></li>
- * </ul>
- * <p>
- * <h2 class="header">Tomcat</h2>
- * There are two ways to start Ignite on Tomcat.
- * <ul>
- * <li>Ignite started when web container starts and Ignite instance is accessible only to all web applications.
- *     <ol>
- *     <li>Add Ignite libraries in Tomcat common loader.
- *         Add in file {@code $TOMCAT_HOME/conf/catalina.properties} for property {@code common.loader}
- *         the following {@code $IGNITE_HOME/*.jar,$IGNITE_HOME/libs/*.jar}
- *         (replace {@code $IGNITE_HOME} with absolute path).
- *     </li>
- *     <li>Configure this startup in {@code $TOMCAT_HOME/conf/web.xml}
- *         <pre name="code" class="xml">
- *         &lt;listener&gt;
- *             &lt;listener-class&gt;org.apache.ignite.startup.servlet.IgniteServletContextListenerStartup&lt;/listener-class&gt;
- *         &lt;/listener&gt;
- *
- *         &lt;context-param&gt;
- *             &lt;param-name&gt;IgniteConfigurationFilePath&lt;/param-name&gt;
- *             &lt;param-value&gt;config/default-config.xml&lt;/param-value&gt;
- *         &lt;/context-param&gt;
- *         </pre>
- *     </li>
- *     </ol>
- * </li>
- * <li>
- * Ignite started from WAR-file and Ignite instance is accessible only to that web application.
- * Difference with approach described above is that {@code web.xml} file and all libraries should
- * be added in WAR file without changes in Tomcat configuration files.
- * </li>
- * </ul>
- */
-public class IgniteServletContextListenerStartup implements ServletContextListener {
-    /** Configuration file path parameter name. */
-    public static final String IGNITE_CFG_FILE_PATH_PARAM = "IgniteConfigurationFilePath";
-
-    /** Names of started grids. */
-    private final Collection<String> gridNames = new ArrayList<>();
-
-    /** {@inheritDoc} */
-    @Override public void contextInitialized(ServletContextEvent evt) {
-        ServletContext ctx = evt.getServletContext();
-
-        String cfgFile = ctx.getInitParameter(IGNITE_CFG_FILE_PATH_PARAM);
-
-        Collection<IgniteConfiguration> cfgs;
-        GridSpringResourceContext rsrcCtx = null;
-
-        if (cfgFile != null) {
-            URL cfgUrl = null;
-
-            try {
-                cfgUrl = evt.getServletContext().getResource("/META-INF/" + cfgFile);
-            }
-            catch (MalformedURLException ignored) {
-                // Ignore, we still need to try with IGNITE_HOME.
-            }
-
-            if (cfgUrl == null)
-                // Try with IGNITE_HOME and with context class loader.
-                cfgUrl = U.resolveIgniteUrl(cfgFile);
-
-            if (cfgUrl == null)
-                throw new IgniteException("Failed to find Spring configuration file (path provided should be " +
-                    "either absolute, relative to IGNITE_HOME, or relative to META-INF folder): " + cfgFile);
-
-            IgniteBiTuple<Collection<IgniteConfiguration>, ? extends GridSpringResourceContext> t;
-
-            try {
-                t = IgnitionEx.loadConfigurations(cfgUrl);
-            }
-            catch (IgniteCheckedException e) {
-                throw new IgniteException("Failed to load Ignite configuration.", e);
-            }
-
-            cfgs = t.get1();
-            rsrcCtx  = t.get2();
-
-            if (cfgs.isEmpty())
-                throw new IgniteException("Can't find grid factory configuration in: " + cfgUrl);
-        }
-        else
-            cfgs = Collections.<IgniteConfiguration>singleton(new IgniteConfiguration());
-
-        try {
-            assert !cfgs.isEmpty();
-
-            for (IgniteConfiguration cfg : cfgs) {
-                assert cfg != null;
-
-                Ignite ignite;
-
-                synchronized (IgniteServletContextListenerStartup.class) {
-                    try {
-                        ignite = G.ignite(cfg.getGridName());
-                    }
-                    catch (IgniteIllegalStateException ignored) {
-                        ignite = IgnitionEx.start(new IgniteConfiguration(cfg), rsrcCtx);
-                    }
-                }
-
-                // Check if grid is not null - started properly.
-                if (ignite != null)
-                    gridNames.add(ignite.name());
-            }
-        }
-        catch (IgniteCheckedException e) {
-            // Stop started grids only.
-            for (String name : gridNames)
-                G.stop(name, true);
-
-            throw new IgniteException("Failed to start Ignite.", e);
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override public void contextDestroyed(ServletContextEvent evt) {
-        // Stop started grids only.
-        for (String name: gridNames)
-            G.stop(name, true);
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(IgniteServletContextListenerStartup.class, this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2bf5da74/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletStartup.java
----------------------------------------------------------------------
diff --git a/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletStartup.java b/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletStartup.java
deleted file mode 100644
index 3824596..0000000
--- a/modules/web/src/main/java/org/apache/ignite/startup/servlet/IgniteServletStartup.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.
- */
-
-package org.apache.ignite.startup.servlet;
-
-import org.apache.ignite.*;
-import org.apache.ignite.configuration.*;
-import org.apache.ignite.internal.*;
-import org.apache.ignite.internal.processors.resource.*;
-import org.apache.ignite.internal.util.typedef.*;
-import org.apache.ignite.internal.util.typedef.internal.*;
-import org.apache.ignite.lang.*;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-import java.net.*;
-import java.util.*;
-
-/**
- * This class defines servlet-based Ignite startup. This startup can be used to start Ignite
- * inside any web container as servlet.
- * <p>
- * This startup must be defined in {@code web.xml} file.
- * <pre name="code" class="xml">
- * &lt;servlet&gt;
- *     &lt;servlet-name&gt;Ignite&lt;/servlet-name&gt;
- *     &lt;servlet-class&gt;org.apache.ignite.startup.servlet.IgniteServletStartup&lt;/servlet-class&gt;
- *     &lt;init-param&gt;
- *         &lt;param-name&gt;cfgFilePath&lt;/param-name&gt;
- *         &lt;param-value&gt;config/default-config.xml&lt;/param-value&gt;
- *     &lt;/init-param&gt;
- *     &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
- * &lt;/servlet&gt;
- * </pre>
- * <p>
- * Servlet-based startup may be used in any web container like Tomcat, Jetty and etc.
- * Depending on the way this startup is deployed the Ignite instance can be accessed
- * by either all web applications or by only one. See web container class loading architecture:
- * <ul>
- * <li><a target=_blank href="http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html">http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html</a></li>
- * <li><a target=_blank href="http://docs.codehaus.org/display/JETTY/Classloading">http://docs.codehaus.org/display/JETTY/Classloading</a></li>
- * </ul>
- * <p>
- * <h2 class="header">Tomcat</h2>
- * There are two ways to start Ignite on Tomcat.
- * <ul>
- * <li>Ignite started when web container starts and Ignite instance is accessible only to all web applications.
- * <ol>
- *     <li>Add Ignite libraries in Tomcat common loader.
- *         Add in file {@code $TOMCAT_HOME/conf/catalina.properties} for property {@code shared.loader}
- *         the following {@code $IGNITE_HOME/ignite.jar,$IGNITE_HOME/libs/*.jar}
- *         (replace {@code $IGNITE_HOME} with absolute path).
- *     </li>
- *     <li>Configure startup in {@code $TOMCAT_HOME/conf/web.xml}
- *         <pre name="code" class="xml">
- *         &lt;servlet&gt;
- *             &lt;servlet-name&gt;Ignite&lt;/servlet-name&gt;
- *             &lt;servlet-class&gt;org.apache.ignite.startup.servlet.IgniteServletStartup&lt;/servlet-class&gt;
- *             &lt;init-param&gt;
- *                 &lt;param-name&gt;cfgFilePath&lt;/param-name&gt;
- *                 &lt;param-value&gt;config/default-config.xml&lt;/param-value&gt;
- *             &lt;/init-param&gt;
- *             &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
- *         &lt;/servlet&gt;
- *         </pre>
- *     </li>
- *     </ol>
- * </li>
- * <li>
- * Ignite started from WAR-file and Ignite instance is accessible only to that web application.
- * Difference with approach described above is that {@code web.xml} file and all libraries should
- * be added in WAR file without changes in Tomcat configuration files.
- * </li>
- * </ul>
- * <p>
- * <h2 class="header">Jetty</h2>
- * Below is Java code example with Jetty API:
- * <pre name="code" class="java">
- * Server service = new Server();
- *
- * service.addListener("localhost:8090");
- *
- * ServletHttpContext ctx = (ServletHttpContext)service.getContext("/");
- *
- * ServletHolder servlet = ctx.addServlet("Ignite", "/IgniteStartup",
- *      "org.apache.ignite.startup.servlet.IgniteServletStartup");
- *
- * servlet.setInitParameter("cfgFilePath", "config/default-config.xml");
- *
- * servlet.setInitOrder(1);
- *
- * servlet.start();
- *
- * service.start();
- * </pre>
- */
-public class IgniteServletStartup extends HttpServlet {
-    /** */
-    private static final long serialVersionUID = 0L;
-
-    /** Grid loaded flag. */
-    private static boolean loaded;
-
-    /** Configuration file path variable name. */
-    private static final String cfgFilePathParam = "cfgFilePath";
-
-    /** */
-    private Collection<String> gridNames = new ArrayList<>();
-
-    /** {@inheritDoc} */
-    @SuppressWarnings({"unchecked"})
-    @Override public void init() throws ServletException {
-        // Avoid multiple servlet instances. Ignite should be loaded once.
-        if (loaded)
-            return;
-
-        String cfgFile = getServletConfig().getInitParameter(cfgFilePathParam);
-
-        if (cfgFile == null)
-            throw new ServletException("Failed to read property: " + cfgFilePathParam);
-
-        URL cfgUrl = U.resolveIgniteUrl(cfgFile);
-
-        if (cfgUrl == null)
-            throw new ServletException("Failed to find Spring configuration file (path provided should be " +
-                "either absolute, relative to IGNITE_HOME, or relative to META-INF folder): " + cfgFile);
-
-        try {
-            IgniteBiTuple<Collection<IgniteConfiguration>, ? extends GridSpringResourceContext> t =
-                IgnitionEx.loadConfigurations(cfgUrl);
-
-            Collection<IgniteConfiguration> cfgs = t.get1();
-
-            if (cfgs == null)
-                throw new ServletException("Failed to find a single grid factory configuration in: " + cfgUrl);
-
-            for (IgniteConfiguration cfg : cfgs) {
-                assert cfg != null;
-
-                IgniteConfiguration adapter = new IgniteConfiguration(cfg);
-
-                Ignite ignite = IgnitionEx.start(adapter, t.get2());
-
-                // Test if grid is not null - started properly.
-                if (ignite != null)
-                    gridNames.add(ignite.name());
-            }
-        }
-        catch (IgniteCheckedException e) {
-            // Stop started grids only.
-            for (String name: gridNames)
-                G.stop(name, true);
-
-            throw new ServletException("Failed to start Ignite.", e);
-        }
-
-        loaded = true;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void destroy() {
-        // Stop started grids only.
-        for (String name: gridNames)
-            G.stop(name, true);
-
-        loaded = false;
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(IgniteServletStartup.class, this);
-    }
-}


Mime
View raw message