You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/12/07 09:00:33 UTC

[18/24] cayenne git commit: CAY-2372. Change package name to previous one.

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
new file mode 100644
index 0000000..ea1b33d
--- /dev/null
+++ b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/StatelessContextRequestHandler.java
@@ -0,0 +1,72 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.BaseContext;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.apache.cayenne.configuration.ObjectContextFactory;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Injector;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * <p>Stateless implementation of {@link RequestHandler} that creates a new
+ * {@link ObjectContext} for each request and binds it to the request thread.
+ * <p>
+ * This is an alternative to the session-based request handler
+ * {@link SessionContextRequestHandler} which is the default.
+ * <p>
+ * The request handler can be used by injecting it with a custom @{link Module}, like so:
+ *
+<pre><code>
+import org.apache.cayenne.configuration.web.RequestHandler;
+import org.apache.cayenne.configuration.web.StatelessContextRequestHandler;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+public class AppModule implements Module {
+    public void configure(Binder binder) {
+        binder.bind(RequestHandler.class).to(StatelessContextRequestHandler.class);
+    }
+}
+</code></pre>
+ *
+ * @since 4.0
+ */
+public class StatelessContextRequestHandler implements RequestHandler {
+
+    // using injector to lookup services instead of injecting them directly for lazy
+    // startup and "late binding"
+    @Inject
+    private Injector injector;
+
+    public void requestStart(ServletRequest request, ServletResponse response) {
+        CayenneRuntime.bindThreadInjector(injector);
+        ObjectContext context = injector.getInstance(ObjectContextFactory.class).createContext();
+        BaseContext.bindThreadObjectContext(context);
+    }
+
+    public void requestEnd(ServletRequest request, ServletResponse response) {
+        CayenneRuntime.bindThreadInjector(null);
+        BaseContext.bindThreadObjectContext(null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebConfiguration.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebConfiguration.java b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebConfiguration.java
new file mode 100644
index 0000000..6b2efbc
--- /dev/null
+++ b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebConfiguration.java
@@ -0,0 +1,183 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.util.Util;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import java.util.*;
+
+/**
+ * A class that provides access to common Cayenne web configuration parameters retrieved
+ * either from a FilterConfig or a ServletConfig configuration.
+ * 
+ * @since 3.1
+ */
+public class WebConfiguration {
+
+    static final String CONFIGURATION_LOCATION_PARAMETER = "configuration-location";
+    static final String EXTRA_MODULES_PARAMETER = "extra-modules";
+
+    private FilterConfig configuration;
+
+    public WebConfiguration(final ServletConfig servletConfiguration) {
+        this.configuration = new FilterConfig() {
+
+            public ServletContext getServletContext() {
+                return servletConfiguration.getServletContext();
+            }
+
+            @SuppressWarnings("all")
+            public Enumeration getInitParameterNames() {
+                return servletConfiguration.getInitParameterNames();
+            }
+
+            public String getInitParameter(String name) {
+                return servletConfiguration.getInitParameter(name);
+            }
+
+            public String getFilterName() {
+                return servletConfiguration.getServletName();
+            }
+        };
+    }
+
+    public WebConfiguration(FilterConfig filterConfiguration) {
+        this.configuration = filterConfiguration;
+    }
+
+    /**
+     * Returns a non-null location of an XML Cayenne configuration, extracted from the
+     * filter or servlet configuration parameters.
+     */
+    public String getConfigurationLocation() {
+        String configurationLocation = configuration
+                .getInitParameter(CONFIGURATION_LOCATION_PARAMETER);
+
+        if (configurationLocation != null) {
+            return configurationLocation;
+        }
+
+        String name = configuration.getFilterName();
+
+        if (name == null) {
+            return null;
+        }
+
+        if (!name.endsWith(".xml")) {
+            name = name + ".xml";
+        }
+
+        return name;
+    }
+
+    /**
+     * Creates and returns a collection of modules made of provided standard modules and
+     * extra custom modules specified via an optional "extra-modules" init parameter. The
+     * value of the parameter is expected to be a comma or space-separated list of class
+     * names, with each class implementing {@link Module} interface. Each custom module
+     * must have a no-arg constructor. If a module of this type is already in the modules
+     * collection, such module is skipped.
+     */
+    public Collection<Module> createModules(Module... standardModules)
+            throws ServletException {
+
+        Set<String> existingModules = new HashSet<>();
+        Collection<Module> modules = new ArrayList<>();
+
+        if (standardModules != null) {
+            for (Module module : standardModules) {
+                modules.add(module);
+                existingModules.add(module.getClass().getName());
+            }
+        }
+
+        String extraModules = configuration.getInitParameter(EXTRA_MODULES_PARAMETER);
+        if (extraModules != null) {
+
+            StringTokenizer toks = new StringTokenizer(extraModules, ", \n\r");
+            while (toks.hasMoreTokens()) {
+                String moduleName = toks.nextToken();
+
+                if (!existingModules.add(moduleName)) {
+                    continue;
+                }
+
+                Module module;
+                try {
+                    module = (Module) Util.getJavaClass(moduleName).newInstance();
+                }
+                catch (Exception e) {
+                    String message = String
+                            .format(
+                                    "Error instantiating custom DI module '%s' by filter '%s': %s",
+                                    moduleName,
+                                    getClass().getName(),
+                                    e.getMessage());
+                    throw new ServletException(message, e);
+                }
+
+                modules.add(module);
+            }
+        }
+
+        return modules;
+    }
+
+    /**
+     * Returns a map of all init parameters from the underlying FilterConfig or
+     * ServletConfig object.
+     */
+    public Map<String, String> getParameters() {
+        Enumeration<?> en = configuration.getInitParameterNames();
+
+        if (!en.hasMoreElements()) {
+            return Collections.EMPTY_MAP;
+        }
+
+        Map<String, String> parameters = new HashMap<>();
+        while (en.hasMoreElements()) {
+            String key = (String) en.nextElement();
+            parameters.put(key, configuration.getInitParameter(key));
+        }
+
+        return parameters;
+    }
+
+    /**
+     * Returns servlet or filter init parameters, excluding those recognized by
+     * WebConfiguration. Namely 'configuration-location' and 'extra-modules' parameters
+     * are removed from the returned map.
+     */
+    public Map<String, String> getOtherParameters() {
+
+        Map<String, String> parameters = getParameters();
+
+        if (!parameters.isEmpty()) {
+            parameters.remove(CONFIGURATION_LOCATION_PARAMETER);
+            parameters.remove(EXTRA_MODULES_PARAMETER);
+        }
+
+        return parameters;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebModule.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebModule.java b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebModule.java
new file mode 100644
index 0000000..292df4c
--- /dev/null
+++ b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebModule.java
@@ -0,0 +1,35 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+
+/**
+ * @since 3.1
+ */
+public class WebModule implements Module {
+
+    public void configure(Binder binder) {
+        binder
+                .bind(RequestHandler.class)
+                .to(SessionContextRequestHandler.class)
+                .withoutScope();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebServerModuleProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebServerModuleProvider.java b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebServerModuleProvider.java
new file mode 100644
index 0000000..47e165e
--- /dev/null
+++ b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebServerModuleProvider.java
@@ -0,0 +1,25 @@
+package org.apache.cayenne.configuration.web;
+
+import org.apache.cayenne.configuration.server.CayenneServerModuleProvider;
+import org.apache.cayenne.di.Module;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class WebServerModuleProvider implements CayenneServerModuleProvider{
+
+    @Override
+    public Module module() {
+        return new WebModule();
+    }
+
+    @Override
+    public Class<? extends Module> moduleType() {
+        return WebModule.class;
+    }
+
+    @Override
+    public Collection<Class<? extends Module>> overrides() {
+        return Collections.emptyList();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
new file mode 100644
index 0000000..9dace8d
--- /dev/null
+++ b/cayenne-web/src/main/java/org/apache/cayenne/configuration/web/WebUtil.java
@@ -0,0 +1,54 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.configuration.CayenneRuntime;
+
+import javax.servlet.ServletContext;
+
+/**
+ * A helper class to retrieve and store {@link CayenneRuntime} in the
+ * {@link ServletContext}. All Cayenne web configuration objects, such as
+ * {@link CayenneFilter} and {@link org.apache.cayenne.rop.ROPServlet}, are using this class to access
+ * runtime.
+ * 
+ * @since 3.1
+ */
+public class WebUtil {
+
+    static final String CAYENNE_RUNTIME_KEY = WebUtil.class.getName()
+            + ".CAYENNE_RUNTIME";
+
+    /**
+     * Retrieves CayenneRuntime previously stored in provided context via
+     * {@link #setCayenneRuntime(ServletContext, CayenneRuntime)}. May return null if no
+     * runtime was stored.
+     */
+    public static CayenneRuntime getCayenneRuntime(ServletContext context) {
+        return (CayenneRuntime) context.getAttribute(CAYENNE_RUNTIME_KEY);
+    }
+
+    /**
+     * Stores {@link CayenneRuntime} in the servlet context. It can be later retrieve via
+     * {@link #getCayenneRuntime(ServletContext)}.
+     */
+    public static void setCayenneRuntime(ServletContext context, CayenneRuntime runtime) {
+        context.setAttribute(CAYENNE_RUNTIME_KEY, runtime);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/java/org/apache/cayenne/web/CayenneFilter.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/java/org/apache/cayenne/web/CayenneFilter.java b/cayenne-web/src/main/java/org/apache/cayenne/web/CayenneFilter.java
deleted file mode 100644
index 0bddc67..0000000
--- a/cayenne-web/src/main/java/org/apache/cayenne/web/CayenneFilter.java
+++ /dev/null
@@ -1,124 +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.cayenne.web;
-
-import org.apache.cayenne.configuration.CayenneRuntime;
-import org.apache.cayenne.configuration.server.ServerModule;
-import org.apache.cayenne.configuration.server.ServerRuntime;
-import org.apache.cayenne.di.Module;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-
-/**
- * A filter that creates a Cayenne server runtime, possibly including custom modules. By
- * default runtime includes {@link ServerModule} and {@link WebModule}. Any custom modules
- * are loaded after the two standard ones to allow custom service overrides. Filter
- * initialization parameters:
- * <ul>
- * <li>configuration-location - (optional) a name of Cayenne configuration XML file that
- * will be used to load Cayenne stack. If missing, the filter name will be used to derive
- * the location. ".xml" extension will be appended to the filter name to get the location,
- * so a filter named "cayenne-foo" will result in location "cayenne-foo.xml".
- * <li>extra-modules - (optional) a comma or space-separated list of class names, with
- * each class implementing {@link Module} interface. These are the custom modules loaded
- * after the two standard ones that allow users to override any Cayenne runtime aspects,
- * e.g. {@link RequestHandler}. Each custom module must have a no-arg constructor.
- * </ul>
- * <p>
- * CayenneFilter is a great utility to quickly start a Cayenne application. More advanced
- * apps most likely will not use it, relying on their own configuration mechanism (such as
- * Guice, Spring, etc.)
- * 
- * @since 3.1
- */
-public class CayenneFilter implements Filter {
-
-    protected ServletContext servletContext;
-
-    public void init(FilterConfig config) throws ServletException {
-
-        checkAlreadyConfigured(config.getServletContext());
-
-        this.servletContext = config.getServletContext();
-
-        WebConfiguration configAdapter = new WebConfiguration(config);
-
-        String configurationLocation = configAdapter.getConfigurationLocation();
-        Collection<Module> modules = configAdapter.createModules();
-        modules.addAll(getAdditionalModules());
-
-        ServerRuntime runtime = ServerRuntime.builder()
-                .addConfig(configurationLocation)
-                .addModules(modules).build();
-
-        WebUtil.setCayenneRuntime(config.getServletContext(), runtime);
-    }
-
-    /**
-     * Subclasses may override this to specify additional modules that should be included when creating the CayenneRuntime
-     * (in addition to those specified in the web.xml file).
-     * 
-     * @since 4.0
-     */
-    protected Collection<Module> getAdditionalModules() {
-		return new ArrayList<>();
-	}
-
-    protected void checkAlreadyConfigured(ServletContext context) throws ServletException {
-        // sanity check
-        if (WebUtil.getCayenneRuntime(context) != null) {
-            throw new ServletException(
-                    "CayenneRuntime is already configured in the servlet environment");
-        }
-    }
-
-    public void destroy() {
-        CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext);
-
-        if (runtime != null) {
-            runtime.shutdown();
-        }
-    }
-
-    public void doFilter(
-            ServletRequest request,
-            ServletResponse response,
-            FilterChain chain) throws IOException, ServletException {
-
-        CayenneRuntime runtime = WebUtil.getCayenneRuntime(servletContext);
-        RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
-
-        handler.requestStart(request, response);
-        try {
-            chain.doFilter(request, response);
-        }
-        finally {
-            handler.requestEnd(request, response);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
----------------------------------------------------------------------
diff --git a/cayenne-web/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider b/cayenne-web/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
index ddca4fc..9ba82dd 100644
--- a/cayenne-web/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
+++ b/cayenne-web/src/main/resources/META-INF/services/org.apache.cayenne.configuration.server.CayenneServerModuleProvider
@@ -17,4 +17,4 @@
 #  under the License.
 ##################################################################
 
-org.apache.cayenne.web.WebServerModuleProvider
\ No newline at end of file
+org.apache.cayenne.configuration.web.WebServerModuleProvider
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilterTest.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilterTest.java
new file mode 100644
index 0000000..c4e5163
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilterTest.java
@@ -0,0 +1,179 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import com.mockrunner.mock.web.*;
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.di.Key;
+import org.apache.cayenne.di.Module;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class CayenneFilterTest {
+
+    @Test
+	public void testInitWithFilterName() throws Exception {
+
+		MockFilterConfig config = new MockFilterConfig();
+		config.setFilterName("abc");
+
+		MockServletContext context = new MockServletContext();
+		config.setupServletContext(context);
+
+		CayenneFilter filter = new CayenneFilter();
+
+		assertNull(WebUtil.getCayenneRuntime(context));
+		filter.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+
+		List<String> locations = runtime.getInjector().getInstance(
+				Key.getListOf(String.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
+
+		assertEquals(Arrays.asList("abc.xml"), locations);
+	}
+
+    @Test
+	public void testInitWithLocation() throws Exception {
+
+		MockFilterConfig config = new MockFilterConfig();
+		config.setFilterName("abc");
+		config.setInitParameter(WebConfiguration.CONFIGURATION_LOCATION_PARAMETER, "xyz");
+
+		MockServletContext context = new MockServletContext();
+		config.setupServletContext(context);
+
+		CayenneFilter filter = new CayenneFilter();
+		filter.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+		List<String> locations = runtime.getInjector().getInstance(
+				Key.getListOf(String.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
+
+		assertEquals(Arrays.asList("xyz"), locations);
+	}
+
+    @Test
+	public void testInitWithStandardModules() throws Exception {
+
+		MockFilterConfig config = new MockFilterConfig();
+		config.setFilterName("cayenne-abc");
+
+		MockServletContext context = new MockServletContext();
+		config.setupServletContext(context);
+
+		CayenneFilter filter = new CayenneFilter();
+
+		assertNull(WebUtil.getCayenneRuntime(context));
+		filter.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+		List<String> locations = runtime.getInjector().getInstance(
+				Key.getListOf(String.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
+
+		assertEquals(Arrays.asList("cayenne-abc.xml"), locations);
+		Collection<Module> modules = runtime.getModules();
+		assertEquals(3, modules.size());
+
+		Object[] marray = modules.toArray();
+
+		if(marray[0] instanceof ServerModule){
+			assertTrue(marray[1] instanceof WebModule);
+		}
+		else{
+			assertTrue(marray[0] instanceof WebModule);
+		}
+
+		RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
+		assertTrue(handler instanceof SessionContextRequestHandler);
+	}
+
+    @Test
+	public void testInitWithExtraModules() throws Exception {
+
+		MockFilterConfig config = new MockFilterConfig();
+		config.setFilterName("abc");
+		config.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, MockModule1.class.getName() + ","
+				+ MockModule2.class.getName());
+
+		MockServletContext context = new MockServletContext();
+		config.setupServletContext(context);
+
+		CayenneFilter filter = new CayenneFilter();
+		filter.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		assertNotNull(runtime);
+
+		Collection<Module> modules = runtime.getModules();
+		assertEquals(5, modules.size());
+
+
+		Object[] marray = modules.toArray();
+		if(marray[0] instanceof ServerModule){
+			assertTrue(marray[1] instanceof WebModule);
+		}
+		else{
+			assertTrue(marray[0] instanceof WebModule);
+		}
+		assertTrue(marray[2] instanceof MockModule1);
+		assertTrue(marray[3] instanceof MockModule2);
+
+		RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
+		assertTrue(handler instanceof MockRequestHandler);
+	}
+
+    @Test
+	public void testDoFilter() throws Exception {
+		MockFilterConfig config = new MockFilterConfig();
+		config.setFilterName("abc");
+		config.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, CayenneFilter_DispatchModule.class.getName());
+
+		MockServletContext context = new MockServletContext();
+		config.setupServletContext(context);
+
+		CayenneFilter filter = new CayenneFilter();
+		filter.init(config);
+
+		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
+		CayenneFilter_DispatchRequestHandler handler = (CayenneFilter_DispatchRequestHandler) runtime.getInjector()
+				.getInstance(RequestHandler.class);
+
+		assertEquals(0, handler.getStarted());
+		assertEquals(0, handler.getEnded());
+
+		filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
+		assertEquals(1, handler.getStarted());
+		assertEquals(1, handler.getEnded());
+
+		filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
+		assertEquals(2, handler.getStarted());
+		assertEquals(2, handler.getEnded());
+	}
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchModule.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchModule.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchModule.java
new file mode 100644
index 0000000..8842e27
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchModule.java
@@ -0,0 +1,29 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+
+public class CayenneFilter_DispatchModule implements Module {
+
+    public void configure(Binder binder) {
+        binder.bind(RequestHandler.class).to(CayenneFilter_DispatchRequestHandler.class);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchRequestHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchRequestHandler.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchRequestHandler.java
new file mode 100644
index 0000000..12006e6
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/CayenneFilter_DispatchRequestHandler.java
@@ -0,0 +1,45 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public class CayenneFilter_DispatchRequestHandler implements RequestHandler {
+
+    private int started;
+    private int ended;
+
+    public void requestEnd(ServletRequest request, ServletResponse response) {
+        ended++;
+    }
+
+    public void requestStart(ServletRequest request, ServletResponse response) {
+        started++;
+    }
+
+    public int getStarted() {
+        return started;
+    }
+
+    public int getEnded() {
+        return ended;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule1.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule1.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule1.java
new file mode 100644
index 0000000..52fcb06
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule1.java
@@ -0,0 +1,30 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+
+
+public class MockModule1 implements Module {
+
+    public void configure(Binder binder) {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule2.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule2.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule2.java
new file mode 100644
index 0000000..21f4099
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockModule2.java
@@ -0,0 +1,31 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Module;
+
+public class MockModule2 implements Module {
+
+    public void configure(Binder binder) {
+        binder.bind(RequestHandler.class).to(MockRequestHandler.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockRequestHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockRequestHandler.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockRequestHandler.java
new file mode 100644
index 0000000..1da4710
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/MockRequestHandler.java
@@ -0,0 +1,33 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+public class MockRequestHandler implements RequestHandler {
+
+    public void requestEnd(ServletRequest request, ServletResponse response) {
+    }
+
+    public void requestStart(ServletRequest request, ServletResponse response) {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/ServletContextHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/ServletContextHandlerTest.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/ServletContextHandlerTest.java
new file mode 100644
index 0000000..2c3905a
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/ServletContextHandlerTest.java
@@ -0,0 +1,124 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import com.mockrunner.mock.web.MockHttpServletRequest;
+import com.mockrunner.mock.web.MockHttpServletResponse;
+import com.mockrunner.mock.web.MockHttpSession;
+import org.apache.cayenne.BaseContext;
+import org.apache.cayenne.DataChannel;
+import org.apache.cayenne.MockDataChannel;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.ObjectContextFactory;
+import org.apache.cayenne.di.DIBootstrap;
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.Module;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+public class ServletContextHandlerTest {
+
+    @Test
+    public void testRequestStart_bindContext() {
+
+        Module module = binder -> {
+
+            binder.bind(DataChannel.class).to(MockDataChannel.class);
+            binder.bind(ObjectContextFactory.class).toInstance(
+                    new ObjectContextFactory() {
+
+                        public ObjectContext createContext(DataChannel parent) {
+                            return mock(ObjectContext.class);
+                        }
+
+                        public ObjectContext createContext() {
+                            return mock(ObjectContext.class);
+                        }
+                    });
+        };
+        Injector injector = DIBootstrap.createInjector(module);
+        SessionContextRequestHandler handler = new SessionContextRequestHandler();
+        injector.injectMembers(handler);
+
+        MockHttpSession session = new MockHttpSession();
+
+        BaseContext.bindThreadObjectContext(null);
+
+        try {
+
+            MockHttpServletRequest request1 = new MockHttpServletRequest();
+            MockHttpServletResponse response1 = new MockHttpServletResponse();
+            request1.setSession(session);
+            handler.requestStart(request1, response1);
+
+            ObjectContext c1 = BaseContext.getThreadObjectContext();
+            assertNotNull(c1);
+
+            handler.requestEnd(request1, response1);
+
+            try {
+                BaseContext.getThreadObjectContext();
+                fail("thread context not null");
+            }
+            catch (IllegalStateException e) {
+                // expected
+            }
+
+            MockHttpServletRequest request2 = new MockHttpServletRequest();
+            MockHttpServletResponse response2 = new MockHttpServletResponse();
+            request2.setSession(session);
+            handler.requestStart(request2, response2);
+
+            ObjectContext c2 = BaseContext.getThreadObjectContext();
+            assertSame(c1, c2);
+
+            handler.requestEnd(request2, response2);
+            try {
+                BaseContext.getThreadObjectContext();
+                fail("thread context not null");
+            }
+            catch (IllegalStateException e) {
+                // expected
+            }
+
+            MockHttpServletRequest request3 = new MockHttpServletRequest();
+            MockHttpServletResponse response3 = new MockHttpServletResponse();
+            request3.setSession(new MockHttpSession());
+            handler.requestStart(request3, response3);
+
+            ObjectContext c3 = BaseContext.getThreadObjectContext();
+            assertNotNull(c3);
+            assertNotSame(c1, c3);
+
+            handler.requestEnd(request3, response3);
+            try {
+                BaseContext.getThreadObjectContext();
+                fail("thread context not null");
+            }
+            catch (IllegalStateException e) {
+                // expected
+            }
+        }
+        finally {
+            BaseContext.bindThreadObjectContext(null);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebConfigurationTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebConfigurationTest.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebConfigurationTest.java
new file mode 100644
index 0000000..95c9fc3
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebConfigurationTest.java
@@ -0,0 +1,214 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import com.mockrunner.mock.web.MockFilterConfig;
+import com.mockrunner.mock.web.MockServletConfig;
+import org.apache.cayenne.di.Module;
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+public class WebConfigurationTest {
+
+    @Test
+    public void testFilterCreateModules_Standard() throws Exception {
+
+        MockFilterConfig config = new MockFilterConfig();
+        WebConfiguration configuration = new WebConfiguration(config);
+
+        Module m1 = binder -> {
+        };
+
+        Module m2 = binder -> {
+        };
+
+        Collection<Module> modules = configuration.createModules(m1, m2);
+        assertEquals(2, modules.size());
+
+        Iterator<Module> it = modules.iterator();
+        assertSame(m1, it.next());
+        assertSame(m2, it.next());
+    }
+
+    @Test
+    public void testFilterCreateModules_Extra() throws Exception {
+
+        MockFilterConfig config = new MockFilterConfig();
+        String exra = String.format(
+                "%s, \n%s",
+                MockModule1.class.getName(),
+                MockModule2.class.getName());
+        config.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, exra);
+
+        WebConfiguration configuration = new WebConfiguration(config);
+
+        Module m1 = binder -> {
+        };
+
+        Module m2 = binder -> {
+        };
+
+        Collection<Module> modules = configuration.createModules(m1, m2);
+        assertEquals(4, modules.size());
+
+        Iterator<Module> it = modules.iterator();
+        assertSame(m1, it.next());
+        assertSame(m2, it.next());
+        assertTrue(it.next() instanceof MockModule1);
+        assertTrue(it.next() instanceof MockModule2);
+    }
+
+    @Test
+    public void testServletCreateModules_Extra() throws Exception {
+
+        MockServletConfig config = new MockServletConfig();
+        String exra = String.format(
+                "%s, \n%s",
+                MockModule1.class.getName(),
+                MockModule2.class.getName());
+        config.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, exra);
+
+        WebConfiguration configuration = new WebConfiguration(config);
+
+        Module m1 = binder -> {
+        };
+
+        Module m2 = binder -> {
+        };
+
+        Collection<Module> modules = configuration.createModules(m1, m2);
+        assertEquals(4, modules.size());
+
+        Iterator<Module> it = modules.iterator();
+        assertSame(m1, it.next());
+        assertSame(m2, it.next());
+        assertTrue(it.next() instanceof MockModule1);
+        assertTrue(it.next() instanceof MockModule2);
+    }
+
+    @Test
+    public void testFilterConfigurationLocation_Name() {
+        MockFilterConfig config1 = new MockFilterConfig();
+        config1.setFilterName("cayenne-x");
+
+        WebConfiguration configuration1 = new WebConfiguration(config1);
+        assertEquals("cayenne-x.xml", configuration1.getConfigurationLocation());
+
+        MockFilterConfig config2 = new MockFilterConfig();
+        config2.setFilterName("cayenne-y.xml");
+
+        WebConfiguration configuration2 = new WebConfiguration(config2);
+        assertEquals("cayenne-y.xml", configuration2.getConfigurationLocation());
+
+        MockFilterConfig config3 = new MockFilterConfig();
+        config3.setFilterName("a/b/c/cayenne-z.xml");
+
+        WebConfiguration configuration3 = new WebConfiguration(config3);
+        assertEquals("a/b/c/cayenne-z.xml", configuration3.getConfigurationLocation());
+    }
+
+    @Test
+    public void testServletConfigurationLocation_Name() {
+        MockServletConfig config1 = new MockServletConfig();
+        config1.setServletName("cayenne-x");
+
+        WebConfiguration configuration1 = new WebConfiguration(config1);
+        assertEquals("cayenne-x.xml", configuration1.getConfigurationLocation());
+
+        MockServletConfig config2 = new MockServletConfig();
+        config2.setServletName("cayenne-y.xml");
+
+        WebConfiguration configuration2 = new WebConfiguration(config2);
+        assertEquals("cayenne-y.xml", configuration2.getConfigurationLocation());
+
+        MockServletConfig config3 = new MockServletConfig();
+        config3.setServletName("a/b/c/cayenne-z.xml");
+
+        WebConfiguration configuration3 = new WebConfiguration(config3);
+        assertEquals("a/b/c/cayenne-z.xml", configuration3.getConfigurationLocation());
+    }
+
+    @Test
+    public void testFilterConfigurationLocation_Parameter() {
+        MockFilterConfig config1 = new MockFilterConfig();
+        config1.setFilterName("cayenne-x");
+        config1.setInitParameter(
+                WebConfiguration.CONFIGURATION_LOCATION_PARAMETER,
+                "cayenne-y.xml");
+
+        WebConfiguration configuration1 = new WebConfiguration(config1);
+        assertEquals("cayenne-y.xml", configuration1.getConfigurationLocation());
+    }
+
+    @Test
+    public void testServletConfigurationLocation_Parameter() {
+        MockServletConfig config1 = new MockServletConfig();
+        config1.setServletName("cayenne-x");
+        config1.setInitParameter(
+                WebConfiguration.CONFIGURATION_LOCATION_PARAMETER,
+                "cayenne-y.xml");
+
+        WebConfiguration configuration1 = new WebConfiguration(config1);
+        assertEquals("cayenne-y.xml", configuration1.getConfigurationLocation());
+    }
+
+    @Test
+    public void testFilterParameters() {
+        MockFilterConfig config1 = new MockFilterConfig();
+        config1.setFilterName("cayenne-x");
+        config1.setInitParameter(
+                WebConfiguration.CONFIGURATION_LOCATION_PARAMETER,
+                "cayenne-y.xml");
+        config1.setInitParameter("test", "xxx");
+
+        WebConfiguration configuration1 = new WebConfiguration(config1);
+        Map<String, String> parameters = configuration1.getParameters();
+        assertNotSame(parameters, configuration1.getParameters());
+        assertEquals(parameters, configuration1.getParameters());
+
+        assertEquals(2, parameters.size());
+        assertEquals("cayenne-y.xml", parameters
+                .get(WebConfiguration.CONFIGURATION_LOCATION_PARAMETER));
+        assertEquals("xxx", parameters.get("test"));
+    }
+
+    @Test
+    public void testFilterOtherParameters() {
+        MockFilterConfig config1 = new MockFilterConfig();
+        config1.setFilterName("cayenne-x");
+        config1.setInitParameter(
+                WebConfiguration.CONFIGURATION_LOCATION_PARAMETER,
+                "cayenne-y.xml");
+        config1.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, "M1,M2");
+        config1.setInitParameter("test", "xxx");
+
+        WebConfiguration configuration1 = new WebConfiguration(config1);
+        Map<String, String> parameters = configuration1.getOtherParameters();
+        assertNotSame(parameters, configuration1.getOtherParameters());
+        assertEquals(parameters, configuration1.getOtherParameters());
+
+        assertEquals(1, parameters.size());
+        assertEquals("xxx", parameters.get("test"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleProviderTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleProviderTest.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleProviderTest.java
new file mode 100644
index 0000000..c6c9184
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleProviderTest.java
@@ -0,0 +1,30 @@
+/*
+ *    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.cayenne.configuration.web;
+
+import org.apache.cayenne.configuration.server.CayenneServerModuleProvider;
+import org.apache.cayenne.unit.util.ModuleProviderChecker;
+import org.junit.Test;
+
+public class WebModuleProviderTest {
+    @Test
+    public void testProviderPresent() {
+        ModuleProviderChecker.testProviderPresent(WebServerModuleProvider.class, CayenneServerModuleProvider.class);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleTest.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleTest.java
new file mode 100644
index 0000000..0fd2ff2
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebModuleTest.java
@@ -0,0 +1,40 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import org.apache.cayenne.di.Injector;
+import org.apache.cayenne.di.spi.DefaultInjector;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+public class WebModuleTest {
+
+    @Test
+    public void testBind_Scopes() {
+
+        Injector injector = new DefaultInjector(new WebModule());
+        RequestHandler handler = injector.getInstance(RequestHandler.class);
+        assertTrue(handler instanceof SessionContextRequestHandler);
+
+        RequestHandler handler1 = injector.getInstance(RequestHandler.class);
+        assertNotSame("Incorrect singleton scope for request handler", handler, handler1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebUtilTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebUtilTest.java b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebUtilTest.java
new file mode 100644
index 0000000..5db0f43
--- /dev/null
+++ b/cayenne-web/src/test/java/org/apache/cayenne/configuration/web/WebUtilTest.java
@@ -0,0 +1,50 @@
+/*****************************************************************
+ *   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.cayenne.configuration.web;
+
+import com.mockrunner.mock.web.MockServletContext;
+import org.apache.cayenne.configuration.CayenneRuntime;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.mock;
+
+public class WebUtilTest {
+
+    @Test
+	public void testGetCayenneRuntime() {
+		MockServletContext context = new MockServletContext();
+
+		assertNull(WebUtil.getCayenneRuntime(context));
+
+		CayenneRuntime runtime = mock(CayenneRuntime.class);
+
+		WebUtil.setCayenneRuntime(context, runtime);
+		assertSame(runtime, WebUtil.getCayenneRuntime(context));
+
+		CayenneRuntime runtime1 = mock(CayenneRuntime.class);
+
+		WebUtil.setCayenneRuntime(context, runtime1);
+		assertSame(runtime1, WebUtil.getCayenneRuntime(context));
+
+		WebUtil.setCayenneRuntime(context, null);
+		assertNull(WebUtil.getCayenneRuntime(context));
+	}
+}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilterTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilterTest.java b/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilterTest.java
deleted file mode 100644
index d0f28d5..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilterTest.java
+++ /dev/null
@@ -1,171 +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.cayenne.web;
-
-import com.mockrunner.mock.web.*;
-import org.apache.cayenne.configuration.CayenneRuntime;
-import org.apache.cayenne.configuration.Constants;
-import org.apache.cayenne.configuration.server.ServerModule;
-import org.apache.cayenne.di.Key;
-import org.apache.cayenne.di.Module;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-public class CayenneFilterTest {
-
-    @Test
-	public void testInitWithFilterName() throws Exception {
-
-		MockFilterConfig config = new MockFilterConfig();
-		config.setFilterName("abc");
-
-		MockServletContext context = new MockServletContext();
-		config.setupServletContext(context);
-
-		CayenneFilter filter = new CayenneFilter();
-
-		assertNull(WebUtil.getCayenneRuntime(context));
-		filter.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-
-		List<String> locations = runtime.getInjector().getInstance(
-				Key.getListOf(String.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
-
-		assertEquals(Arrays.asList("abc.xml"), locations);
-	}
-
-    @Test
-	public void testInitWithLocation() throws Exception {
-
-		MockFilterConfig config = new MockFilterConfig();
-		config.setFilterName("abc");
-		config.setInitParameter(WebConfiguration.CONFIGURATION_LOCATION_PARAMETER, "xyz");
-
-		MockServletContext context = new MockServletContext();
-		config.setupServletContext(context);
-
-		CayenneFilter filter = new CayenneFilter();
-		filter.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-		List<String> locations = runtime.getInjector().getInstance(
-				Key.getListOf(String.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
-
-		assertEquals(Arrays.asList("xyz"), locations);
-	}
-
-    @Test
-	public void testInitWithStandardModules() throws Exception {
-
-		MockFilterConfig config = new MockFilterConfig();
-		config.setFilterName("cayenne-abc");
-
-		MockServletContext context = new MockServletContext();
-		config.setupServletContext(context);
-
-		CayenneFilter filter = new CayenneFilter();
-
-		assertNull(WebUtil.getCayenneRuntime(context));
-		filter.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-		List<String> locations = runtime.getInjector().getInstance(
-				Key.getListOf(String.class, Constants.SERVER_PROJECT_LOCATIONS_LIST));
-
-		assertEquals(Arrays.asList("cayenne-abc.xml"), locations);
-		Collection<Module> modules = runtime.getModules();
-		assertEquals(3, modules.size());
-
-// 		Now we dont  correct order.
-/*		Object[] marray = modules.toArray();
-	    assertTrue(marray[0] instanceof WebModule);
-		assertTrue(marray[1] instanceof ServerModule);*/
-
-		RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
-		assertTrue(handler instanceof SessionContextRequestHandler);
-	}
-
-    @Test
-	public void testInitWithExtraModules() throws Exception {
-
-		MockFilterConfig config = new MockFilterConfig();
-		config.setFilterName("abc");
-		config.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, MockModule1.class.getName() + ","
-				+ MockModule2.class.getName());
-
-		MockServletContext context = new MockServletContext();
-		config.setupServletContext(context);
-
-		CayenneFilter filter = new CayenneFilter();
-		filter.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		assertNotNull(runtime);
-
-		Collection<Module> modules = runtime.getModules();
-		assertEquals(5, modules.size());
-
-//		Now we dont know correct order.
-		/*Object[] marray = modules.toArray();
-		assertTrue(marray[0] instanceof WebModule);
-		assertTrue(marray[1] instanceof ServerModule);
-		assertTrue(marray[2] instanceof MockModule1);
-		assertTrue(marray[3] instanceof MockModule2);*/
-
-		RequestHandler handler = runtime.getInjector().getInstance(RequestHandler.class);
-		assertTrue(handler instanceof MockRequestHandler);
-	}
-
-    @Test
-	public void testDoFilter() throws Exception {
-		MockFilterConfig config = new MockFilterConfig();
-		config.setFilterName("abc");
-		config.setInitParameter(WebConfiguration.EXTRA_MODULES_PARAMETER, CayenneFilter_DispatchModule.class.getName());
-
-		MockServletContext context = new MockServletContext();
-		config.setupServletContext(context);
-
-		CayenneFilter filter = new CayenneFilter();
-		filter.init(config);
-
-		CayenneRuntime runtime = WebUtil.getCayenneRuntime(context);
-		CayenneFilter_DispatchRequestHandler handler = (CayenneFilter_DispatchRequestHandler) runtime.getInjector()
-				.getInstance(RequestHandler.class);
-
-		assertEquals(0, handler.getStarted());
-		assertEquals(0, handler.getEnded());
-
-		filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
-		assertEquals(1, handler.getStarted());
-		assertEquals(1, handler.getEnded());
-
-		filter.doFilter(new MockHttpServletRequest(), new MockHttpServletResponse(), new MockFilterChain());
-		assertEquals(2, handler.getStarted());
-		assertEquals(2, handler.getEnded());
-	}
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchModule.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchModule.java b/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchModule.java
deleted file mode 100644
index f805910..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchModule.java
+++ /dev/null
@@ -1,29 +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.cayenne.web;
-
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.Module;
-
-public class CayenneFilter_DispatchModule implements Module {
-
-    public void configure(Binder binder) {
-        binder.bind(RequestHandler.class).to(CayenneFilter_DispatchRequestHandler.class);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchRequestHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchRequestHandler.java b/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchRequestHandler.java
deleted file mode 100644
index 257472d..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/CayenneFilter_DispatchRequestHandler.java
+++ /dev/null
@@ -1,45 +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.cayenne.web;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
-public class CayenneFilter_DispatchRequestHandler implements RequestHandler {
-
-    private int started;
-    private int ended;
-
-    public void requestEnd(ServletRequest request, ServletResponse response) {
-        ended++;
-    }
-
-    public void requestStart(ServletRequest request, ServletResponse response) {
-        started++;
-    }
-
-    public int getStarted() {
-        return started;
-    }
-
-    public int getEnded() {
-        return ended;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule1.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule1.java b/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule1.java
deleted file mode 100644
index 64d28e2..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule1.java
+++ /dev/null
@@ -1,30 +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.cayenne.web;
-
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.Module;
-
-
-public class MockModule1 implements Module {
-
-    public void configure(Binder binder) {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule2.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule2.java b/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule2.java
deleted file mode 100644
index 0af8f2b..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/MockModule2.java
+++ /dev/null
@@ -1,31 +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.cayenne.web;
-
-
-import org.apache.cayenne.di.Binder;
-import org.apache.cayenne.di.Module;
-
-public class MockModule2 implements Module {
-
-    public void configure(Binder binder) {
-        binder.bind(RequestHandler.class).to(MockRequestHandler.class);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/MockRequestHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/MockRequestHandler.java b/cayenne-web/src/test/java/org/apache/cayenne/web/MockRequestHandler.java
deleted file mode 100644
index c38b171..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/MockRequestHandler.java
+++ /dev/null
@@ -1,33 +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.cayenne.web;
-
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
-
-public class MockRequestHandler implements RequestHandler {
-
-    public void requestEnd(ServletRequest request, ServletResponse response) {
-    }
-
-    public void requestStart(ServletRequest request, ServletResponse response) {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/cayenne/blob/80416411/cayenne-web/src/test/java/org/apache/cayenne/web/ServletContextHandlerTest.java
----------------------------------------------------------------------
diff --git a/cayenne-web/src/test/java/org/apache/cayenne/web/ServletContextHandlerTest.java b/cayenne-web/src/test/java/org/apache/cayenne/web/ServletContextHandlerTest.java
deleted file mode 100644
index fe1d3d0..0000000
--- a/cayenne-web/src/test/java/org/apache/cayenne/web/ServletContextHandlerTest.java
+++ /dev/null
@@ -1,124 +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.cayenne.web;
-
-import com.mockrunner.mock.web.MockHttpServletRequest;
-import com.mockrunner.mock.web.MockHttpServletResponse;
-import com.mockrunner.mock.web.MockHttpSession;
-import org.apache.cayenne.BaseContext;
-import org.apache.cayenne.DataChannel;
-import org.apache.cayenne.MockDataChannel;
-import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.configuration.ObjectContextFactory;
-import org.apache.cayenne.di.DIBootstrap;
-import org.apache.cayenne.di.Injector;
-import org.apache.cayenne.di.Module;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.mock;
-
-public class ServletContextHandlerTest {
-
-    @Test
-    public void testRequestStart_bindContext() {
-
-        Module module = binder -> {
-
-            binder.bind(DataChannel.class).to(MockDataChannel.class);
-            binder.bind(ObjectContextFactory.class).toInstance(
-                    new ObjectContextFactory() {
-
-                        public ObjectContext createContext(DataChannel parent) {
-                            return mock(ObjectContext.class);
-                        }
-
-                        public ObjectContext createContext() {
-                            return mock(ObjectContext.class);
-                        }
-                    });
-        };
-        Injector injector = DIBootstrap.createInjector(module);
-        SessionContextRequestHandler handler = new SessionContextRequestHandler();
-        injector.injectMembers(handler);
-
-        MockHttpSession session = new MockHttpSession();
-
-        BaseContext.bindThreadObjectContext(null);
-
-        try {
-
-            MockHttpServletRequest request1 = new MockHttpServletRequest();
-            MockHttpServletResponse response1 = new MockHttpServletResponse();
-            request1.setSession(session);
-            handler.requestStart(request1, response1);
-
-            ObjectContext c1 = BaseContext.getThreadObjectContext();
-            assertNotNull(c1);
-
-            handler.requestEnd(request1, response1);
-
-            try {
-                BaseContext.getThreadObjectContext();
-                fail("thread context not null");
-            }
-            catch (IllegalStateException e) {
-                // expected
-            }
-
-            MockHttpServletRequest request2 = new MockHttpServletRequest();
-            MockHttpServletResponse response2 = new MockHttpServletResponse();
-            request2.setSession(session);
-            handler.requestStart(request2, response2);
-
-            ObjectContext c2 = BaseContext.getThreadObjectContext();
-            assertSame(c1, c2);
-
-            handler.requestEnd(request2, response2);
-            try {
-                BaseContext.getThreadObjectContext();
-                fail("thread context not null");
-            }
-            catch (IllegalStateException e) {
-                // expected
-            }
-
-            MockHttpServletRequest request3 = new MockHttpServletRequest();
-            MockHttpServletResponse response3 = new MockHttpServletResponse();
-            request3.setSession(new MockHttpSession());
-            handler.requestStart(request3, response3);
-
-            ObjectContext c3 = BaseContext.getThreadObjectContext();
-            assertNotNull(c3);
-            assertNotSame(c1, c3);
-
-            handler.requestEnd(request3, response3);
-            try {
-                BaseContext.getThreadObjectContext();
-                fail("thread context not null");
-            }
-            catch (IllegalStateException e) {
-                // expected
-            }
-        }
-        finally {
-            BaseContext.bindThreadObjectContext(null);
-        }
-    }
-}