├── .github ├── dependabot.yml └── workflows │ └── pr-builder.yaml ├── .gitignore ├── LICENSE ├── README.md ├── checkstyle ├── ClassHeader.txt ├── checkstyle.xml └── suppressions.xml ├── images └── NoteSmall.jpg ├── pom.xml ├── spotbugs └── spotbugs-excludes.xml ├── tomcat-core ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── ClientServerConfigLoader.java │ │ ├── ClientServerLifecycleListener.java │ │ ├── HazelcastInstanceFactory.java │ │ ├── HazelcastSession.java │ │ ├── HazelcastSessionChangeValve.java │ │ ├── HazelcastSessionCommitValve.java │ │ ├── LocalSessionsInvalidateListener.java │ │ ├── P2PConfigLoader.java │ │ ├── P2PLifecycleListener.java │ │ ├── SessionManager.java │ │ └── package-info.java │ └── test │ ├── java │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── AbstractAsyncServletTest.java │ │ ├── AbstractHazelcastSessionsTest.java │ │ ├── AbstractMapNameTest.java │ │ ├── AbstractNonSerializableSessionTest.java │ │ ├── AbstractSessionExpireTest.java │ │ ├── AbstractTomcatSecurityTest.java │ │ ├── ConfigLoaderTest.java │ │ ├── CustomAttribute.java │ │ ├── HazelcastGlobalKryoSerializer.java │ │ ├── LoginServlet.java │ │ ├── TestServlet.java │ │ ├── WebContainerConfigurator.java │ │ ├── nonsticky │ │ ├── AbstractClientServerNonStickySessionsTest.java │ │ ├── AbstractNonStickySessionsTest.java │ │ └── AbstractP2PNonStickySessionsTest.java │ │ └── sticky │ │ ├── AbstractClientServerStickySessionsTest.java │ │ ├── AbstractP2PStickySessionsTest.java │ │ └── AbstractStickySessionsTest.java │ └── resources │ ├── appWithSecurity │ ├── WEB-INF │ │ └── web.xml │ └── tomcat-users.xml │ ├── defaultApp │ ├── WEB-INF │ │ └── web.xml │ └── tomcat-users.xml │ ├── hazelcast-1.xml │ ├── hazelcast-2.xml │ ├── hazelcast-3.xml │ ├── hazelcast-4.xml │ ├── hazelcast-client-default.xml │ ├── hazelcast-invalid.xml │ ├── hazelcast-invalid.yaml │ ├── hazelcast.xml │ ├── logging.properties │ ├── test-hazelcast-client.yaml │ └── test-hazelcast.yaml ├── tomcat6 ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── HazelcastSessionManager.java │ │ └── package-info.java │ └── test │ ├── java │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── Tomcat6Configurator.java │ │ ├── Tomcat6MapNameTest.java │ │ ├── Tomcat6NonSerializableSessionTest.java │ │ ├── Tomcat6SecurityTest.java │ │ ├── Tomcat6SessionExpireTest.java │ │ ├── nonsticky │ │ ├── Tomcat6ClientServerNonStickySessionsTest.java │ │ └── Tomcat6P2PNonStickySessionsTest.java │ │ └── sticky │ │ ├── Tomcat6ClientServerStickySessionsTest.java │ │ └── Tomcat6P2PStickySessionsTest.java │ └── resources │ └── logging.properties ├── tomcat7 ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── HazelcastSessionManager.java │ │ └── package-info.java │ └── test │ └── java │ └── com │ └── hazelcast │ └── session │ ├── AsyncServlet.java │ ├── AsyncServletTest.java │ ├── Tomcat7AsyncConfigurator.java │ ├── Tomcat7Configurator.java │ ├── Tomcat7MapNameTest.java │ ├── Tomcat7NonSerializableSessionTest.java │ ├── Tomcat7SecurityTest.java │ ├── Tomcat7SessionExpireTest.java │ ├── nonsticky │ ├── Tomcat7ClientServerNonStickySessionsTest.java │ └── Tomcat7P2PNonStickySessionsTest.java │ └── sticky │ ├── Tomcat7ClientServerStickySessionsTest.java │ └── Tomcat7P2PStickySessionsTest.java ├── tomcat8 ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── HazelcastSessionManager.java │ │ └── package-info.java │ └── test │ └── java │ ├── Tomcat8SessionExpireTest.java │ └── com │ └── hazelcast │ └── session │ ├── AsyncServlet.java │ ├── AsyncServletTest.java │ ├── Tomcat8AsyncConfigurator.java │ ├── Tomcat8Configurator.java │ ├── Tomcat8MapNameTest.java │ ├── Tomcat8NonSerializableSessionTest.java │ ├── Tomcat8SecurityTest.java │ ├── Tomcat8SessionExpireTest.java │ ├── nonsticky │ ├── Tomcat8ClientServerNonStickySessionsTest.java │ └── Tomcat8P2PNonStickySessionsTest.java │ └── sticky │ ├── Tomcat8ClientServerStickySessionsTest.java │ └── Tomcat8P2PStickySessionsTest.java ├── tomcat85 ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── HazelcastSessionManager.java │ │ └── package-info.java │ └── test │ └── java │ └── com │ └── hazelcast │ └── session │ ├── AsyncServlet.java │ ├── AsyncServletTest.java │ ├── Tomcat85AsyncConfigurator.java │ ├── Tomcat85Configurator.java │ ├── Tomcat85MapNameTest.java │ ├── Tomcat85NonSerializableSessionTest.java │ ├── Tomcat85SecurityTest.java │ ├── Tomcat85SessionExpireTest.java │ ├── nonsticky │ ├── Tomcat85ClientServerNonStickySessionsTest.java │ └── Tomcat85P2PNonStickySessionsTest.java │ └── sticky │ ├── Tomcat85ClientServerStickySessionsTest.java │ └── Tomcat85P2PStickySessionsTest.java └── tomcat9 ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── hazelcast │ │ └── session │ │ ├── HazelcastSessionManager.java │ │ ├── HazelcastSessionManagerConfiguration.java │ │ └── package-info.java └── resources │ └── META-INF │ └── spring.factories └── test ├── java └── com │ └── hazelcast │ └── session │ ├── AsyncServlet.java │ ├── AsyncServletTest.java │ ├── Tomcat9AsyncConfigurator.java │ ├── Tomcat9Configurator.java │ ├── Tomcat9MapNameTest.java │ ├── Tomcat9NonSerializableSessionTest.java │ ├── Tomcat9SecurityTest.java │ ├── Tomcat9SessionExpireTest.java │ ├── nonsticky │ ├── Tomcat9ClientServerNonStickySessionsTest.java │ └── Tomcat9P2PNonStickySessionsTest.java │ ├── springboot │ ├── AbstractSpringBootConfigurationTest.java │ ├── ClientServerSpringBootConfigurationTest.java │ ├── P2PSpringBootConfigurationTest.java │ └── TestController.java │ └── sticky │ ├── Tomcat9ClientServerStickySessionsTest.java │ └── Tomcat9P2PStickySessionsTest.java └── resources ├── application.properties └── clientServer.properties /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "maven" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | - package-ecosystem: "github-actions" 8 | directory: "/" 9 | schedule: 10 | interval: "monthly" 11 | -------------------------------------------------------------------------------- /.github/workflows/pr-builder.yaml: -------------------------------------------------------------------------------- 1 | name: PR builder 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 'master' 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | 15 | - name: Setup JDK 16 | uses: actions/setup-java@v4 17 | with: 18 | java-version: 17 19 | distribution: 'temurin' 20 | 21 | - name: Override MAVEN_OPTS 22 | run: |- 23 | echo 'MAVEN_ARGS=--batch-mode --quiet --no-transfer-progress' >> "$GITHUB_ENV" 24 | 25 | - name: Build 26 | run: | 27 | mvn install -DskipTests --update-snapshots --activate-profiles checkstyle 28 | 29 | - name: SpotBugs 30 | run: | 31 | mvn compile --activate-profiles spotbugs 32 | 33 | - name: Verify 34 | run: | 35 | mvn verify -Dmaven.test.failure.ignore=false 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | .project 3 | .classpath 4 | .settings/ 5 | .idea/ 6 | .patch 7 | *.iml 8 | .DS_Store 9 | *dependency-reduced-pom.xml 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Hazelcast Community License 2 | 3 | Version 1.0 4 | 5 | 6 | 7 | This Hazelcast Community License Agreement Version 1.0 (the “Agreement”) sets 8 | forth the terms on which Hazelcast, Inc. (“Hazelcast”) makes available certain 9 | software made available by Hazelcast under this Agreement (the “Software”). BY 10 | INSTALLING, DOWNLOADING, ACCESSING, USING OR DISTRIBUTING ANY OF THE SOFTWARE, 11 | YOU AGREE TO THE TERMS AND CONDITIONS OF THIS AGREEMENT.IF YOU DO NOT AGREE TO 12 | SUCH TERMS AND CONDITIONS, YOU MUST NOT USE THE SOFTWARE. IF YOU ARE RECEIVING 13 | THE SOFTWARE ON BEHALF OF A LEGAL ENTITY, YOU REPRESENT AND WARRANT THAT YOU 14 | HAVE THE ACTUAL AUTHORITY TO AGREE TO THE TERMS AND CONDITIONS OF THIS 15 | AGREEMENT ON BEHALF OF SUCH ENTITY. “Licensee” means you, an individual, or 16 | the entity on whose behalf you are receiving the Software. 17 | 18 | 19 | 20 | 1. LICENSE GRANT AND CONDITIONS. 21 | 22 | 23 | 1.1 License. Subject to the terms and conditions of this Agreement, Hazelcast 24 | hereby grants to Licensee a non-exclusive, royalty-free, worldwide, 25 | non-transferable, non-sublicenseable license during the term of this Agreement 26 | to: (a) use the Software; (b) prepare modifications and derivative works of 27 | the Software; (c) distribute the Software (including without limitation in 28 | source code or object code form); and (d) reproduce copies of the Software ( 29 | the “License”). Licensee is not granted the right to, and Licensee shall not, 30 | exercise the License for an Excluded Purpose. For purposes of this Agreement, 31 | “Excluded Purpose” means making available any software-as-a-service, 32 | platform-as-a-service, infrastructure-as-a-service or other similar online 33 | service that competes with Hazelcast products or services that provide the 34 | Software. 35 | 36 | 37 | 1.2 Conditions. In consideration of the License, Licensee’s distribution of 38 | the Software is subject to the following conditions: 39 | 40 | a. Licensee must cause any Software modified by Licensee to carry prominent 41 | notices stating that Licensee modified the Software. 42 | 43 | b. On each Software copy, Licensee shall reproduce and not remove or alter all 44 | Hazelcast or third party copyright or other proprietary notices contained in 45 | the Software, and Licensee must provide the notice below with each copy. 46 | 47 | “This software is made available by Hazelcast, Inc., under the terms of the 48 | Hazelcast Community License Agreement, Version 1.0 located at 49 | http://hazelcast.com/Hazelcast-community-license. BY INSTALLING, DOWNLOADING, 50 | ACCESSING, USING OR DISTRIBUTING ANY OF THE SOFTWARE, YOU AGREE TO THE TERMS 51 | OF SUCH LICENSE AGREEMENT.” 52 | 53 | 54 | 1.3 Licensee Modifications. Licensee may add its own copyright notices to 55 | modifications made by Licensee and may provide additional or different license 56 | terms and conditions for use, reproduction, or distribution of Licensee’s 57 | modifications. While redistributing the Software or modifications thereof, 58 | Licensee may choose to offer, for a fee or free of charge, support, warranty, 59 | indemnity, or other obligations.Licensee, and not Hazelcast, will be 60 | responsible for any such obligations. 61 | 62 | 63 | 1.4 No Sublicensing. The License does not include the right to sublicense the 64 | Software, however, each recipient to which Licensee provides the Software may 65 | exercise the Licenses so long as such recipient agrees to the terms and 66 | conditions of this Agreement. 67 | 68 | 69 | 70 | 2. TERM AND TERMINATION. 71 | 72 | This Agreement will continue unless and until earlier terminated as set forth 73 | herein. If Licensee breaches any of its conditions or obligations under this 74 | Agreement, this Agreement will terminate automatically and the License will 75 | terminate automatically and permanently. 76 | 77 | 78 | 79 | 3. INTELLECTUAL PROPERTY. 80 | 81 | As between the parties, Hazelcast will retain all right, title, and interest 82 | in the Software, and all intellectual property rights therein. Hazelcast 83 | hereby reserves all rights not expressly granted to Licensee in this 84 | Agreement.Hazelcast hereby reserves all rights in its trademarks and service 85 | marks, and no licenses therein are granted in this Agreement. 86 | 87 | 88 | 89 | 4. DISCLAIMER. 90 | 91 | HAZELCAST HEREBY DISCLAIMS ANY AND ALL WARRANTIES AND CONDITIONS, EXPRESS, 92 | IMPLIED, STATUTORY, OR OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY WARRANTY OF 93 | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE 94 | SOFTWARE. 95 | 96 | 97 | 98 | 5. LIMITATION OF LIABILITY. 99 | 100 | HAZELCAST WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND, INCLUDING BUT NOT 101 | LIMITED TO, LOST PROFITS OR ANY CONSEQUENTIAL, SPECIAL, INCIDENTAL, INDIRECT, 102 | OR DIRECT DAMAGES, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ARISING OUT 103 | OF THIS AGREEMENT. THE FOREGOING SHALL APPLY TO THE EXTENT PERMITTED BY 104 | APPLICABLE LAW. 105 | 106 | 107 | 108 | 6. GENERAL. 109 | 110 | 111 | 6.1 Governing Law.This Agreement will be governed by and interpreted in 112 | accordance with the laws of the state of California, without reference to its 113 | conflict of laws principles. If Licensee is located within the United States, 114 | all disputes arising out of this Agreement are subject to the exclusive 115 | jurisdiction of courts located in Santa Clara County, California, USA. If 116 | Licensee is located outside of the United States, any dispute, controversy or 117 | claim arising out of or relating to this Agreement will be referred to and 118 | finally determined by arbitration in accordance with the JAMS International 119 | Arbitration Rules. The tribunal will consist of one arbitrator.The place of 120 | arbitration will be San Francisco, California.The language to be used in the 121 | arbitral proceedings will be English.Judgment upon the award rendered by the 122 | arbitrator may be entered in any court having jurisdiction thereof. 123 | 124 | 125 | 6.2. Assignment. Licensee is not authorized to assign its rights under this 126 | Agreement to any third party.Hazelcast may freely assign its rights under this 127 | Agreement to any third party. 128 | 129 | 130 | 6.3. Other. This Agreement is the entire agreement between the parties 131 | regarding the subject matter hereof. No amendment or modification of this 132 | Agreement will be valid or binding upon the parties unless made in writing and 133 | signed by the duly authorized representatives of both parties. In the event 134 | that any provision, including without limitation any condition, of this 135 | Agreement is held to be unenforceable, this Agreement and all licenses and 136 | rights granted hereunder will immediately terminate. Waiver by Hazelcast of a 137 | breach of any provision of this Agreement or the failure by Hazelcast to 138 | exercise any right hereunder will not be construed as a waiver of any 139 | subsequent breach of that right or as a waiver of any other right. -------------------------------------------------------------------------------- /checkstyle/ClassHeader.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | -------------------------------------------------------------------------------- /checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /images/NoteSmall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hazelcast/hazelcast-tomcat-sessionmanager/911b3eb35d0a9ba2abe59b01743eec1d4be19a98/images/NoteSmall.jpg -------------------------------------------------------------------------------- /spotbugs/spotbugs-excludes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /tomcat-core/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | hazelcast-tomcat-sessionmanager 17 | com.hazelcast 18 | 2.3-SNAPSHOT 19 | 20 | 4.0.0 21 | 22 | Hazelcast Tomcat Session Manager(Tomcat-Core) 23 | com.hazelcast 24 | tomcat-core 25 | jar 26 | 27 | 6.0.41 28 | 29 | ${project.parent.basedir} 30 | 31 | 32 | 33 | 34 | org.apache.tomcat 35 | catalina 36 | ${tomcat-version} 37 | provided 38 | 39 | 40 | com.esotericsoftware 41 | kryo 42 | ${kryo.version} 43 | test 44 | 45 | 46 | 47 | 48 | 49 | org.apache.maven.plugins 50 | maven-jar-plugin 51 | 2.2 52 | 53 | 54 | 55 | test-jar 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | release 66 | 67 | true 68 | 69 | 70 | 71 | 72 | org.apache.maven.plugins 73 | maven-deploy-plugin 74 | 75 | true 76 | 77 | 78 | 79 | org.sonatype.plugins 80 | nexus-staging-maven-plugin 81 | 1.7.0 82 | true 83 | 84 | true 85 | false 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/ClientServerConfigLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.client.config.ClientConfig; 19 | import com.hazelcast.client.config.XmlClientConfigBuilder; 20 | import com.hazelcast.client.config.YamlClientConfigBuilder; 21 | import com.hazelcast.client.config.impl.ClientXmlConfigRootTagRecognizer; 22 | import com.hazelcast.client.config.impl.ClientYamlConfigRootTagRecognizer; 23 | import com.hazelcast.config.ConfigRecognizer; 24 | import com.hazelcast.config.ConfigStream; 25 | import com.hazelcast.config.InvalidConfigurationException; 26 | 27 | import java.net.URL; 28 | 29 | import static com.hazelcast.internal.config.ConfigLoader.locateConfig; 30 | 31 | class ClientServerConfigLoader { 32 | private ConfigRecognizer xmlConfigRecognizer; 33 | private ConfigRecognizer yamlConfigRecognizer; 34 | 35 | ClientServerConfigLoader() throws Exception { 36 | xmlConfigRecognizer = new ClientXmlConfigRootTagRecognizer(); 37 | yamlConfigRecognizer = new ClientYamlConfigRootTagRecognizer(); 38 | } 39 | 40 | ClientConfig load(final String path) throws Exception { 41 | final URL url = locateConfig(path); 42 | if (url == null) { 43 | return null; 44 | } 45 | ConfigStream xmlConfigStream = new ConfigStream(url.openStream()); 46 | try { 47 | if (xmlConfigRecognizer.isRecognized(xmlConfigStream)) { 48 | return new XmlClientConfigBuilder(url).build(); 49 | } 50 | } finally { 51 | xmlConfigStream.close(); 52 | } 53 | ConfigStream yamlConfigStream = new ConfigStream(url.openStream()); 54 | try { 55 | if (yamlConfigRecognizer.isRecognized(yamlConfigStream)) { 56 | return new YamlClientConfigBuilder(url).build(); 57 | } 58 | } finally { 59 | yamlConfigStream.close(); 60 | } 61 | throw new InvalidConfigurationException("The provided file is not a valid Hazelcast client configuration: " + url); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/ClientServerLifecycleListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | 19 | import com.hazelcast.client.config.ClientConfig; 20 | import org.apache.catalina.LifecycleEvent; 21 | import org.apache.catalina.LifecycleListener; 22 | 23 | public class ClientServerLifecycleListener implements LifecycleListener { 24 | 25 | private static ClientConfig config; 26 | private String configLocation; 27 | 28 | @Override 29 | public void lifecycleEvent(LifecycleEvent event) { 30 | 31 | if (getConfigLocation() == null) { 32 | setConfigLocation("hazelcast-client-default.xml"); 33 | } 34 | 35 | if ("before_start".equals(event.getType())) { 36 | 37 | try { 38 | ClientServerLifecycleListener.config = new ClientServerConfigLoader().load(getConfigLocation()); 39 | } catch (Exception e) { 40 | throw new RuntimeException("failed to load Config:", e); 41 | } 42 | 43 | if (config == null) { 44 | throw new RuntimeException("failed to find configLocation:" + getConfigLocation()); 45 | } 46 | } 47 | } 48 | 49 | 50 | public String getConfigLocation() { 51 | return configLocation; 52 | } 53 | 54 | public void setConfigLocation(String configLocation) { 55 | this.configLocation = configLocation; 56 | } 57 | 58 | public static void setConfig(ClientConfig config) { 59 | ClientServerLifecycleListener.config = config; 60 | } 61 | 62 | public static ClientConfig getConfig() { 63 | return config; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/HazelcastInstanceFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.client.HazelcastClient; 19 | import com.hazelcast.client.config.ClientConfig; 20 | import com.hazelcast.config.Config; 21 | import com.hazelcast.core.Hazelcast; 22 | import com.hazelcast.core.HazelcastInstance; 23 | import org.apache.catalina.LifecycleException; 24 | import org.apache.juli.logging.Log; 25 | import org.apache.juli.logging.LogFactory; 26 | 27 | /** 28 | * Factory for {@link HazelcastInstance}'s for session management 29 | */ 30 | public final class HazelcastInstanceFactory { 31 | private static final Log LOGGER = LogFactory.getLog(HazelcastInstanceFactory.class); 32 | 33 | private HazelcastInstanceFactory() { 34 | } 35 | 36 | /** 37 | * Gets a {@link HazelcastInstance} by creating a new one (or getting the existing one on P2P setup). 38 | * 39 | * @param classLoader the classloader to set for the {@link HazelcastInstance} 40 | * @param clientOnly states if the instance is a client or not 41 | * @param instanceName name of the Hazelcast instance 42 | * @return the Hazelcast instance created/found 43 | * @throws LifecycleException when {@link HazelcastInstance} cannot be created in client/server mode 44 | */ 45 | public static HazelcastInstance getHazelcastInstance(ClassLoader classLoader, boolean clientOnly, String instanceName) 46 | throws LifecycleException { 47 | HazelcastInstance instance; 48 | if (instanceName != null) { 49 | if (clientOnly) { 50 | instance = HazelcastClient.getHazelcastClientByName(instanceName); 51 | } else { 52 | instance = Hazelcast.getHazelcastInstanceByName(instanceName); 53 | } 54 | } else if (clientOnly) { 55 | try { 56 | ClientConfig clientConfig = ClientServerLifecycleListener.getConfig(); 57 | clientConfig.setClassLoader(classLoader); 58 | instance = HazelcastClient.newHazelcastClient(clientConfig); 59 | } catch (Exception e) { 60 | LOGGER.error("Hazelcast Client could not be created.", e); 61 | throw new LifecycleException(e.getMessage()); 62 | } 63 | } else { 64 | /* 65 | Note that Hazelcast instance can only set a classloader during the initialization. If the context classloader 66 | changes after the initialization of the Hazelcast instance, it cannot be changed for the Hazelcast instance. 67 | */ 68 | Config config = P2PLifecycleListener.getConfig(); 69 | config.setClassLoader(classLoader); 70 | instance = Hazelcast.getOrCreateHazelcastInstance(config); 71 | } 72 | 73 | return instance; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/HazelcastSessionChangeValve.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import org.apache.catalina.connector.Request; 19 | import org.apache.catalina.connector.Response; 20 | import org.apache.catalina.valves.ValveBase; 21 | import org.apache.juli.logging.Log; 22 | import org.apache.juli.logging.LogFactory; 23 | 24 | import javax.servlet.ServletException; 25 | import java.io.IOException; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | 29 | public class HazelcastSessionChangeValve extends ValveBase { 30 | 31 | private final Log log = LogFactory.getLog(HazelcastSessionChangeValve.class); 32 | 33 | private final SessionManager sessionManager; 34 | 35 | private final Map handledSessions = new HashMap(); 36 | 37 | public HazelcastSessionChangeValve(SessionManager sessionManager) { 38 | this.sessionManager = sessionManager; 39 | } 40 | 41 | @Override 42 | public void invoke(Request request, Response response) throws IOException, ServletException { 43 | handleTomcatSessionChange(request); 44 | getNext().invoke(request, response); 45 | } 46 | 47 | private void handleTomcatSessionChange(Request request) throws IOException { 48 | String currentSessionId = request.getRequestedSessionId(); 49 | if (currentSessionId == null) { 50 | return; 51 | } 52 | String jvmRoute = sessionManager.getJvmRoute(); 53 | int index = currentSessionId.indexOf("."); 54 | String requestedJvmRoute = null; 55 | if (index > 0) { 56 | requestedJvmRoute = currentSessionId.substring(index + 1); 57 | } 58 | 59 | if (requestedJvmRoute == null || requestedJvmRoute.equals(jvmRoute)) { 60 | return; 61 | } 62 | 63 | request.changeSessionId(getOrCreateHandledSessionId(currentSessionId, jvmRoute)); 64 | request.getSession().invalidate(); 65 | } 66 | 67 | private String getOrCreateHandledSessionId(String currentSessionId, String jvmRoute) 68 | throws IOException { 69 | log.debug(String.format("Thread name: %s, Handling session id: %s", Thread.currentThread().getName(), currentSessionId)); 70 | String handledSessionId; 71 | synchronized (this) { 72 | if (!handledSessions.containsKey(currentSessionId)) { 73 | handledSessions.put(currentSessionId, sessionManager.updateJvmRouteForSession(currentSessionId, jvmRoute)); 74 | } 75 | } 76 | handledSessionId = handledSessions.get(currentSessionId); 77 | 78 | log.info(String.format("Thread name: %s, Handled session id from %s to %s", 79 | Thread.currentThread().getName(), currentSessionId, handledSessionId)); 80 | return handledSessionId; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/HazelcastSessionCommitValve.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import org.apache.catalina.Session; 19 | import org.apache.catalina.connector.Request; 20 | import org.apache.catalina.connector.Response; 21 | import org.apache.catalina.valves.ValveBase; 22 | import org.apache.juli.logging.Log; 23 | import org.apache.juli.logging.LogFactory; 24 | 25 | import javax.servlet.ServletException; 26 | import java.io.IOException; 27 | 28 | public class HazelcastSessionCommitValve extends ValveBase { 29 | 30 | private final Log log = LogFactory.getLog(HazelcastSessionCommitValve.class); 31 | 32 | private SessionManager sessionManager; 33 | 34 | public HazelcastSessionCommitValve(SessionManager sessionManager) { 35 | this.sessionManager = sessionManager; 36 | } 37 | 38 | @Override 39 | public void invoke(Request request, Response response) throws IOException, ServletException { 40 | try { 41 | getNext().invoke(request, response); 42 | } catch (Exception e) { 43 | log.error(e.getMessage()); 44 | } finally { 45 | final Session session = request.getSessionInternal(false); 46 | storeOrRemoveSession(session); 47 | } 48 | } 49 | 50 | private void storeOrRemoveSession(Session session) { 51 | if (session != null) { 52 | if (session.isValid()) { 53 | log.trace("Request with session completed, saving session " + session.getId()); 54 | if (session.getSession() != null) { 55 | log.trace("HTTP Session present, saving " + session.getId()); 56 | sessionManager.commit(session); 57 | } else { 58 | log.trace("No HTTP Session present, Not saving " + session.getId()); 59 | } 60 | } else { 61 | log.trace("HTTP Session has been invalidated, removing :" + session.getId()); 62 | sessionManager.remove(session); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/LocalSessionsInvalidateListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.core.EntryEvent; 19 | import com.hazelcast.map.listener.EntryEvictedListener; 20 | import com.hazelcast.map.listener.EntryRemovedListener; 21 | import org.apache.catalina.Session; 22 | 23 | import java.util.Map; 24 | 25 | public class LocalSessionsInvalidateListener implements EntryEvictedListener, 26 | EntryRemovedListener { 27 | 28 | private Map sessions; 29 | 30 | public LocalSessionsInvalidateListener(Map sessions) { 31 | this.sessions = sessions; 32 | } 33 | 34 | @Override 35 | public void entryEvicted(EntryEvent event) { 36 | invalidateSessions(event); 37 | } 38 | 39 | @Override 40 | public void entryRemoved(EntryEvent event) { 41 | invalidateSessions(event); 42 | } 43 | 44 | private void invalidateSessions(EntryEvent entryEvent) { 45 | if (entryEvent.getMember() == null || !entryEvent.getMember().localMember()) { 46 | sessions.remove(entryEvent.getKey()); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/P2PConfigLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.config.Config; 19 | import com.hazelcast.config.ConfigRecognizer; 20 | import com.hazelcast.config.ConfigStream; 21 | import com.hazelcast.config.InvalidConfigurationException; 22 | import com.hazelcast.config.UrlXmlConfig; 23 | import com.hazelcast.config.UrlYamlConfig; 24 | import com.hazelcast.internal.config.MemberXmlConfigRootTagRecognizer; 25 | import com.hazelcast.internal.config.MemberYamlConfigRootTagRecognizer; 26 | 27 | import java.net.URL; 28 | 29 | import static com.hazelcast.internal.config.ConfigLoader.locateConfig; 30 | 31 | class P2PConfigLoader { 32 | private ConfigRecognizer xmlConfigRecognizer; 33 | private ConfigRecognizer yamlConfigRecognizer; 34 | 35 | P2PConfigLoader() throws Exception { 36 | xmlConfigRecognizer = new MemberXmlConfigRootTagRecognizer(); 37 | yamlConfigRecognizer = new MemberYamlConfigRootTagRecognizer(); 38 | } 39 | 40 | Config load(final String path) throws Exception { 41 | final URL url = locateConfig(path); 42 | if (url == null) { 43 | return null; 44 | } 45 | ConfigStream xmlConfigStream = new ConfigStream(url.openStream()); 46 | try { 47 | if (xmlConfigRecognizer.isRecognized(xmlConfigStream)) { 48 | return new UrlXmlConfig(url); 49 | } 50 | } finally { 51 | xmlConfigStream.close(); 52 | } 53 | ConfigStream yamlConfigStream = new ConfigStream(url.openStream()); 54 | try { 55 | if (yamlConfigRecognizer.isRecognized(yamlConfigStream)) { 56 | return new UrlYamlConfig(url); 57 | } 58 | } finally { 59 | yamlConfigStream.close(); 60 | } 61 | throw new InvalidConfigurationException("The provided file is not a valid Hazelcast member configuration: " + url); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/P2PLifecycleListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.config.Config; 19 | import com.hazelcast.core.Hazelcast; 20 | import com.hazelcast.core.HazelcastInstance; 21 | import org.apache.catalina.LifecycleEvent; 22 | import org.apache.catalina.LifecycleListener; 23 | 24 | public class P2PLifecycleListener implements LifecycleListener { 25 | private static Config config; 26 | private String configLocation; 27 | 28 | @Override 29 | public void lifecycleEvent(LifecycleEvent event) { 30 | String shutdown = System.getProperty("hazelcast.tomcat.shutdown_hazelcast_instance"); 31 | if (getConfigLocation() == null) { 32 | setConfigLocation("hazelcast-default.xml"); 33 | } 34 | 35 | if ("before_start".equals(event.getType())) { 36 | try { 37 | config = new P2PConfigLoader().load(getConfigLocation()); 38 | } catch (Exception e) { 39 | throw new RuntimeException("failed to load Config:", e); 40 | } 41 | 42 | if (config == null) { 43 | throw new RuntimeException("failed to find configLocation:" + getConfigLocation()); 44 | } 45 | if (config.getInstanceName() == null) { 46 | config.setInstanceName(SessionManager.DEFAULT_INSTANCE_NAME); 47 | } 48 | } else if ("stop".equals(event.getType()) && !"false".equals(shutdown)) { 49 | HazelcastInstance instance = Hazelcast.getHazelcastInstanceByName(SessionManager.DEFAULT_INSTANCE_NAME); 50 | if (instance != null) { 51 | instance.shutdown(); 52 | } 53 | } 54 | } 55 | 56 | 57 | public String getConfigLocation() { 58 | return configLocation; 59 | } 60 | 61 | public void setConfigLocation(String configLocation) { 62 | this.configLocation = configLocation; 63 | } 64 | 65 | public static Config getConfig() { 66 | return config; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/SessionManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.map.IMap; 19 | import org.apache.catalina.Session; 20 | 21 | import java.io.IOException; 22 | 23 | public interface SessionManager { 24 | 25 | /** 26 | * Default name for the {@link com.hazelcast.core.HazelcastInstance}. 27 | */ 28 | String DEFAULT_INSTANCE_NAME = "SESSION-REPLICATION-INSTANCE"; 29 | 30 | void remove(Session session); 31 | 32 | void commit(Session session); 33 | 34 | String updateJvmRouteForSession(String sessionId, String newJvmRoute) throws IOException; 35 | 36 | String getJvmRoute(); 37 | 38 | IMap getDistributedMap(); 39 | 40 | boolean isDeferredEnabled(); 41 | 42 | /** 43 | * @return true if this {@link SessionManager} has sticky sessions enabled, otherwise false. 44 | */ 45 | boolean isSticky(); 46 | } 47 | -------------------------------------------------------------------------------- /tomcat-core/src/main/java/com/hazelcast/session/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | /** 17 | * This package provides core classes for Filterless Session Replication Module 18 | */ 19 | package com.hazelcast.session; 20 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/AbstractAsyncServletTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import org.apache.http.client.CookieStore; 5 | import org.apache.http.impl.client.BasicCookieStore; 6 | import org.junit.Before; 7 | import org.junit.Rule; 8 | import org.junit.Test; 9 | import org.junit.rules.TemporaryFolder; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | public abstract class AbstractAsyncServletTest extends AbstractHazelcastSessionsTest { 14 | @Rule 15 | public TemporaryFolder temporaryFolder = new TemporaryFolder(); 16 | 17 | @Before 18 | public void setUp() throws Exception { 19 | Hazelcast.newHazelcastInstance(); 20 | 21 | instance1 = getWebContainerConfigurator(); 22 | instance1.port(SERVER_PORT_1).sticky(true).clientOnly(true).sessionTimeout(10).start(); 23 | instance2 = getWebContainerConfigurator(); 24 | instance2.port(SERVER_PORT_2).sticky(true).clientOnly(true).sessionTimeout(10).start(); 25 | } 26 | 27 | @Override 28 | protected WebContainerConfigurator getWebContainerConfigurator() { 29 | return getAsyncWebContainerConfigurator(); 30 | } 31 | 32 | protected abstract WebContainerConfigurator getAsyncWebContainerConfigurator(); 33 | 34 | @Test 35 | public void testReadWriteRead() throws Exception { 36 | CookieStore cookieStore = new BasicCookieStore(); 37 | String value = executeRequest("", SERVER_PORT_1, cookieStore); 38 | assertEquals(value, "OK"); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/AbstractHazelcastSessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.client.HazelcastClient; 4 | import com.hazelcast.core.Hazelcast; 5 | import com.hazelcast.test.HazelcastTestSupport; 6 | import org.apache.catalina.Manager; 7 | import org.apache.catalina.session.StandardSession; 8 | import org.apache.http.HttpEntity; 9 | import org.apache.http.HttpResponse; 10 | import org.apache.http.client.CookieStore; 11 | import org.apache.http.client.HttpClient; 12 | import org.apache.http.client.methods.HttpGet; 13 | import org.apache.http.cookie.Cookie; 14 | import org.apache.http.impl.client.HttpClientBuilder; 15 | import org.apache.http.util.EntityUtils; 16 | import org.junit.After; 17 | 18 | import java.io.IOException; 19 | import java.net.ServerSocket; 20 | 21 | public abstract class AbstractHazelcastSessionsTest extends HazelcastTestSupport { 22 | 23 | protected static int SERVER_PORT_1 = findFreeTCPPort(); 24 | protected static int SERVER_PORT_2 = findFreeTCPPort(); 25 | protected static String SESSION_REPLICATION_MAP_NAME = "session-replication-map"; 26 | 27 | protected WebContainerConfigurator instance1; 28 | protected WebContainerConfigurator instance2; 29 | 30 | protected abstract WebContainerConfigurator getWebContainerConfigurator(); 31 | 32 | @After 33 | public void cleanup() throws Exception { 34 | instance1.stop(); 35 | instance2.stop(); 36 | HazelcastClient.shutdownAll(); 37 | Hazelcast.shutdownAll(); 38 | } 39 | 40 | protected String executeRequest(String context, int serverPort, CookieStore cookieStore) throws Exception { 41 | HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build(); 42 | HttpGet request = new HttpGet("http://localhost:" + serverPort + "/" + context); 43 | HttpResponse response = client.execute(request); 44 | HttpEntity entity = response.getEntity(); 45 | return EntityUtils.toString(entity); 46 | } 47 | 48 | /** 49 | * Helper method to retrieve the JSESSIONID value from the {@link CookieStore}. 50 | * @param cookieStore the cookie store containing sessions. 51 | * @return the value of the JSESSIONID cookie if present, otherwise null. 52 | */ 53 | protected static String getJSessionId(CookieStore cookieStore) { 54 | String jSessionId = null; 55 | for (Cookie cookie : cookieStore.getCookies()) { 56 | if ("JSESSIONID".equalsIgnoreCase(cookie.getName())) { 57 | jSessionId = cookie.getValue(); 58 | } 59 | } 60 | return jSessionId; 61 | } 62 | 63 | /** 64 | * Retrieves sessions using {@link Manager#findSession(String)} in accordance with the {@link StandardSession#isValid()} 65 | * method. 66 | * 67 | * @param jSessionId the session id. 68 | * @param instance the tomcat instance. 69 | * @return the instance of {@link HazelcastSession} if present, otherwise null. 70 | */ 71 | protected static HazelcastSession getHazelcastSession(String jSessionId, WebContainerConfigurator instance) 72 | throws IOException { 73 | return (HazelcastSession) ((Manager) instance.getManager()).findSession(jSessionId); 74 | } 75 | 76 | /** 77 | * Returns any free local TCP port number available. 78 | */ 79 | private static int findFreeTCPPort() { 80 | try { 81 | ServerSocket serverSocket = new ServerSocket(0); 82 | int localPort = serverSocket.getLocalPort(); 83 | serverSocket.close(); 84 | return localPort; 85 | } catch (Exception e) { 86 | throw new IllegalStateException("Could not find any available port", e); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/AbstractMapNameTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import com.hazelcast.map.IMap; 6 | import org.apache.http.client.CookieStore; 7 | import org.apache.http.cookie.Cookie; 8 | import org.apache.http.impl.client.BasicCookieStore; 9 | import org.junit.Test; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | import static org.junit.Assert.assertFalse; 13 | import static org.junit.Assert.assertTrue; 14 | 15 | public abstract class AbstractMapNameTest extends AbstractHazelcastSessionsTest { 16 | 17 | @Test 18 | public void testMapName() throws Exception { 19 | HazelcastInstance hz = Hazelcast.newHazelcastInstance(); 20 | 21 | instance1 = getWebContainerConfigurator(); 22 | instance1.port(SERVER_PORT_1).sticky(true).clientOnly(true).mapName(SESSION_REPLICATION_MAP_NAME).sessionTimeout(10).start(); 23 | instance2 = getWebContainerConfigurator(); 24 | instance2.port(SERVER_PORT_2).sticky(true).clientOnly(true).mapName(SESSION_REPLICATION_MAP_NAME).sessionTimeout(10).start(); 25 | 26 | CookieStore cookieStore = new BasicCookieStore(); 27 | executeRequest("write", SERVER_PORT_1, cookieStore); 28 | 29 | Cookie cookie = cookieStore.getCookies().get(0); 30 | String sessionId = cookie.getValue(); 31 | 32 | IMap map = hz.getMap(SESSION_REPLICATION_MAP_NAME); 33 | assertEquals(1, map.size()); 34 | HazelcastSession session = map.get(sessionId); 35 | 36 | assertFalse(session.getAttributes().isEmpty()); 37 | 38 | executeRequest("remove", SERVER_PORT_1, cookieStore); 39 | cookie = cookieStore.getCookies().get(0); 40 | String newSessionId = cookie.getValue(); 41 | session = map.get(newSessionId); 42 | 43 | assertTrue(session.getAttributes().isEmpty()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/AbstractNonSerializableSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import org.apache.http.client.CookieStore; 5 | import org.apache.http.impl.client.BasicCookieStore; 6 | import org.junit.Test; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | public abstract class AbstractNonSerializableSessionTest extends AbstractHazelcastSessionsTest { 11 | @Test 12 | public void testSerialization() throws Exception { 13 | Hazelcast.newHazelcastInstance(); 14 | 15 | instance1 = getWebContainerConfigurator(); 16 | instance1.port(SERVER_PORT_1).sticky(true).clientOnly(true).mapName(SESSION_REPLICATION_MAP_NAME).sessionTimeout(10).start(); 17 | instance2 = getWebContainerConfigurator(); 18 | instance2.port(SERVER_PORT_2).sticky(true).clientOnly(true).mapName(SESSION_REPLICATION_MAP_NAME).sessionTimeout(10).start(); 19 | 20 | CookieStore cookieStore = new BasicCookieStore(); 21 | assertEquals("true", executeRequest("nonserializable", SERVER_PORT_1, cookieStore)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/AbstractSessionExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import org.apache.http.client.CookieStore; 6 | import org.apache.http.impl.client.BasicCookieStore; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public abstract class AbstractSessionExpireTest extends AbstractHazelcastSessionsTest { 12 | 13 | @Test 14 | public void testSessionExpireAfterFailoverAndSessionTimeout() throws Exception { 15 | testSessionExpireAfterFailover("hazelcast-1.xml", "hazelcast-2.xml", 0); 16 | } 17 | 18 | @Test 19 | public void testSessionExpireAfterFailoverAndSessionTimeout_withDifferentHzExpirationConfiguration() throws Exception { 20 | testSessionExpireAfterFailover("hazelcast-3.xml", "hazelcast-4.xml", 1); 21 | } 22 | 23 | private void testSessionExpireAfterFailover(String firstConfig, String secondConfig, int expectedSessionCount) 24 | throws Exception { 25 | final int SESSION_TIMEOUT_IN_MINUTES = 1; 26 | final int EXTRA_DELAY_IN_SECONDS = 5; 27 | 28 | initializeInstances(firstConfig, secondConfig, SESSION_TIMEOUT_IN_MINUTES); 29 | 30 | CookieStore cookieStore = new BasicCookieStore(); 31 | executeRequest("write", SERVER_PORT_1, cookieStore); 32 | String value = executeRequest("read", SERVER_PORT_1, cookieStore); 33 | assertEquals("value", value); 34 | 35 | instance1.stop(); 36 | 37 | shutdownHzInstance1(); 38 | 39 | sleepSeconds(SESSION_TIMEOUT_IN_MINUTES * 60 + EXTRA_DELAY_IN_SECONDS); 40 | 41 | assertEquals(expectedSessionCount, instance2.getManager().getDistributedMap().size()); 42 | 43 | instance2.stop(); 44 | } 45 | 46 | @Test 47 | public void testSessionExpireAfterFailoverAndSessionTimeout_withSessionSpecificTimeout() 48 | throws Exception { 49 | final int GENERIC_SESSION_TIMEOUT_IN_MINUTES = 10; 50 | final int SPECIFIC_SESSION_TIMEOUT_IN_MINUTES = 1; 51 | final int EXTRA_DELAY_IN_SECONDS = 5; 52 | 53 | initializeInstances("hazelcast-1.xml", "hazelcast-2.xml", GENERIC_SESSION_TIMEOUT_IN_MINUTES); 54 | 55 | CookieStore cookieStore = new BasicCookieStore(); 56 | executeRequest("write", SERVER_PORT_1, cookieStore); 57 | 58 | String sessionId = getJSessionId(cookieStore); 59 | HazelcastSession session = getHazelcastSession(sessionId, instance1); 60 | session.setMaxInactiveInterval(SPECIFIC_SESSION_TIMEOUT_IN_MINUTES); 61 | 62 | String value = executeRequest("read", SERVER_PORT_1, cookieStore); 63 | assertEquals("value", value); 64 | 65 | instance1.stop(); 66 | 67 | shutdownHzInstance1(); 68 | 69 | sleepSeconds(SPECIFIC_SESSION_TIMEOUT_IN_MINUTES * 60 + EXTRA_DELAY_IN_SECONDS); 70 | 71 | assertEquals(0, instance2.getManager().getDistributedMap().size()); 72 | 73 | instance2.stop(); 74 | } 75 | 76 | private void shutdownHzInstance1() { 77 | HazelcastInstance hzInstance1 = Hazelcast.getHazelcastInstanceByName("hzInstance1"); 78 | if (hzInstance1 != null) { 79 | hzInstance1.shutdown(); 80 | } 81 | } 82 | 83 | private void initializeInstances(String firstConfig, String secondConfig, int sessionTimeout) 84 | throws Exception { 85 | instance1 = getWebContainerConfigurator(); 86 | instance1.port(SERVER_PORT_1).sticky(true).clientOnly(false).mapName(SESSION_REPLICATION_MAP_NAME) 87 | .sessionTimeout(sessionTimeout).configLocation(firstConfig).start(); 88 | 89 | instance2 = getWebContainerConfigurator(); 90 | instance2.port(SERVER_PORT_2).sticky(true).clientOnly(false).mapName(SESSION_REPLICATION_MAP_NAME) 91 | .sessionTimeout(sessionTimeout).configLocation(secondConfig).start(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/AbstractTomcatSecurityTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import org.apache.http.client.CookieStore; 5 | import org.apache.http.impl.client.BasicCookieStore; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertTrue; 10 | 11 | public abstract class AbstractTomcatSecurityTest extends AbstractHazelcastSessionsTest { 12 | @Override 13 | protected WebContainerConfigurator getWebContainerConfigurator() { 14 | return getTomcatConfigurator("appWithSecurity"); 15 | } 16 | 17 | @Before 18 | public void init() throws Exception { 19 | Hazelcast.newHazelcastInstance(); 20 | instance1 = getWebContainerConfigurator(); 21 | instance1.port(SERVER_PORT_1).sticky(false).clientOnly(true).sessionTimeout(10).start(); 22 | instance2 = getWebContainerConfigurator(); 23 | instance2.port(SERVER_PORT_2).sticky(false).clientOnly(true).sessionTimeout(10).start(); 24 | } 25 | 26 | @Test 27 | public void testGetProtectedResourceFormLogin() throws Exception { 28 | CookieStore cookieStore = new BasicCookieStore(); 29 | 30 | assertTrue(executeRequest("secureEndpoint", SERVER_PORT_1, cookieStore).contains("redirected to LoginServlet")); 31 | } 32 | 33 | protected abstract WebContainerConfigurator getTomcatConfigurator(String appName); 34 | } 35 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/ConfigLoaderTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.client.config.ClientConfig; 4 | import com.hazelcast.config.Config; 5 | import com.hazelcast.config.InvalidConfigurationException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | 9 | import static org.junit.Assert.assertNotNull; 10 | 11 | public class ConfigLoaderTest { 12 | 13 | private P2PConfigLoader memberConfigLoader; 14 | private ClientServerConfigLoader clientConfigLoader; 15 | 16 | @Before 17 | public void setup() 18 | throws Exception { 19 | memberConfigLoader = new P2PConfigLoader(); 20 | clientConfigLoader = new ClientServerConfigLoader(); 21 | } 22 | 23 | @Test 24 | public void testLoad_withMemberXmlConfig() throws Exception { 25 | //given 26 | String path = "hazelcast.xml"; 27 | //when 28 | Config config = memberConfigLoader.load(path); 29 | //then 30 | assertNotNull(config); 31 | } 32 | 33 | @Test(expected = InvalidConfigurationException.class) 34 | public void testLoad_invalidMemberXmlConfig() throws Exception { 35 | //given 36 | String path = "hazelcast-invalid.xml"; 37 | //when 38 | memberConfigLoader.load(path); 39 | //then 40 | //expect com.hazelcast.config.InvalidConfigurationException 41 | } 42 | 43 | @Test 44 | public void testLoad_withMemberYamlConfig() throws Exception { 45 | //given 46 | String path = "test-hazelcast.yaml"; 47 | //when 48 | Config config = memberConfigLoader.load(path); 49 | //then 50 | assertNotNull(config); 51 | } 52 | 53 | @Test(expected = InvalidConfigurationException.class) 54 | public void testLoad_invalidMemberYamlConfig() throws Exception { 55 | //given 56 | String path = "hazelcast-invalid.yaml"; 57 | //when 58 | memberConfigLoader.load(path); 59 | //then 60 | //expect com.hazelcast.config.InvalidConfigurationException 61 | } 62 | 63 | @Test 64 | public void testLoad_withClientXmlConfig() throws Exception { 65 | //given 66 | String path = "hazelcast-client-default.xml"; 67 | //when 68 | ClientConfig config = clientConfigLoader.load(path); 69 | //then 70 | assertNotNull(config); 71 | } 72 | 73 | @Test(expected = InvalidConfigurationException.class) 74 | public void testLoad_invalidClientXmlConfig() throws Exception { 75 | //given 76 | String path = "hazelcast-invalid.xml"; 77 | //when 78 | clientConfigLoader.load(path); 79 | //then 80 | //expect com.hazelcast.config.InvalidConfigurationException 81 | } 82 | 83 | @Test 84 | public void testLoad_withClientYamlConfig() throws Exception { 85 | //given 86 | String path = "test-hazelcast-client.yaml"; 87 | //when 88 | ClientConfig config = clientConfigLoader.load(path); 89 | //then 90 | assertNotNull(config); 91 | } 92 | 93 | @Test(expected = InvalidConfigurationException.class) 94 | public void testLoad_invalidClientYamlConfig() throws Exception { 95 | //given 96 | String path = "hazelcast-invalid.yaml"; 97 | //when 98 | clientConfigLoader.load(path); 99 | //then 100 | //expect com.hazelcast.config.InvalidConfigurationException 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/CustomAttribute.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2019, Hazelcast, Inc. All Rights Reserved. 3 | */ 4 | 5 | package com.hazelcast.session; 6 | 7 | public class CustomAttribute { 8 | private String value; 9 | 10 | //Needed for Kryo 11 | public CustomAttribute() { 12 | } 13 | 14 | public CustomAttribute(String value) { 15 | this.value = value; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "CustomAttribute{" + "value='" + value + '\'' + '}'; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/HazelcastGlobalKryoSerializer.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.esotericsoftware.kryo.Kryo; 4 | import com.esotericsoftware.kryo.io.InputChunked; 5 | import com.esotericsoftware.kryo.io.OutputChunked; 6 | import com.hazelcast.nio.ObjectDataInput; 7 | import com.hazelcast.nio.ObjectDataOutput; 8 | import com.hazelcast.nio.serialization.StreamSerializer; 9 | 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | import java.io.OutputStream; 13 | 14 | public class HazelcastGlobalKryoSerializer 15 | implements StreamSerializer { 16 | 17 | private final ThreadLocal kryoThreadLocal = new ThreadLocal() { 18 | @Override 19 | protected Kryo initialValue() { 20 | Kryo kryo = new Kryo(); 21 | kryo.register(CustomAttribute.class); 22 | return kryo; 23 | } 24 | }; 25 | 26 | @Override 27 | public int getTypeId() { 28 | return 123; 29 | } 30 | 31 | @Override 32 | public void write(ObjectDataOutput objectDataOutput, Object object) 33 | throws IOException { 34 | OutputChunked output = new OutputChunked((OutputStream) objectDataOutput, 4096); 35 | kryoThreadLocal.get().writeClassAndObject(output, object); 36 | output.endChunk(); 37 | output.flush(); 38 | } 39 | 40 | @Override 41 | public Object read(ObjectDataInput objectDataInput) 42 | throws IOException { 43 | InputStream in = (InputStream) objectDataInput; 44 | InputChunked input = new InputChunked(in, 4096); 45 | return kryoThreadLocal.get().readClassAndObject(input); 46 | } 47 | 48 | @Override 49 | public void destroy() { 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/LoginServlet.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import javax.servlet.ServletException; 4 | import javax.servlet.http.HttpServlet; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | public class LoginServlet extends HttpServlet { 10 | @Override 11 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 12 | resp.getWriter().write("redirected to LoginServlet"); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/TestServlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008-2020, Hazelcast, Inc. All Rights Reserved. 3 | */ 4 | 5 | package com.hazelcast.session; 6 | 7 | import javax.servlet.ServletException; 8 | import javax.servlet.http.HttpServlet; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import javax.servlet.http.HttpSession; 12 | import java.io.IOException; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class TestServlet extends HttpServlet { 17 | 18 | @Override 19 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 20 | HttpSession session = req.getSession(); 21 | if (req.getRequestURI().endsWith("write")) { 22 | session.setAttribute("key", "value"); 23 | resp.getWriter().write("true"); 24 | } else if (req.getRequestURI().endsWith("read")) { 25 | Object value = session.getAttribute("key"); 26 | resp.getWriter().write(value == null ? "null" : value.toString()); 27 | } else if (req.getRequestURI().endsWith("remove")) { 28 | session.removeAttribute("key"); 29 | resp.getWriter().write("true"); 30 | } else if (req.getRequestURI().endsWith("invalidate")) { 31 | session.invalidate(); 32 | resp.getWriter().write("true"); 33 | } else if (req.getRequestURI().endsWith("update")) { 34 | session.setAttribute("key", "value-updated"); 35 | resp.getWriter().write("true"); 36 | } else if (req.getRequestURI().endsWith("names")) { 37 | List names = Collections.list(session.getAttributeNames()); 38 | String nameList = names.toString(); 39 | //return comma separated list of attribute names 40 | resp.getWriter().write(nameList.substring(1, nameList.length() - 1).replace(", ", ",")); 41 | } else if (req.getRequestURI().endsWith("reload")) { 42 | session.invalidate(); 43 | session = req.getSession(); 44 | session.setAttribute("first-key", "first-value"); 45 | session.setAttribute("second-key", "second-value"); 46 | resp.getWriter().write("true"); 47 | } else if (req.getRequestURI().endsWith("isNew")) { 48 | resp.getWriter().write(session.isNew() ? "true" : "false"); 49 | } else if (req.getRequestURI().endsWith("lastAccessTime")) { 50 | resp.getWriter().write(String.valueOf(session.getLastAccessedTime())); 51 | } else if (req.getRequestURI().endsWith("nonserializable")) { 52 | session.setAttribute("key", new Object()); 53 | resp.getWriter().write("true"); 54 | } else if (req.getRequestURI().endsWith("write-custom-attribute")) { 55 | session.setAttribute("key", new CustomAttribute("value")); 56 | resp.getWriter().write("true"); 57 | } else if (req.getRequestURI().endsWith("read-custom-attribute")) { 58 | CustomAttribute value = (CustomAttribute) session.getAttribute("key"); 59 | resp.getWriter().write(value == null ? "null" : value.toString()); 60 | } else if (req.getRequestURI().endsWith("get-session-id")) { 61 | resp.getWriter().write(req.getSession().getId()); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/WebContainerConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | @SuppressWarnings("unused") 4 | public abstract class WebContainerConfigurator { 5 | 6 | protected int port; 7 | protected boolean sticky = true; 8 | protected boolean clientOnly; 9 | protected String mapName = "default"; 10 | protected int sessionTimeout; 11 | protected boolean deferredWrite; 12 | protected String configLocation = "hazelcast.xml"; 13 | 14 | public WebContainerConfigurator port(int port) { 15 | this.port = port; 16 | return this; 17 | } 18 | 19 | public WebContainerConfigurator sticky(boolean sticky) { 20 | this.sticky = sticky; 21 | return this; 22 | } 23 | 24 | public WebContainerConfigurator mapName(String mapName) { 25 | this.mapName = mapName; 26 | return this; 27 | } 28 | 29 | public WebContainerConfigurator clientOnly(boolean clientOnly) { 30 | this.clientOnly = clientOnly; 31 | return this; 32 | } 33 | 34 | public WebContainerConfigurator sessionTimeout(int sessionTimeout) { 35 | this.sessionTimeout = sessionTimeout; 36 | return this; 37 | } 38 | 39 | public WebContainerConfigurator deferredWrite(boolean deferredWrite) { 40 | this.deferredWrite = deferredWrite; 41 | return this; 42 | } 43 | 44 | public WebContainerConfigurator configLocation(String configLocation) { 45 | this.configLocation = configLocation; 46 | return this; 47 | } 48 | 49 | public abstract T configure() throws Exception; 50 | 51 | public abstract void start() throws Exception; 52 | 53 | public abstract void stop() throws Exception; 54 | 55 | public abstract void reload(); 56 | 57 | public abstract SessionManager getManager(); 58 | } 59 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/nonsticky/AbstractClientServerNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import org.junit.Before; 5 | 6 | public abstract class AbstractClientServerNonStickySessionsTest extends AbstractNonStickySessionsTest { 7 | 8 | @Before 9 | public void init() throws Exception { 10 | Hazelcast.newHazelcastInstance(); 11 | instance1 = getWebContainerConfigurator(); 12 | instance1.port(SERVER_PORT_1).sticky(false).clientOnly(true).sessionTimeout(10).start(); 13 | instance2 = getWebContainerConfigurator(); 14 | instance2.port(SERVER_PORT_2).sticky(false).clientOnly(true).sessionTimeout(10).start(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/nonsticky/AbstractNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.client.HazelcastClient; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import com.hazelcast.map.IMap; 6 | import com.hazelcast.session.AbstractHazelcastSessionsTest; 7 | import com.hazelcast.session.CustomAttribute; 8 | import com.hazelcast.session.HazelcastSession; 9 | import org.apache.http.client.CookieStore; 10 | import org.apache.http.impl.client.BasicCookieStore; 11 | import org.junit.Test; 12 | 13 | import static org.junit.Assert.assertEquals; 14 | import static org.junit.Assert.assertNotEquals; 15 | 16 | public abstract class AbstractNonStickySessionsTest extends AbstractHazelcastSessionsTest { 17 | 18 | @Test 19 | public void testContextReloadNonSticky() throws Exception { 20 | CookieStore cookieStore = new BasicCookieStore(); 21 | executeRequest("write", SERVER_PORT_1, cookieStore); 22 | instance1.reload(); 23 | 24 | String value = executeRequest("read", SERVER_PORT_2, cookieStore); 25 | assertEquals("value", value); 26 | } 27 | 28 | @Test 29 | public void testReadWriteRead() throws Exception { 30 | CookieStore cookieStore = new BasicCookieStore(); 31 | String value = executeRequest("read", SERVER_PORT_1, cookieStore); 32 | assertEquals("null", value); 33 | 34 | executeRequest("write", SERVER_PORT_1, cookieStore); 35 | 36 | value = executeRequest("read", SERVER_PORT_2, cookieStore); 37 | assertEquals("value", value); 38 | } 39 | 40 | @Test 41 | public void testReadWriteReadWithCustomSerialization() throws Exception { 42 | CustomAttribute expected = new CustomAttribute("value"); 43 | 44 | CookieStore cookieStore = new BasicCookieStore(); 45 | String value = executeRequest("read-custom-attribute", SERVER_PORT_1, cookieStore); 46 | assertEquals("null", value); 47 | 48 | executeRequest("write-custom-attribute", SERVER_PORT_1, cookieStore); 49 | 50 | value = executeRequest("read-custom-attribute", SERVER_PORT_2, cookieStore); 51 | assertEquals(expected.toString(), value); 52 | } 53 | 54 | @Test(timeout = 60000) 55 | public void testAttributeDistribution() throws Exception { 56 | CookieStore cookieStore = new BasicCookieStore(); 57 | executeRequest("write", SERVER_PORT_1, cookieStore); 58 | 59 | String value = executeRequest("read", SERVER_PORT_2, cookieStore); 60 | assertEquals("value", value); 61 | } 62 | 63 | @Test(timeout = 60000) 64 | public void testAttributeRemoval() throws Exception { 65 | CookieStore cookieStore = new BasicCookieStore(); 66 | executeRequest("write", SERVER_PORT_1, cookieStore); 67 | 68 | String value = executeRequest("read", SERVER_PORT_2, cookieStore); 69 | assertEquals("value", value); 70 | 71 | value = executeRequest("remove", SERVER_PORT_2, cookieStore); 72 | assertEquals("true", value); 73 | 74 | value = executeRequest("read", SERVER_PORT_1, cookieStore); 75 | assertEquals("null", value); 76 | } 77 | 78 | @Test(timeout = 60000) 79 | public void testAttributeUpdate() throws Exception { 80 | CookieStore cookieStore = new BasicCookieStore(); 81 | executeRequest("write", SERVER_PORT_1, cookieStore); 82 | 83 | String value = executeRequest("read", SERVER_PORT_2, cookieStore); 84 | assertEquals("value", value); 85 | 86 | value = executeRequest("update", SERVER_PORT_2, cookieStore); 87 | assertEquals("true", value); 88 | 89 | value = executeRequest("read", SERVER_PORT_1, cookieStore); 90 | assertEquals("value-updated", value); 91 | } 92 | 93 | @Test(timeout = 60000) 94 | public void testAttributeInvalidate() throws Exception { 95 | CookieStore cookieStore = new BasicCookieStore(); 96 | executeRequest("write", SERVER_PORT_1, cookieStore); 97 | 98 | String value = executeRequest("read", SERVER_PORT_2, cookieStore); 99 | assertEquals("value", value); 100 | 101 | value = executeRequest("invalidate", SERVER_PORT_2, cookieStore); 102 | assertEquals("true", value); 103 | 104 | HazelcastInstance instance = HazelcastClient.newHazelcastClient(); 105 | IMap map = instance.getMap("default"); 106 | assertEquals(0, map.size()); 107 | } 108 | 109 | @Test(timeout = 60000) 110 | public void testAttributeNames() throws Exception { 111 | CookieStore cookieStore = new BasicCookieStore(); 112 | executeRequest("read", SERVER_PORT_1, cookieStore); 113 | 114 | String commaSeparatedAttributeNames = executeRequest("names", SERVER_PORT_2, cookieStore); 115 | 116 | // no name should be created 117 | assertEquals("", commaSeparatedAttributeNames); 118 | 119 | executeRequest("write", SERVER_PORT_2, cookieStore); 120 | 121 | commaSeparatedAttributeNames = executeRequest("names", SERVER_PORT_1, cookieStore); 122 | assertEquals("key", commaSeparatedAttributeNames); 123 | 124 | } 125 | 126 | @Test(timeout = 60000) 127 | public void test_isNew() throws Exception { 128 | CookieStore cookieStore = new BasicCookieStore(); 129 | 130 | assertEquals("true", executeRequest("isNew", SERVER_PORT_1, cookieStore)); 131 | assertEquals("false", executeRequest("isNew", SERVER_PORT_2, cookieStore)); 132 | } 133 | 134 | @Test(timeout = 60000) 135 | public void test_LastAccessTime() throws Exception { 136 | CookieStore cookieStore = new BasicCookieStore(); 137 | String lastAccessTime1 = executeRequest("lastAccessTime", SERVER_PORT_1, cookieStore); 138 | executeRequest("lastAccessTime", SERVER_PORT_2, cookieStore); 139 | String lastAccessTime2 = executeRequest("lastAccessTime", SERVER_PORT_2, cookieStore); 140 | 141 | assertNotEquals(lastAccessTime1, lastAccessTime2); 142 | } 143 | 144 | @Test 145 | public void givenValidSession_whenNonStickySessions_thenAccessTimesAreEqualOnAllNodes() throws Exception { 146 | CookieStore cookieStore = new BasicCookieStore(); 147 | assertEquals("true", executeRequest("isNew", SERVER_PORT_1, cookieStore)); 148 | String jSessionId = getJSessionId(cookieStore); 149 | 150 | HazelcastSession session1 = getHazelcastSession(jSessionId, instance1); 151 | HazelcastSession session2 = getHazelcastSession(jSessionId, instance2); 152 | 153 | validateSessionAccessTime(session1, session2); 154 | } 155 | 156 | public abstract void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2); 157 | } 158 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/nonsticky/AbstractP2PNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import org.junit.Before; 4 | 5 | public abstract class AbstractP2PNonStickySessionsTest extends AbstractNonStickySessionsTest { 6 | 7 | @Before 8 | public void init() throws Exception { 9 | instance1 = getWebContainerConfigurator(); 10 | instance1.port(SERVER_PORT_1).sticky(false).clientOnly(false).sessionTimeout(10).start(); 11 | instance2 = getWebContainerConfigurator(); 12 | instance2.port(SERVER_PORT_2).sticky(false).clientOnly(false).sessionTimeout(10).start(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/sticky/AbstractClientServerStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import org.junit.Before; 5 | 6 | public abstract class AbstractClientServerStickySessionsTest extends AbstractStickySessionsTest { 7 | 8 | @Before 9 | public void init() throws Exception { 10 | Hazelcast.newHazelcastInstance(); 11 | instance1 = getWebContainerConfigurator(); 12 | instance1.port(SERVER_PORT_1).sticky(true).clientOnly(true).sessionTimeout(10).start(); 13 | instance2 = getWebContainerConfigurator(); 14 | instance2.port(SERVER_PORT_2).sticky(true).clientOnly(true).sessionTimeout(10).start(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat-core/src/test/java/com/hazelcast/session/sticky/AbstractP2PStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import org.junit.Before; 4 | 5 | public abstract class AbstractP2PStickySessionsTest extends AbstractStickySessionsTest { 6 | 7 | @Before 8 | public void init() throws Exception { 9 | instance1 = getWebContainerConfigurator(); 10 | instance1.port(SERVER_PORT_1) 11 | .sticky(true) 12 | .clientOnly(false) 13 | .sessionTimeout(10) 14 | .configLocation("hazelcast-1.xml") 15 | .start(); 16 | 17 | instance2 = getWebContainerConfigurator(); 18 | instance2.port(SERVER_PORT_2) 19 | .sticky(true) 20 | .clientOnly(false) 21 | .sessionTimeout(10) 22 | .configLocation("hazelcast-2.xml") 23 | .start(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/appWithSecurity/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | IntegrationTest Application 7 | 8 | 9 | secureServlet 10 | com.hazelcast.session.TestServlet 11 | 1 12 | 13 | 14 | 15 | secureServlet 16 | /secureEndpoint 17 | 18 | 19 | 20 | loginServlet 21 | com.hazelcast.session.LoginServlet 22 | 1 23 | 24 | 25 | 26 | loginServlet 27 | /loginPage 28 | 29 | 30 | 31 | Test Security Constraint 32 | 33 | Profile Area 34 | /secureEndpoint 35 | DELETE 36 | GET 37 | POST 38 | PUT 39 | 40 | 41 | role1 42 | role2 43 | 44 | 45 | 46 | 47 | FORM 48 | Form-Based Authentication Area 49 | 50 | /loginPage 51 | /errorPage 52 | 53 | 54 | 55 | 56 | role1 57 | 58 | 59 | role2 60 | 61 | 62 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/appWithSecurity/tomcat-users.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/defaultApp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | IntegrationTest Application 7 | 8 | 9 | testServlet 10 | com.hazelcast.session.TestServlet 11 | 1 12 | 13 | 14 | 15 | testServlet 16 | /* 17 | 18 | 19 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/defaultApp/tomcat-users.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-1.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | hzInstance1 20 | 21 | 5701 22 | 23 | 24 | 25 | 127.0.0.1 26 | 27 | 28 | 29 | 30 | 31 | 60 32 | 33 | 34 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-2.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | hzInstance2 20 | 21 | 5701 22 | 23 | 24 | 25 | 127.0.0.1 26 | 27 | 28 | 29 | 30 | 31 | 60 32 | 33 | 34 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-3.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | hzInstance1 20 | 21 | 5701 22 | 23 | 24 | 25 | 127.0.0.1 26 | 27 | 28 | 29 | 30 | 31 | 600 32 | 33 | 34 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-4.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | hzInstance2 20 | 21 | 5701 22 | 23 | 24 | 25 | 127.0.0.1 26 | 27 | 28 | 29 | 30 | 31 | 600 32 | 33 | 34 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-client-default.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 23 | 24 | 25 | 26 | com.hazelcast.session.HazelcastGlobalKryoSerializer 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-invalid.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast-invalid.yaml: -------------------------------------------------------------------------------- 1 | configuration: invalid 2 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/hazelcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 19 | 20 | 5701 21 | 22 | 23 | 24 | 127.0.0.1 25 | 26 | 27 | 28 | 29 | 30 | 31 | com.hazelcast.session.HazelcastGlobalKryoSerializer 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/logging.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Hazelcast Inc. 3 | # 4 | # Licensed under the Hazelcast Community License (the "License"); you may not use 5 | # this file except in compliance with the License. You may obtain a copy of the 6 | # License at 7 | # 8 | # http://hazelcast.com/hazelcast-community-license 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations under the License. 14 | # 15 | 16 | handlers = java.util.logging.ConsoleHandler 17 | 18 | .handlers = java.util.logging.ConsoleHandler 19 | 20 | ############################################################ 21 | # Handler specific properties. 22 | # Describes specific configuration info for Handlers. 23 | ############################################################ 24 | 25 | java.util.logging.ConsoleHandler.level = FINE 26 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 27 | 1fine.java.util.logging.ConsoleHandler.level = INFO 28 | 29 | 30 | ############################################################ 31 | # Facility specific properties. 32 | # Provides extra control for each logger. 33 | ############################################################ 34 | 35 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = FINE 36 | org.apache.catalina.core.level = FINE 37 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler 38 | 39 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO 40 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler 41 | 42 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO 43 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler 44 | 45 | com.hazelcast.session.level = FINE -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/test-hazelcast-client.yaml: -------------------------------------------------------------------------------- 1 | hazelcast-client: 2 | cluster-name: hz-test-cluster -------------------------------------------------------------------------------- /tomcat-core/src/test/resources/test-hazelcast.yaml: -------------------------------------------------------------------------------- 1 | hazelcast: 2 | cluster-name: hz-test-cluster -------------------------------------------------------------------------------- /tomcat6/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 4.0.0 16 | Hazelcast Tomcat Session Manager(Tomcat6) 17 | hazelcast-tomcat6-sessionmanager 18 | jar 19 | 20 | 21 | 6.0.41 22 | 23 | ${project.parent.basedir} 24 | 25 | 26 | com.hazelcast 27 | hazelcast-tomcat-sessionmanager 28 | 1.1.4-SNAPSHOT 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-shade-plugin 36 | 2.2 37 | 38 | 39 | false 40 | 41 | 42 | com.hazelcast:tomcat-core 43 | 44 | 45 | 46 | 47 | *:* 48 | 49 | META-INF/maven/com.hazelcast/tomcat-core/* 50 | 51 | 52 | 53 | 54 | 55 | 56 | package 57 | 58 | shade 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | com.hazelcast 69 | tomcat-core 70 | ${project.version} 71 | test-jar 72 | test 73 | 74 | 75 | com.hazelcast 76 | tomcat-core 77 | ${project.version} 78 | 79 | 80 | org.apache.tomcat 81 | catalina 82 | ${tomcat-version} 83 | provided 84 | 85 | 86 | -------------------------------------------------------------------------------- /tomcat6/src/main/java/com/hazelcast/session/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | /** 17 | * This package provides Filterless Session Replication for Tomcat 6 18 | */ 19 | package com.hazelcast.session; 20 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/Tomcat6Configurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Engine; 5 | import org.apache.catalina.Host; 6 | import org.apache.catalina.LifecycleException; 7 | import org.apache.catalina.connector.Connector; 8 | import org.apache.catalina.core.StandardServer; 9 | import org.apache.catalina.realm.MemoryRealm; 10 | import org.apache.catalina.startup.Embedded; 11 | import org.apache.juli.logging.Log; 12 | import org.apache.juli.logging.LogFactory; 13 | 14 | import java.io.File; 15 | import java.net.URL; 16 | import java.net.URLDecoder; 17 | 18 | public class Tomcat6Configurator extends WebContainerConfigurator { 19 | 20 | private Embedded tomcat; 21 | private SessionManager manager; 22 | 23 | private static String DEFAULT_HOST = "localhost"; 24 | 25 | private String appName; 26 | 27 | private final Log log = LogFactory.getLog(Tomcat6Configurator.class); 28 | 29 | public Tomcat6Configurator(String appName) { 30 | this.appName = appName; 31 | } 32 | 33 | public Tomcat6Configurator() { 34 | this.appName = "defaultApp"; 35 | } 36 | 37 | @Override 38 | public Embedded configure() throws Exception { 39 | final URL root = new URL(Tomcat6Configurator.class.getResource("/"), "../../../tomcat-core/target/test-classes"); 40 | final String cleanedRoot = URLDecoder.decode(root.getFile(), "UTF-8"); 41 | 42 | final String docBase = cleanedRoot + File.separator + appName; 43 | 44 | MemoryRealm memoryRealm = new MemoryRealm(); 45 | memoryRealm.setPathname(docBase + File.separator + "tomcat-users.xml"); 46 | 47 | final Embedded catalina = new Embedded(memoryRealm); 48 | if (!clientOnly) { 49 | P2PLifecycleListener listener = new P2PLifecycleListener(); 50 | listener.setConfigLocation(configLocation); 51 | catalina.addLifecycleListener(listener); 52 | } else { 53 | catalina.addLifecycleListener(new ClientServerLifecycleListener()); 54 | } 55 | 56 | final StandardServer server = new StandardServer(); 57 | server.addService(catalina); 58 | 59 | final Engine engine = catalina.createEngine(); 60 | engine.setName("engine-" + port); 61 | engine.setDefaultHost(DEFAULT_HOST); 62 | engine.setJvmRoute("tomcat-" + port); 63 | 64 | catalina.addEngine(engine); 65 | engine.setService(catalina); 66 | 67 | final Host host = catalina.createHost(DEFAULT_HOST, docBase); 68 | engine.addChild(host); 69 | 70 | final Context context = createContext(catalina, "/", docBase); 71 | host.addChild(context); 72 | 73 | this.manager = new HazelcastSessionManager(); 74 | context.setManager((HazelcastSessionManager) manager); 75 | updateManager((HazelcastSessionManager) manager); 76 | context.setBackgroundProcessorDelay(1); 77 | context.setCookies(true); 78 | 79 | final Connector connector = catalina.createConnector("localhost", port, false); 80 | connector.setProperty("bindOnInit", "false"); 81 | catalina.addConnector(connector); 82 | 83 | return catalina; 84 | } 85 | 86 | @Override 87 | public void start() throws Exception { 88 | tomcat = configure(); 89 | tomcat.start(); 90 | } 91 | 92 | @Override 93 | public void stop() throws Exception { 94 | try { 95 | tomcat.stop(); 96 | } catch (LifecycleException e) { 97 | log.warn("Failed to stop Tomcat. May be already stopped."); 98 | } 99 | } 100 | 101 | @Override 102 | public void reload() { 103 | Context ctx = (Context) tomcat.getContainer().findChild(DEFAULT_HOST).findChild("/"); 104 | ctx.reload(); 105 | } 106 | 107 | @Override 108 | public SessionManager getManager() { 109 | return manager; 110 | } 111 | 112 | private Context createContext(final Embedded catalina, final String contextPath, final String docBase) { 113 | return catalina.createContext(contextPath, docBase); 114 | } 115 | 116 | private void updateManager(HazelcastSessionManager manager) { 117 | manager.setSticky(sticky); 118 | manager.setClientOnly(clientOnly); 119 | manager.setMapName(mapName); 120 | manager.setMaxInactiveInterval(sessionTimeout); 121 | manager.setDeferredWrite(deferredWrite); 122 | manager.setProcessExpiresFrequency(1); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/Tomcat6MapNameTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat6MapNameTest extends AbstractMapNameTest { 11 | 12 | @Override 13 | protected WebContainerConfigurator getWebContainerConfigurator() { 14 | return new Tomcat6Configurator(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/Tomcat6NonSerializableSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class Tomcat6NonSerializableSessionTest extends AbstractNonSerializableSessionTest { 4 | @Override 5 | protected WebContainerConfigurator getWebContainerConfigurator() { 6 | return new Tomcat6Configurator(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/Tomcat6SecurityTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat6SecurityTest extends AbstractTomcatSecurityTest { 11 | @Override 12 | protected WebContainerConfigurator getTomcatConfigurator(String appName) { 13 | return new Tomcat6Configurator(appName); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/Tomcat6SessionExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat6SessionExpireTest extends AbstractSessionExpireTest { 11 | @Override 12 | protected WebContainerConfigurator getWebContainerConfigurator() { 13 | return new Tomcat6Configurator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/nonsticky/Tomcat6ClientServerNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat6Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat6ClientServerNonStickySessionsTest extends AbstractClientServerNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat6Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/nonsticky/Tomcat6P2PNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat6Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat6P2PNonStickySessionsTest extends AbstractP2PNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat6Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/sticky/Tomcat6ClientServerStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat6Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat6ClientServerStickySessionsTest extends AbstractClientServerStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat6Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat6/src/test/java/com/hazelcast/session/sticky/Tomcat6P2PStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat6Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat6P2PStickySessionsTest extends AbstractP2PStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat6Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat6/src/test/resources/logging.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 Hazelcast Inc. 3 | # 4 | # Licensed under the Hazelcast Community License (the "License"); you may not use 5 | # this file except in compliance with the License. You may obtain a copy of the 6 | # License at 7 | # 8 | # http://hazelcast.com/hazelcast-community-license 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | # WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | # specific language governing permissions and limitations under the License. 14 | # 15 | 16 | handlers = java.util.logging.ConsoleHandler 17 | 18 | .handlers = java.util.logging.ConsoleHandler 19 | 20 | ############################################################ 21 | # Handler specific properties. 22 | # Describes specific configuration info for Handlers. 23 | ############################################################ 24 | 25 | java.util.logging.ConsoleHandler.level = FINE 26 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 27 | 1fine.java.util.logging.ConsoleHandler.level = INFO 28 | 29 | 30 | ############################################################ 31 | # Facility specific properties. 32 | # Provides extra control for each logger. 33 | ############################################################ 34 | 35 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = FINE 36 | org.apache.catalina.core.level = FINE 37 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler 38 | 39 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO 40 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = 3manager.org.apache.juli.FileHandler 41 | 42 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO 43 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = 4host-manager.org.apache.juli.FileHandler 44 | 45 | com.hazelcast.session.level = FINE -------------------------------------------------------------------------------- /tomcat7/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 4.0.0 16 | Hazelcast Tomcat Session Manager(Tomcat7) 17 | hazelcast-tomcat7-sessionmanager 18 | jar 19 | 20 | hazelcast-tomcat-sessionmanager 21 | com.hazelcast 22 | 2.3-SNAPSHOT 23 | 24 | 25 | 26 | 7.0.54 27 | 28 | ${project.parent.basedir} 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-shade-plugin 36 | 2.2 37 | 38 | 39 | true 40 | 41 | 42 | com.hazelcast:tomcat-core 43 | 44 | 45 | 46 | 47 | *:* 48 | 49 | META-INF/maven/com.hazelcast/tomcat-core/* 50 | 51 | 52 | 53 | 54 | 55 | 56 | package 57 | 58 | shade 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | com.hazelcast 69 | tomcat-core 70 | ${project.version} 71 | test-jar 72 | test 73 | 74 | 75 | org.apache.tomcat 76 | catalina 77 | 78 | 79 | 80 | 81 | com.hazelcast 82 | tomcat-core 83 | ${project.version} 84 | 85 | 86 | org.apache.tomcat 87 | catalina 88 | 89 | 90 | 91 | 92 | org.apache.tomcat 93 | tomcat-catalina 94 | ${tomcat-version} 95 | provided 96 | 97 | 98 | org.apache.tomcat 99 | tomcat-coyote 100 | ${tomcat-version} 101 | provided 102 | 103 | 104 | org.apache.tomcat 105 | tomcat-jasper 106 | ${tomcat-version} 107 | provided 108 | 109 | 110 | com.esotericsoftware 111 | kryo 112 | ${kryo.version} 113 | test 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /tomcat7/src/main/java/com/hazelcast/session/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | /** 17 | * This package provides Filterless Session Replication for Tomcat 7 18 | */ 19 | package com.hazelcast.session; 20 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/AsyncServlet.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import javax.servlet.AsyncContext; 4 | import javax.servlet.ServletException; 5 | import javax.servlet.annotation.WebServlet; 6 | import javax.servlet.http.HttpServlet; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.concurrent.ArrayBlockingQueue; 12 | import java.util.concurrent.BlockingQueue; 13 | import java.util.concurrent.Executors; 14 | import java.util.concurrent.ScheduledExecutorService; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @WebServlet(asyncSupported = true, value = "/AsyncServlet") 18 | public class AsyncServlet extends HttpServlet { 19 | private static final BlockingQueue queue = new ArrayBlockingQueue(20000); 20 | 21 | public AsyncServlet() { 22 | ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); 23 | executorService.scheduleAtFixedRate(new Runnable() { 24 | @Override 25 | public void run() { 26 | AsyncServlet.newEvent(); 27 | } 28 | }, 0, 5, TimeUnit.SECONDS); 29 | } 30 | 31 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 32 | queue.add(request.startAsync()); 33 | } 34 | 35 | private static void newEvent() { 36 | ArrayList clients = new ArrayList(queue.size()); 37 | queue.drainTo(clients); 38 | for (AsyncContext ac : clients) { 39 | try { 40 | ac.getResponse().getWriter().write("OK"); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | ac.complete(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/AsyncServletTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class AsyncServletTest extends AbstractAsyncServletTest { 4 | @Override 5 | protected WebContainerConfigurator getAsyncWebContainerConfigurator() { 6 | return new Tomcat7AsyncConfigurator(temporaryFolder.getRoot().getAbsolutePath()); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/Tomcat7AsyncConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.Wrapper; 8 | import org.apache.catalina.connector.Connector; 9 | import org.apache.catalina.startup.Tomcat; 10 | 11 | public class Tomcat7AsyncConfigurator extends WebContainerConfigurator { 12 | 13 | private final String baseDir; 14 | 15 | private Tomcat tomcat; 16 | private SessionManager manager; 17 | 18 | public Tomcat7AsyncConfigurator(String baseDir) { 19 | this.baseDir = baseDir; 20 | } 21 | 22 | @Override 23 | public Tomcat configure() throws Exception { 24 | Tomcat tomcat = new Tomcat(); 25 | if (!clientOnly) { 26 | P2PLifecycleListener listener = new P2PLifecycleListener(); 27 | listener.setConfigLocation(configLocation); 28 | tomcat.getServer().addLifecycleListener(listener); 29 | } else { 30 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 31 | } 32 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 33 | tomcat.getEngine().setName("engine-" + port); 34 | 35 | final Connector connector = tomcat.getConnector(); 36 | connector.setPort(port); 37 | connector.setProperty("bindOnInit", "false"); 38 | 39 | tomcat.addUser("someuser", "somepass"); 40 | tomcat.addRole("someuser", "role1"); 41 | 42 | Context context; 43 | try { 44 | context = tomcat.addWebapp("", baseDir); 45 | 46 | Wrapper asyncServlet = context.createWrapper(); 47 | asyncServlet.setName("asyncServlet"); 48 | asyncServlet.setServletClass(AsyncServlet.class.getName()); 49 | asyncServlet.setAsyncSupported(true); 50 | 51 | context.addChild(asyncServlet); 52 | context.addServletMapping("/*", "asyncServlet"); 53 | 54 | } catch (final Exception e) { 55 | throw new IllegalStateException(e); 56 | } 57 | 58 | this.manager = new HazelcastSessionManager(); 59 | context.setManager((HazelcastSessionManager) manager); 60 | updateManager((HazelcastSessionManager) manager); 61 | context.setCookies(true); 62 | context.setBackgroundProcessorDelay(1); 63 | context.setReloadable(true); 64 | context.addLifecycleListener(new LifecycleListener() { 65 | @Override 66 | public void lifecycleEvent(LifecycleEvent event) { 67 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 68 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 69 | } 70 | } 71 | }); 72 | 73 | return tomcat; 74 | } 75 | 76 | @Override 77 | public void start() throws Exception { 78 | tomcat = configure(); 79 | tomcat.start(); 80 | } 81 | 82 | @Override 83 | public void stop() throws Exception { 84 | if (tomcat.getServer().getState().isAvailable()) { 85 | tomcat.stop(); 86 | } 87 | } 88 | 89 | @Override 90 | public void reload() { 91 | Context context = (Context) tomcat.getHost().findChild("/"); 92 | if (context == null) { 93 | context = (Context) tomcat.getHost().findChild(""); 94 | } 95 | context.reload(); 96 | } 97 | 98 | @Override 99 | public SessionManager getManager() { 100 | return manager; 101 | } 102 | 103 | private void updateManager(HazelcastSessionManager manager) { 104 | manager.setSticky(sticky); 105 | manager.setClientOnly(clientOnly); 106 | manager.setMapName(mapName); 107 | manager.setMaxInactiveInterval(sessionTimeout); 108 | manager.setDeferredWrite(deferredWrite); 109 | manager.setProcessExpiresFrequency(1); 110 | } 111 | } -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/Tomcat7Configurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.connector.Connector; 8 | import org.apache.catalina.startup.Tomcat; 9 | 10 | import java.io.File; 11 | import java.net.URL; 12 | import java.net.URLDecoder; 13 | 14 | public class Tomcat7Configurator extends WebContainerConfigurator { 15 | 16 | private Tomcat tomcat; 17 | private SessionManager manager; 18 | 19 | private String appName; 20 | 21 | public Tomcat7Configurator(String appName) { 22 | this.appName = appName; 23 | } 24 | 25 | public Tomcat7Configurator() { 26 | this.appName = "defaultApp"; 27 | } 28 | 29 | @Override 30 | public Tomcat configure() throws Exception { 31 | final URL root = new URL(TestServlet.class.getResource("/"), "../../../tomcat-core/target/test-classes"); 32 | final String cleanedRoot = URLDecoder.decode(root.getFile(), "UTF-8"); 33 | 34 | final String docBase = cleanedRoot + File.separator + appName; 35 | 36 | Tomcat tomcat = new Tomcat(); 37 | if (!clientOnly) { 38 | P2PLifecycleListener listener = new P2PLifecycleListener(); 39 | listener.setConfigLocation(configLocation); 40 | tomcat.getServer().addLifecycleListener(listener); 41 | } else { 42 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 43 | } 44 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 45 | tomcat.setBaseDir(docBase); 46 | 47 | tomcat.getEngine().setName("engine-" + port); 48 | 49 | final Connector connector = tomcat.getConnector(); 50 | connector.setPort(port); 51 | connector.setProperty("bindOnInit", "false"); 52 | 53 | Context context; 54 | try { 55 | context = tomcat.addWebapp(tomcat.getHost(), "/", docBase); 56 | } catch (final Exception e) { 57 | throw new IllegalStateException(e); 58 | } 59 | 60 | this.manager = new HazelcastSessionManager(); 61 | context.setManager((HazelcastSessionManager) manager); 62 | updateManager((HazelcastSessionManager) manager); 63 | context.setCookies(true); 64 | context.setBackgroundProcessorDelay(1); 65 | context.setReloadable(true); 66 | context.addLifecycleListener(new LifecycleListener() { 67 | @Override 68 | public void lifecycleEvent(LifecycleEvent event) { 69 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 70 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 71 | } 72 | } 73 | }); 74 | 75 | return tomcat; 76 | } 77 | 78 | @Override 79 | public void start() throws Exception { 80 | tomcat = configure(); 81 | tomcat.start(); 82 | } 83 | 84 | @Override 85 | public void stop() throws Exception { 86 | if (tomcat.getServer().getState().isAvailable()) { 87 | tomcat.stop(); 88 | } 89 | } 90 | 91 | @Override 92 | public void reload() { 93 | Context context = (Context) tomcat.getHost().findChild("/"); 94 | context.reload(); 95 | } 96 | 97 | @Override 98 | public SessionManager getManager() { 99 | return manager; 100 | } 101 | 102 | private void updateManager(HazelcastSessionManager manager) { 103 | manager.setSticky(sticky); 104 | manager.setClientOnly(clientOnly); 105 | manager.setMapName(mapName); 106 | manager.setMaxInactiveInterval(sessionTimeout); 107 | manager.setDeferredWrite(deferredWrite); 108 | manager.setProcessExpiresFrequency(1); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/Tomcat7MapNameTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat7MapNameTest extends AbstractMapNameTest { 11 | 12 | @Override 13 | protected WebContainerConfigurator getWebContainerConfigurator() { 14 | return new Tomcat7Configurator(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/Tomcat7NonSerializableSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class Tomcat7NonSerializableSessionTest extends AbstractNonSerializableSessionTest { 4 | @Override 5 | protected WebContainerConfigurator getWebContainerConfigurator() { 6 | return new Tomcat7Configurator(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/Tomcat7SecurityTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat7SecurityTest extends AbstractTomcatSecurityTest { 11 | @Override 12 | protected WebContainerConfigurator getTomcatConfigurator(String appName) { 13 | return new Tomcat7Configurator(appName); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/Tomcat7SessionExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat7SessionExpireTest extends AbstractSessionExpireTest { 11 | @Override 12 | protected WebContainerConfigurator getWebContainerConfigurator() { 13 | return new Tomcat7Configurator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/nonsticky/Tomcat7ClientServerNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat7Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat7ClientServerNonStickySessionsTest extends AbstractClientServerNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat7Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/nonsticky/Tomcat7P2PNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat7Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat7P2PNonStickySessionsTest extends AbstractP2PNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat7Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/sticky/Tomcat7ClientServerStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat7Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat7ClientServerStickySessionsTest extends AbstractClientServerStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat7Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat7/src/test/java/com/hazelcast/session/sticky/Tomcat7P2PStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat7Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat7P2PStickySessionsTest extends AbstractP2PStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat7Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat8/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 4.0.0 16 | Hazelcast Tomcat Session Manager(Tomcat8) 17 | hazelcast-tomcat8-sessionmanager 18 | jar 19 | 20 | hazelcast-tomcat-sessionmanager 21 | com.hazelcast 22 | 2.3-SNAPSHOT 23 | 24 | 25 | 26 | 8.0.36 27 | 28 | ${project.parent.basedir} 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-shade-plugin 36 | 2.2 37 | 38 | 39 | true 40 | 41 | 42 | com.hazelcast:tomcat-core 43 | 44 | 45 | 46 | 47 | *:* 48 | 49 | META-INF/maven/com.hazelcast/tomcat-core/* 50 | 51 | 52 | 53 | 54 | 55 | 56 | package 57 | 58 | shade 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | com.hazelcast 69 | tomcat-core 70 | ${project.version} 71 | test-jar 72 | test 73 | 74 | 75 | org.apache.tomcat 76 | catalina 77 | 78 | 79 | 80 | 81 | com.hazelcast 82 | tomcat-core 83 | ${project.version} 84 | 85 | 86 | org.apache.tomcat 87 | catalina 88 | 89 | 90 | 91 | 92 | org.apache.tomcat 93 | tomcat-catalina 94 | ${tomcat-version} 95 | provided 96 | 97 | 98 | org.apache.tomcat 99 | tomcat-coyote 100 | ${tomcat-version} 101 | provided 102 | 103 | 104 | org.apache.tomcat 105 | tomcat-jasper 106 | ${tomcat-version} 107 | provided 108 | 109 | 110 | com.esotericsoftware 111 | kryo 112 | ${kryo.version} 113 | test 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /tomcat8/src/main/java/com/hazelcast/session/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | /** 17 | * This package provides Filterless Session Replication for Tomcat 8 18 | */ 19 | package com.hazelcast.session; 20 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/Tomcat8SessionExpireTest.java: -------------------------------------------------------------------------------- 1 | import com.hazelcast.session.AbstractSessionExpireTest; 2 | import com.hazelcast.session.Tomcat8Configurator; 3 | import com.hazelcast.session.WebContainerConfigurator; 4 | 5 | public class Tomcat8SessionExpireTest extends AbstractSessionExpireTest { 6 | @Override 7 | protected WebContainerConfigurator getWebContainerConfigurator() { 8 | return new Tomcat8Configurator(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/AsyncServlet.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import javax.servlet.AsyncContext; 4 | import javax.servlet.ServletException; 5 | import javax.servlet.annotation.WebServlet; 6 | import javax.servlet.http.HttpServlet; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.concurrent.ArrayBlockingQueue; 12 | import java.util.concurrent.BlockingQueue; 13 | import java.util.concurrent.Executors; 14 | import java.util.concurrent.ScheduledExecutorService; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @WebServlet(asyncSupported = true, value = "/AsyncServlet") 18 | public class AsyncServlet extends HttpServlet { 19 | private static final BlockingQueue queue = new ArrayBlockingQueue(20000); 20 | 21 | public AsyncServlet() { 22 | ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); 23 | executorService.scheduleAtFixedRate(new Runnable() { 24 | @Override 25 | public void run() { 26 | AsyncServlet.newEvent(); 27 | } 28 | }, 0, 5, TimeUnit.SECONDS); 29 | } 30 | 31 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 32 | queue.add(request.startAsync()); 33 | } 34 | 35 | private static void newEvent() { 36 | ArrayList clients = new ArrayList(queue.size()); 37 | queue.drainTo(clients); 38 | for (AsyncContext ac : clients) { 39 | try { 40 | ac.getResponse().getWriter().write("OK"); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | ac.complete(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/AsyncServletTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class AsyncServletTest extends AbstractAsyncServletTest { 4 | @Override 5 | protected WebContainerConfigurator getAsyncWebContainerConfigurator() { 6 | return new Tomcat8AsyncConfigurator(temporaryFolder.getRoot().getAbsolutePath()); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/Tomcat8AsyncConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.Wrapper; 8 | import org.apache.catalina.connector.Connector; 9 | import org.apache.catalina.startup.Tomcat; 10 | 11 | public class Tomcat8AsyncConfigurator extends WebContainerConfigurator { 12 | 13 | private final String baseDir; 14 | 15 | private Tomcat tomcat; 16 | private HazelcastSessionManager manager; 17 | 18 | public Tomcat8AsyncConfigurator(String baseDir) { 19 | this.baseDir = baseDir; 20 | } 21 | 22 | @Override 23 | public Tomcat configure() throws Exception { 24 | Tomcat tomcat = new Tomcat(); 25 | if (!clientOnly) { 26 | P2PLifecycleListener listener = new P2PLifecycleListener(); 27 | listener.setConfigLocation(configLocation); 28 | tomcat.getServer().addLifecycleListener(listener); 29 | } else { 30 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 31 | } 32 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 33 | tomcat.getEngine().setName("engine-" + port); 34 | 35 | final Connector connector = tomcat.getConnector(); 36 | connector.setPort(port); 37 | connector.setProperty("bindOnInit", "false"); 38 | 39 | tomcat.addUser("someuser", "somepass"); 40 | tomcat.addRole("someuser", "role1"); 41 | 42 | Context context; 43 | try { 44 | context = tomcat.addWebapp("", baseDir); 45 | 46 | Wrapper asyncServlet = context.createWrapper(); 47 | asyncServlet.setName("asyncServlet"); 48 | asyncServlet.setServletClass(AsyncServlet.class.getName()); 49 | asyncServlet.setAsyncSupported(true); 50 | 51 | context.addChild(asyncServlet); 52 | context.addServletMapping("/*", "asyncServlet"); 53 | 54 | } catch (final Exception e) { 55 | throw new IllegalStateException(e); 56 | } 57 | 58 | this.manager = new HazelcastSessionManager(); 59 | context.setManager(manager); 60 | updateManager(manager); 61 | context.setCookies(true); 62 | context.setBackgroundProcessorDelay(1); 63 | context.setReloadable(true); 64 | context.addLifecycleListener(new LifecycleListener() { 65 | @Override 66 | public void lifecycleEvent(LifecycleEvent event) { 67 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 68 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 69 | } 70 | } 71 | }); 72 | 73 | return tomcat; 74 | } 75 | 76 | @Override 77 | public void start() throws Exception { 78 | tomcat = configure(); 79 | tomcat.start(); 80 | } 81 | 82 | @Override 83 | public void stop() throws Exception { 84 | if (tomcat.getServer().getState().isAvailable()) { 85 | tomcat.stop(); 86 | } 87 | } 88 | 89 | @Override 90 | public void reload() { 91 | Context context = (Context) tomcat.getHost().findChild("/"); 92 | if (context == null) { 93 | context = (Context) tomcat.getHost().findChild(""); 94 | } 95 | context.reload(); 96 | } 97 | 98 | @Override 99 | public SessionManager getManager() { 100 | return manager; 101 | } 102 | 103 | private void updateManager(HazelcastSessionManager manager) { 104 | manager.setSticky(sticky); 105 | manager.setClientOnly(clientOnly); 106 | manager.setMapName(mapName); 107 | manager.setDeferredWrite(deferredWrite); 108 | manager.setProcessExpiresFrequency(1); 109 | } 110 | } -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/Tomcat8Configurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.connector.Connector; 8 | import org.apache.catalina.startup.Tomcat; 9 | 10 | import java.io.File; 11 | import java.net.URL; 12 | import java.net.URLDecoder; 13 | 14 | public class Tomcat8Configurator extends WebContainerConfigurator { 15 | 16 | private Tomcat tomcat; 17 | private HazelcastSessionManager manager; 18 | private String appName; 19 | 20 | public Tomcat8Configurator(String appName) { 21 | this.appName = appName; 22 | } 23 | 24 | public Tomcat8Configurator() { 25 | this.appName = "defaultApp"; 26 | } 27 | 28 | @Override 29 | public Tomcat configure() throws Exception { 30 | final URL root = new URL(TestServlet.class.getResource("/"), "../../../tomcat-core/target/test-classes"); 31 | final String cleanedRoot = URLDecoder.decode(root.getFile(), "UTF-8"); 32 | 33 | final String fileSeparator = File.separator.equals("\\") ? "\\\\" : File.separator; 34 | final String docBase = cleanedRoot + File.separator + appName + fileSeparator; 35 | 36 | Tomcat tomcat = new Tomcat(); 37 | if (!clientOnly) { 38 | P2PLifecycleListener listener = new P2PLifecycleListener(); 39 | listener.setConfigLocation(configLocation); 40 | tomcat.getServer().addLifecycleListener(listener); 41 | } else { 42 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 43 | } 44 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 45 | tomcat.setBaseDir(docBase); 46 | 47 | tomcat.getEngine().setName("engine-" + port); 48 | 49 | final Connector connector = tomcat.getConnector(); 50 | connector.setPort(port); 51 | connector.setProperty("bindOnInit", "false"); 52 | 53 | tomcat.addUser("someuser", "somepass"); 54 | tomcat.addRole("someuser", "role1"); 55 | 56 | Context context; 57 | try { 58 | context = tomcat.addWebapp(tomcat.getHost(), "/", docBase); 59 | } catch (final Exception e) { 60 | throw new IllegalStateException(e); 61 | } 62 | 63 | this.manager = new HazelcastSessionManager(); 64 | context.setManager(manager); 65 | updateManager(manager); 66 | context.setCookies(true); 67 | context.setBackgroundProcessorDelay(1); 68 | context.setReloadable(true); 69 | context.addLifecycleListener(new LifecycleListener() { 70 | @Override 71 | public void lifecycleEvent(LifecycleEvent event) { 72 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 73 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 74 | } 75 | } 76 | }); 77 | 78 | return tomcat; 79 | } 80 | 81 | @Override 82 | public void start() throws Exception { 83 | tomcat = configure(); 84 | tomcat.start(); 85 | } 86 | 87 | @Override 88 | public void stop() throws Exception { 89 | if (tomcat.getServer().getState().isAvailable()) { 90 | tomcat.stop(); 91 | } 92 | } 93 | 94 | @Override 95 | public void reload() { 96 | Context context = (Context) tomcat.getHost().findChild("/"); 97 | if (context == null) { 98 | //Starting with Tomcat 8.0.35, child name is changed 99 | context = (Context) tomcat.getHost().findChild(""); 100 | } 101 | context.reload(); 102 | } 103 | 104 | @Override 105 | public SessionManager getManager() { 106 | return manager; 107 | } 108 | 109 | private void updateManager(HazelcastSessionManager manager) { 110 | manager.setSticky(sticky); 111 | manager.setClientOnly(clientOnly); 112 | manager.setMapName(mapName); 113 | manager.setDeferredWrite(deferredWrite); 114 | manager.setProcessExpiresFrequency(1); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/Tomcat8MapNameTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat8MapNameTest extends AbstractMapNameTest { 11 | 12 | @Override 13 | protected WebContainerConfigurator getWebContainerConfigurator() { 14 | return new Tomcat8Configurator(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/Tomcat8NonSerializableSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class Tomcat8NonSerializableSessionTest extends AbstractNonSerializableSessionTest { 4 | @Override 5 | protected WebContainerConfigurator getWebContainerConfigurator() { 6 | return new Tomcat8Configurator(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/Tomcat8SecurityTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat8SecurityTest extends AbstractTomcatSecurityTest { 11 | @Override 12 | protected WebContainerConfigurator getTomcatConfigurator(String appName) { 13 | return new Tomcat8Configurator(appName); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/Tomcat8SessionExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat8SessionExpireTest extends AbstractSessionExpireTest { 11 | @Override 12 | protected WebContainerConfigurator getWebContainerConfigurator() { 13 | return new Tomcat8Configurator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/nonsticky/Tomcat8ClientServerNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat8Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.Rule; 9 | import org.junit.experimental.categories.Category; 10 | import org.junit.runner.RunWith; 11 | 12 | import static org.junit.Assert.assertEquals; 13 | 14 | @RunWith(HazelcastSerialClassRunner.class) 15 | @Category(QuickTest.class) 16 | public class Tomcat8ClientServerNonStickySessionsTest extends AbstractClientServerNonStickySessionsTest { 17 | 18 | @Override 19 | protected WebContainerConfigurator getWebContainerConfigurator() { 20 | return new Tomcat8Configurator(); 21 | } 22 | 23 | @Override 24 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 25 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 26 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/nonsticky/Tomcat8P2PNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat8Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat8P2PNonStickySessionsTest extends AbstractP2PNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat8Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/sticky/Tomcat8ClientServerStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat8Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat8ClientServerStickySessionsTest extends AbstractClientServerStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat8Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat8/src/test/java/com/hazelcast/session/sticky/Tomcat8P2PStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat8Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat8P2PStickySessionsTest extends AbstractP2PStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat8Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat85/pom.xml: -------------------------------------------------------------------------------- 1 | 15 | 4.0.0 16 | Hazelcast Tomcat Session Manager(Tomcat85) 17 | hazelcast-tomcat85-sessionmanager 18 | jar 19 | 20 | hazelcast-tomcat-sessionmanager 21 | com.hazelcast 22 | 2.3-SNAPSHOT 23 | 24 | 25 | 26 | 8.5.9 27 | 28 | ${project.parent.basedir} 29 | 30 | 31 | 32 | 33 | 34 | org.apache.maven.plugins 35 | maven-shade-plugin 36 | 2.2 37 | 38 | 39 | true 40 | 41 | 42 | com.hazelcast:tomcat-core 43 | 44 | 45 | 46 | 47 | *:* 48 | 49 | META-INF/maven/com.hazelcast/tomcat-core/* 50 | 51 | 52 | 53 | 54 | 55 | 56 | package 57 | 58 | shade 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | com.hazelcast 69 | tomcat-core 70 | ${project.version} 71 | test-jar 72 | test 73 | 74 | 75 | org.apache.tomcat 76 | catalina 77 | 78 | 79 | 80 | 81 | com.hazelcast 82 | tomcat-core 83 | ${project.version} 84 | 85 | 86 | org.apache.tomcat 87 | catalina 88 | 89 | 90 | 91 | 92 | org.apache.tomcat 93 | tomcat-catalina 94 | ${tomcat-version} 95 | provided 96 | 97 | 98 | org.apache.tomcat 99 | tomcat-coyote 100 | ${tomcat-version} 101 | provided 102 | 103 | 104 | org.apache.tomcat 105 | tomcat-jasper 106 | ${tomcat-version} 107 | provided 108 | 109 | 110 | com.esotericsoftware 111 | kryo 112 | ${kryo.version} 113 | test 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /tomcat85/src/main/java/com/hazelcast/session/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | /** 17 | * This package provides Filterless Session Replication for Tomcat 8.5 18 | */ 19 | package com.hazelcast.session; 20 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/AsyncServlet.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import javax.servlet.AsyncContext; 4 | import javax.servlet.ServletException; 5 | import javax.servlet.annotation.WebServlet; 6 | import javax.servlet.http.HttpServlet; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.concurrent.ArrayBlockingQueue; 12 | import java.util.concurrent.BlockingQueue; 13 | import java.util.concurrent.Executors; 14 | import java.util.concurrent.ScheduledExecutorService; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @WebServlet(asyncSupported = true, value = "/AsyncServlet") 18 | public class AsyncServlet extends HttpServlet { 19 | private static final BlockingQueue queue = new ArrayBlockingQueue(20000); 20 | 21 | public AsyncServlet() { 22 | ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); 23 | executorService.scheduleAtFixedRate(new Runnable() { 24 | @Override 25 | public void run() { 26 | AsyncServlet.newEvent(); 27 | } 28 | }, 0, 5, TimeUnit.SECONDS); 29 | } 30 | 31 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 32 | queue.add(request.startAsync()); 33 | } 34 | 35 | private static void newEvent() { 36 | ArrayList clients = new ArrayList(queue.size()); 37 | queue.drainTo(clients); 38 | for (AsyncContext ac : clients) { 39 | try { 40 | ac.getResponse().getWriter().write("OK"); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | ac.complete(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/AsyncServletTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class AsyncServletTest extends AbstractAsyncServletTest { 4 | @Override 5 | protected WebContainerConfigurator getAsyncWebContainerConfigurator() { 6 | return new Tomcat85AsyncConfigurator(temporaryFolder.getRoot().getAbsolutePath()); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/Tomcat85AsyncConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.Wrapper; 8 | import org.apache.catalina.connector.Connector; 9 | import org.apache.catalina.startup.Tomcat; 10 | 11 | public class Tomcat85AsyncConfigurator extends WebContainerConfigurator { 12 | 13 | private final String baseDir; 14 | 15 | private Tomcat tomcat; 16 | private HazelcastSessionManager manager; 17 | 18 | public Tomcat85AsyncConfigurator(String baseDir) { 19 | this.baseDir = baseDir; 20 | } 21 | 22 | @Override 23 | public Tomcat configure() throws Exception { 24 | Tomcat tomcat = new Tomcat(); 25 | if (!clientOnly) { 26 | P2PLifecycleListener listener = new P2PLifecycleListener(); 27 | listener.setConfigLocation(configLocation); 28 | tomcat.getServer().addLifecycleListener(listener); 29 | } else { 30 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 31 | } 32 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 33 | tomcat.getEngine().setName("engine-" + port); 34 | 35 | final Connector connector = tomcat.getConnector(); 36 | connector.setPort(port); 37 | connector.setProperty("bindOnInit", "false"); 38 | 39 | tomcat.addUser("someuser", "somepass"); 40 | tomcat.addRole("someuser", "role1"); 41 | 42 | Context context; 43 | try { 44 | context = tomcat.addWebapp("", baseDir); 45 | 46 | Wrapper asyncServlet = context.createWrapper(); 47 | asyncServlet.setName("asyncServlet"); 48 | asyncServlet.setServletClass(AsyncServlet.class.getName()); 49 | asyncServlet.setAsyncSupported(true); 50 | 51 | context.addChild(asyncServlet); 52 | context.addServletMappingDecoded("/*", "asyncServlet"); 53 | 54 | } catch (final Exception e) { 55 | throw new IllegalStateException(e); 56 | } 57 | 58 | this.manager = new HazelcastSessionManager(); 59 | context.setManager(manager); 60 | updateManager(manager); 61 | context.setCookies(true); 62 | context.setBackgroundProcessorDelay(1); 63 | context.setReloadable(true); 64 | context.addLifecycleListener(new LifecycleListener() { 65 | @Override 66 | public void lifecycleEvent(LifecycleEvent event) { 67 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 68 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 69 | } 70 | } 71 | }); 72 | 73 | return tomcat; 74 | } 75 | 76 | @Override 77 | public void start() throws Exception { 78 | tomcat = configure(); 79 | tomcat.start(); 80 | } 81 | 82 | @Override 83 | public void stop() throws Exception { 84 | if (tomcat.getServer().getState().isAvailable()) { 85 | tomcat.stop(); 86 | } 87 | } 88 | 89 | @Override 90 | public void reload() { 91 | Context context = (Context) tomcat.getHost().findChild("/"); 92 | if (context == null) { 93 | context = (Context) tomcat.getHost().findChild(""); 94 | } 95 | context.reload(); 96 | } 97 | 98 | @Override 99 | public SessionManager getManager() { 100 | return manager; 101 | } 102 | 103 | private void updateManager(HazelcastSessionManager manager) { 104 | manager.setSticky(sticky); 105 | manager.setClientOnly(clientOnly); 106 | manager.setMapName(mapName); 107 | manager.setDeferredWrite(deferredWrite); 108 | manager.setProcessExpiresFrequency(1); 109 | } 110 | } -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/Tomcat85Configurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.connector.Connector; 8 | import org.apache.catalina.startup.Tomcat; 9 | 10 | import java.io.File; 11 | import java.net.URL; 12 | import java.net.URLDecoder; 13 | 14 | public class Tomcat85Configurator extends WebContainerConfigurator { 15 | 16 | private Tomcat tomcat; 17 | private HazelcastSessionManager manager; 18 | private String appName; 19 | 20 | public Tomcat85Configurator(String appName) { 21 | this.appName = appName; 22 | } 23 | 24 | public Tomcat85Configurator() { 25 | this.appName = "defaultApp"; 26 | } 27 | 28 | @Override 29 | public Tomcat configure() throws Exception { 30 | final URL root = new URL(TestServlet.class.getResource("/"), "../../../tomcat-core/target/test-classes"); 31 | final String cleanedRoot = URLDecoder.decode(root.getFile(), "UTF-8"); 32 | 33 | final String fileSeparator = File.separator.equals("\\") ? "\\\\" : File.separator; 34 | final String docBase = cleanedRoot + File.separator + appName + fileSeparator; 35 | 36 | Tomcat tomcat = new Tomcat(); 37 | if (!clientOnly) { 38 | P2PLifecycleListener listener = new P2PLifecycleListener(); 39 | listener.setConfigLocation(configLocation); 40 | tomcat.getServer().addLifecycleListener(listener); 41 | } else { 42 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 43 | } 44 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 45 | tomcat.setBaseDir(docBase); 46 | 47 | tomcat.getEngine().setName("engine-" + port); 48 | 49 | final Connector connector = tomcat.getConnector(); 50 | connector.setPort(port); 51 | connector.setProperty("bindOnInit", "false"); 52 | 53 | tomcat.addUser("someuser", "somepass"); 54 | tomcat.addRole("someuser", "role1"); 55 | 56 | Context context; 57 | try { 58 | context = tomcat.addWebapp(tomcat.getHost(), "/", docBase); 59 | } catch (final Exception e) { 60 | throw new IllegalStateException(e); 61 | } 62 | 63 | this.manager = new HazelcastSessionManager(); 64 | context.setManager(manager); 65 | updateManager(manager); 66 | context.setCookies(true); 67 | context.setBackgroundProcessorDelay(1); 68 | context.setReloadable(true); 69 | context.addLifecycleListener(new LifecycleListener() { 70 | @Override 71 | public void lifecycleEvent(LifecycleEvent event) { 72 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 73 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 74 | } 75 | } 76 | }); 77 | 78 | return tomcat; 79 | } 80 | 81 | @Override 82 | public void start() throws Exception { 83 | tomcat = configure(); 84 | tomcat.start(); 85 | } 86 | 87 | @Override 88 | public void stop() throws Exception { 89 | if (tomcat.getServer().getState().isAvailable()) { 90 | tomcat.stop(); 91 | } 92 | } 93 | 94 | @Override 95 | public void reload() { 96 | Context context = (Context) tomcat.getHost().findChild("/"); 97 | if (context == null) { 98 | //Starting with Tomcat 8.0.35, child name is changed 99 | context = (Context) tomcat.getHost().findChild(""); 100 | } 101 | context.reload(); 102 | } 103 | 104 | @Override 105 | public SessionManager getManager() { 106 | return manager; 107 | } 108 | 109 | private void updateManager(HazelcastSessionManager manager) { 110 | manager.setSticky(sticky); 111 | manager.setClientOnly(clientOnly); 112 | manager.setMapName(mapName); 113 | manager.setDeferredWrite(deferredWrite); 114 | manager.setProcessExpiresFrequency(1); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/Tomcat85MapNameTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat85MapNameTest extends AbstractMapNameTest { 11 | 12 | @Override 13 | protected WebContainerConfigurator getWebContainerConfigurator() { 14 | return new Tomcat85Configurator(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/Tomcat85NonSerializableSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class Tomcat85NonSerializableSessionTest extends AbstractNonSerializableSessionTest { 4 | @Override 5 | protected WebContainerConfigurator getWebContainerConfigurator() { 6 | return new Tomcat85Configurator(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/Tomcat85SecurityTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat85SecurityTest extends AbstractTomcatSecurityTest { 11 | @Override 12 | protected WebContainerConfigurator getTomcatConfigurator(String appName) { 13 | return new Tomcat85Configurator(appName); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/Tomcat85SessionExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat85SessionExpireTest extends AbstractSessionExpireTest { 11 | @Override 12 | protected WebContainerConfigurator getWebContainerConfigurator() { 13 | return new Tomcat85Configurator(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/nonsticky/Tomcat85ClientServerNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat85Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat85ClientServerNonStickySessionsTest extends AbstractClientServerNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat85Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/nonsticky/Tomcat85P2PNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat85Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat85P2PNonStickySessionsTest extends AbstractP2PNonStickySessionsTest { 16 | 17 | @Override 18 | protected WebContainerConfigurator getWebContainerConfigurator() { 19 | return new Tomcat85Configurator(); 20 | } 21 | 22 | @Override 23 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 24 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 25 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/sticky/Tomcat85ClientServerStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat85Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat85ClientServerStickySessionsTest extends AbstractClientServerStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat85Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat85/src/test/java/com/hazelcast/session/sticky/Tomcat85P2PStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat85Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat85P2PStickySessionsTest extends AbstractP2PStickySessionsTest { 13 | 14 | @Override 15 | protected WebContainerConfigurator getWebContainerConfigurator() { 16 | return new Tomcat85Configurator(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tomcat9/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | Hazelcast Tomcat Session Manager(Tomcat9) 4 | hazelcast-tomcat9-sessionmanager 5 | jar 6 | 7 | hazelcast-tomcat-sessionmanager 8 | com.hazelcast 9 | 2.3-SNAPSHOT 10 | 11 | 12 | 13 | 9.0.27 14 | 15 | ${project.parent.basedir} 16 | 17 | 18 | 19 | 20 | 21 | org.apache.maven.plugins 22 | maven-shade-plugin 23 | 2.2 24 | 25 | 26 | true 27 | 28 | 29 | com.hazelcast:tomcat-core 30 | 31 | 32 | 33 | 34 | *:* 35 | 36 | META-INF/maven/com.hazelcast/tomcat-core/* 37 | 38 | 39 | 40 | 41 | 42 | 43 | package 44 | 45 | shade 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | com.hazelcast 56 | tomcat-core 57 | ${project.version} 58 | test-jar 59 | test 60 | 61 | 62 | org.apache.tomcat 63 | catalina 64 | 65 | 66 | 67 | 68 | com.hazelcast 69 | tomcat-core 70 | ${project.version} 71 | 72 | 73 | org.apache.tomcat 74 | catalina 75 | 76 | 77 | 78 | 79 | org.apache.tomcat 80 | tomcat-catalina 81 | ${tomcat-version} 82 | provided 83 | 84 | 85 | org.apache.tomcat 86 | tomcat-coyote 87 | ${tomcat-version} 88 | provided 89 | 90 | 91 | org.apache.tomcat 92 | tomcat-jasper 93 | ${tomcat-version} 94 | provided 95 | 96 | 97 | org.springframework.boot 98 | spring-boot-starter-web 99 | 2.4.1 100 | provided 101 | 102 | 103 | org.springframework.boot 104 | spring-boot-starter-test 105 | 2.4.1 106 | test 107 | 108 | 109 | com.esotericsoftware 110 | kryo 111 | ${kryo.version} 112 | test 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /tomcat9/src/main/java/com/hazelcast/session/HazelcastSessionManagerConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | package com.hazelcast.session; 17 | 18 | import com.hazelcast.client.config.ClientConfig; 19 | import com.hazelcast.config.Config; 20 | import com.hazelcast.core.HazelcastInstance; 21 | import org.apache.catalina.Context; 22 | import org.apache.juli.logging.Log; 23 | import org.apache.juli.logging.LogFactory; 24 | import org.springframework.beans.factory.annotation.Value; 25 | import org.springframework.boot.autoconfigure.condition.ConditionOutcome; 26 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 27 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 28 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 29 | import org.springframework.boot.autoconfigure.condition.SpringBootCondition; 30 | import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer; 31 | import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; 32 | import org.springframework.boot.web.server.WebServerFactoryCustomizer; 33 | import org.springframework.context.annotation.Bean; 34 | import org.springframework.context.annotation.ConditionContext; 35 | import org.springframework.context.annotation.Conditional; 36 | import org.springframework.context.annotation.Configuration; 37 | import org.springframework.core.type.AnnotatedTypeMetadata; 38 | 39 | @Configuration 40 | @ConditionalOnClass(HazelcastSessionManager.class) 41 | @ConditionalOnProperty(name = "tsm.autoconfig.enabled", havingValue = "true", matchIfMissing = true) 42 | public class HazelcastSessionManagerConfiguration { 43 | private static final String TSM_HAZELCAST_CONFIG_LOCATION = "tsm.config.location"; 44 | private final Log log = LogFactory.getLog(HazelcastSessionManager.class); 45 | 46 | @Value("${" + TSM_HAZELCAST_CONFIG_LOCATION + ":hazelcast-default.xml}") 47 | private String configLocation; 48 | @Value("${tsm.map.name:default}") 49 | private String mapName; 50 | @Value("${tsm.sticky:true}") 51 | private boolean sticky; 52 | @Value("${tsm.process.expires.frequency:6}") 53 | private int processExpiresFrequency; 54 | @Value("${tsm.deferred.write:true}") 55 | private boolean deferredWrite; 56 | @Value("${tsm.hazelcast.instance.name:" + SessionManager.DEFAULT_INSTANCE_NAME + "}") 57 | private String hazelcastInstanceName; 58 | private boolean clientOnly; 59 | 60 | @Bean 61 | @ConditionalOnMissingBean(Config.class) 62 | @Conditional(HazelcastConfigAvailableCondition.class) 63 | public Config hazelcastConfigForTomcatSessionManager() throws Exception { 64 | Config config = new P2PConfigLoader().load(configLocation); 65 | if (config.getInstanceName() == null) { 66 | config.setInstanceName(SessionManager.DEFAULT_INSTANCE_NAME); 67 | } 68 | return config; 69 | } 70 | 71 | @Bean 72 | @ConditionalOnMissingBean(ClientConfig.class) 73 | @Conditional(HazelcastClientConfigAvailableCondition.class) 74 | public ClientConfig hazelcastClientConfigForTomcatSessionManager() throws Exception { 75 | clientOnly = true; 76 | ClientConfig clientConfig = new ClientServerConfigLoader().load(configLocation); 77 | if (clientConfig.getInstanceName() == null) { 78 | clientConfig.setInstanceName(SessionManager.DEFAULT_INSTANCE_NAME); 79 | } 80 | return clientConfig; 81 | } 82 | 83 | @Bean(name = "hazelcastTomcatSessionManagerCustomizer") 84 | public WebServerFactoryCustomizer customizeTomcat(HazelcastInstance hazelcastInstance) { 85 | return new WebServerFactoryCustomizer() { 86 | @Override 87 | public void customize(TomcatServletWebServerFactory factory) { 88 | factory.addContextCustomizers(new TomcatContextCustomizer() { 89 | @Override 90 | public void customize(Context context) { 91 | HazelcastSessionManager manager = new HazelcastSessionManager(); 92 | manager.setClientOnly(clientOnly); 93 | manager.setMapName(mapName); 94 | manager.setSticky(sticky); 95 | manager.setProcessExpiresFrequency(processExpiresFrequency); 96 | manager.setDeferredWrite(deferredWrite); 97 | manager.setHazelcastInstanceName(hazelcastInstanceName); 98 | context.setManager(manager); 99 | log.info(String.format( 100 | "Tomcat context is configured with HazelcastSessionManager => clientOnly: %s, mapName: %s, " 101 | + "isSticky: %s, processExpiresFrequency: %d, deferredWrite: %s, " 102 | + "hazelcastInstanceName: %s", 103 | clientOnly, mapName, sticky, processExpiresFrequency, deferredWrite, hazelcastInstanceName)); 104 | } 105 | }); 106 | } 107 | }; 108 | } 109 | 110 | private static ConditionOutcome getConditionOutcome(ConditionContext context, boolean forClient) { 111 | String message = "No explicit config provided using " + TSM_HAZELCAST_CONFIG_LOCATION; 112 | if (!context.getEnvironment().containsProperty(TSM_HAZELCAST_CONFIG_LOCATION)) { 113 | if (forClient) { 114 | return ConditionOutcome.noMatch(message); 115 | } 116 | return ConditionOutcome.match(message); 117 | } 118 | String configLocation = context.getEnvironment().getProperty(TSM_HAZELCAST_CONFIG_LOCATION); 119 | try { 120 | if (!forClient) { 121 | new P2PConfigLoader().load(configLocation); 122 | } else { 123 | new ClientServerConfigLoader().load(configLocation); 124 | } 125 | return ConditionOutcome.match("Found proper config at " + TSM_HAZELCAST_CONFIG_LOCATION); 126 | } catch (Exception e) { 127 | return ConditionOutcome.noMatch("No proper config at " + TSM_HAZELCAST_CONFIG_LOCATION 128 | + ", Reason: " + e.getMessage()); 129 | } 130 | } 131 | 132 | private static class HazelcastConfigAvailableCondition extends SpringBootCondition { 133 | @Override 134 | public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { 135 | return getConditionOutcome(context, false); 136 | } 137 | } 138 | 139 | private static class HazelcastClientConfigAvailableCondition extends SpringBootCondition { 140 | @Override 141 | public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { 142 | return getConditionOutcome(context, true); 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /tomcat9/src/main/java/com/hazelcast/session/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Hazelcast Inc. 3 | * 4 | * Licensed under the Hazelcast Community License (the "License"); you may not use 5 | * this file except in compliance with the License. You may obtain a copy of the 6 | * License at 7 | * 8 | * http://hazelcast.com/hazelcast-community-license 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OF ANY KIND, either express or implied. See the License for the 13 | * specific language governing permissions and limitations under the License. 14 | */ 15 | 16 | /** 17 | * This package provides Filterless Session Replication for Tomcat 9 18 | */ 19 | package com.hazelcast.session; 20 | -------------------------------------------------------------------------------- /tomcat9/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration= \ 2 | com.hazelcast.session.HazelcastSessionManagerConfiguration -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/AsyncServlet.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import javax.servlet.AsyncContext; 4 | import javax.servlet.ServletException; 5 | import javax.servlet.annotation.WebServlet; 6 | import javax.servlet.http.HttpServlet; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.util.ArrayList; 11 | import java.util.concurrent.ArrayBlockingQueue; 12 | import java.util.concurrent.BlockingQueue; 13 | import java.util.concurrent.Executors; 14 | import java.util.concurrent.ScheduledExecutorService; 15 | import java.util.concurrent.TimeUnit; 16 | 17 | @WebServlet(asyncSupported = true, value = "/AsyncServlet") 18 | public class AsyncServlet extends HttpServlet { 19 | private static final BlockingQueue queue = new ArrayBlockingQueue(20000); 20 | 21 | public AsyncServlet() { 22 | ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); 23 | executorService.scheduleAtFixedRate(new Runnable() { 24 | @Override 25 | public void run() { 26 | AsyncServlet.newEvent(); 27 | } 28 | }, 0, 5, TimeUnit.SECONDS); 29 | } 30 | 31 | protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 32 | queue.add(request.startAsync()); 33 | } 34 | 35 | private static void newEvent() { 36 | ArrayList clients = new ArrayList(queue.size()); 37 | queue.drainTo(clients); 38 | for (AsyncContext ac : clients) { 39 | try { 40 | ac.getResponse().getWriter().write("OK"); 41 | } catch (IOException e) { 42 | e.printStackTrace(); 43 | } 44 | ac.complete(); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/AsyncServletTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class AsyncServletTest extends AbstractAsyncServletTest { 4 | @Override 5 | protected WebContainerConfigurator getAsyncWebContainerConfigurator() { 6 | return new Tomcat9AsyncConfigurator(temporaryFolder.getRoot().getAbsolutePath()); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/Tomcat9AsyncConfigurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.Wrapper; 8 | import org.apache.catalina.connector.Connector; 9 | import org.apache.catalina.startup.Tomcat; 10 | 11 | public class Tomcat9AsyncConfigurator 12 | extends WebContainerConfigurator { 13 | 14 | private final String baseDir; 15 | 16 | private Tomcat tomcat; 17 | private HazelcastSessionManager manager; 18 | 19 | public Tomcat9AsyncConfigurator(String baseDir) { 20 | this.baseDir = baseDir; 21 | } 22 | 23 | @Override 24 | public Tomcat configure() throws Exception { 25 | Tomcat tomcat = new Tomcat(); 26 | if (!clientOnly) { 27 | P2PLifecycleListener listener = new P2PLifecycleListener(); 28 | listener.setConfigLocation(configLocation); 29 | tomcat.getServer().addLifecycleListener(listener); 30 | } else { 31 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 32 | } 33 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 34 | tomcat.getEngine().setName("engine-" + port); 35 | 36 | final Connector connector = tomcat.getConnector(); 37 | connector.setPort(port); 38 | connector.setProperty("bindOnInit", "false"); 39 | 40 | tomcat.addUser("someuser", "somepass"); 41 | tomcat.addRole("someuser", "role1"); 42 | 43 | Context context; 44 | try { 45 | context = tomcat.addWebapp("", baseDir); 46 | 47 | Wrapper asyncServlet = context.createWrapper(); 48 | asyncServlet.setName("asyncServlet"); 49 | asyncServlet.setServletClass(AsyncServlet.class.getName()); 50 | asyncServlet.setAsyncSupported(true); 51 | 52 | context.addChild(asyncServlet); 53 | context.addServletMappingDecoded("/*", "asyncServlet"); 54 | 55 | } catch (final Exception e) { 56 | throw new IllegalStateException(e); 57 | } 58 | 59 | this.manager = new HazelcastSessionManager(); 60 | context.setManager(manager); 61 | updateManager(manager); 62 | context.setCookies(true); 63 | context.setBackgroundProcessorDelay(1); 64 | context.setReloadable(true); 65 | context.addLifecycleListener(new LifecycleListener() { 66 | @Override 67 | public void lifecycleEvent(LifecycleEvent event) { 68 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 69 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 70 | } 71 | } 72 | }); 73 | 74 | return tomcat; 75 | } 76 | 77 | @Override 78 | public void start() throws Exception { 79 | tomcat = configure(); 80 | tomcat.start(); 81 | } 82 | 83 | @Override 84 | public void stop() throws Exception { 85 | if (tomcat.getServer().getState().isAvailable()) { 86 | tomcat.stop(); 87 | } 88 | } 89 | 90 | @Override 91 | public void reload() { 92 | Context context = (Context) tomcat.getHost().findChild("/"); 93 | if (context == null) { 94 | context = (Context) tomcat.getHost().findChild(""); 95 | } 96 | context.reload(); 97 | } 98 | 99 | @Override 100 | public SessionManager getManager() { 101 | return manager; 102 | } 103 | 104 | private void updateManager(HazelcastSessionManager manager) { 105 | manager.setSticky(sticky); 106 | manager.setClientOnly(clientOnly); 107 | manager.setMapName(mapName); 108 | manager.setDeferredWrite(deferredWrite); 109 | manager.setProcessExpiresFrequency(1); 110 | } 111 | } -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/Tomcat9Configurator.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import org.apache.catalina.Context; 4 | import org.apache.catalina.Lifecycle; 5 | import org.apache.catalina.LifecycleEvent; 6 | import org.apache.catalina.LifecycleListener; 7 | import org.apache.catalina.connector.Connector; 8 | import org.apache.catalina.startup.Tomcat; 9 | 10 | import java.io.File; 11 | import java.net.URL; 12 | import java.net.URLDecoder; 13 | 14 | public class Tomcat9Configurator 15 | extends WebContainerConfigurator { 16 | 17 | private Tomcat tomcat; 18 | private HazelcastSessionManager manager; 19 | private String appName; 20 | 21 | public Tomcat9Configurator(String appName) { 22 | this.appName = appName; 23 | } 24 | 25 | public Tomcat9Configurator() { 26 | this.appName = "defaultApp"; 27 | } 28 | 29 | @Override 30 | public Tomcat configure() throws Exception { 31 | final URL root = new URL(TestServlet.class.getResource("/"), "../../../tomcat-core/target/test-classes"); 32 | final String cleanedRoot = URLDecoder.decode(root.getFile(), "UTF-8"); 33 | 34 | final String fileSeparator = File.separator.equals("\\") ? "\\\\" : File.separator; 35 | final String docBase = cleanedRoot + File.separator + appName + fileSeparator; 36 | 37 | Tomcat tomcat = new Tomcat(); 38 | if (!clientOnly) { 39 | P2PLifecycleListener listener = new P2PLifecycleListener(); 40 | listener.setConfigLocation(configLocation); 41 | tomcat.getServer().addLifecycleListener(listener); 42 | } else { 43 | tomcat.getServer().addLifecycleListener(new ClientServerLifecycleListener()); 44 | } 45 | tomcat.getEngine().setJvmRoute("tomcat-" + port); 46 | tomcat.setBaseDir(docBase); 47 | 48 | tomcat.getEngine().setName("engine-" + port); 49 | 50 | final Connector connector = tomcat.getConnector(); 51 | connector.setPort(port); 52 | connector.setProperty("bindOnInit", "false"); 53 | 54 | tomcat.addUser("someuser", "somepass"); 55 | tomcat.addRole("someuser", "role1"); 56 | 57 | Context context; 58 | try { 59 | context = tomcat.addWebapp(tomcat.getHost(), "/", docBase); 60 | } catch (final Exception e) { 61 | throw new IllegalStateException(e); 62 | } 63 | 64 | this.manager = new HazelcastSessionManager(); 65 | context.setManager(manager); 66 | updateManager(manager); 67 | context.setCookies(true); 68 | context.setBackgroundProcessorDelay(1); 69 | context.setReloadable(true); 70 | context.addLifecycleListener(new LifecycleListener() { 71 | @Override 72 | public void lifecycleEvent(LifecycleEvent event) { 73 | if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) { 74 | ((Context) event.getLifecycle()).setSessionTimeout(sessionTimeout); 75 | } 76 | } 77 | }); 78 | 79 | return tomcat; 80 | } 81 | 82 | @Override 83 | public void start() throws Exception { 84 | tomcat = configure(); 85 | tomcat.start(); 86 | } 87 | 88 | @Override 89 | public void stop() throws Exception { 90 | if (tomcat.getServer().getState().isAvailable()) { 91 | tomcat.stop(); 92 | } 93 | } 94 | 95 | @Override 96 | public void reload() { 97 | Context context = (Context) tomcat.getHost().findChild("/"); 98 | if (context == null) { 99 | //Starting with Tomcat 8.0.35, child name is changed 100 | context = (Context) tomcat.getHost().findChild(""); 101 | } 102 | context.reload(); 103 | } 104 | 105 | @Override 106 | public SessionManager getManager() { 107 | return manager; 108 | } 109 | 110 | private void updateManager(HazelcastSessionManager manager) { 111 | manager.setSticky(sticky); 112 | manager.setClientOnly(clientOnly); 113 | manager.setMapName(mapName); 114 | manager.setDeferredWrite(deferredWrite); 115 | manager.setProcessExpiresFrequency(1); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/Tomcat9MapNameTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat9MapNameTest 11 | extends AbstractMapNameTest { 12 | 13 | @Override 14 | protected WebContainerConfigurator getWebContainerConfigurator() { 15 | return new Tomcat9Configurator(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/Tomcat9NonSerializableSessionTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | public class Tomcat9NonSerializableSessionTest 4 | extends AbstractNonSerializableSessionTest { 5 | @Override 6 | protected WebContainerConfigurator getWebContainerConfigurator() { 7 | return new Tomcat9Configurator(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/Tomcat9SecurityTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat9SecurityTest 11 | extends AbstractTomcatSecurityTest { 12 | @Override 13 | protected WebContainerConfigurator getTomcatConfigurator(String appName) { 14 | return new Tomcat9Configurator(appName); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/Tomcat9SessionExpireTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session; 2 | 3 | import com.hazelcast.test.HazelcastSerialClassRunner; 4 | import com.hazelcast.test.annotation.QuickTest; 5 | import org.junit.experimental.categories.Category; 6 | import org.junit.runner.RunWith; 7 | 8 | @RunWith(HazelcastSerialClassRunner.class) 9 | @Category(QuickTest.class) 10 | public class Tomcat9SessionExpireTest 11 | extends AbstractSessionExpireTest { 12 | @Override 13 | protected WebContainerConfigurator getWebContainerConfigurator() { 14 | return new Tomcat9Configurator(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/nonsticky/Tomcat9ClientServerNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat9Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat9ClientServerNonStickySessionsTest 16 | extends AbstractClientServerNonStickySessionsTest { 17 | 18 | @Override 19 | protected WebContainerConfigurator getWebContainerConfigurator() { 20 | return new Tomcat9Configurator(); 21 | } 22 | 23 | @Override 24 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 25 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 26 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/nonsticky/Tomcat9P2PNonStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.nonsticky; 2 | 3 | import com.hazelcast.session.HazelcastSession; 4 | import com.hazelcast.session.Tomcat9Configurator; 5 | import com.hazelcast.session.WebContainerConfigurator; 6 | import com.hazelcast.test.HazelcastSerialClassRunner; 7 | import com.hazelcast.test.annotation.QuickTest; 8 | import org.junit.experimental.categories.Category; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | 13 | @RunWith(HazelcastSerialClassRunner.class) 14 | @Category(QuickTest.class) 15 | public class Tomcat9P2PNonStickySessionsTest 16 | extends AbstractP2PNonStickySessionsTest { 17 | 18 | @Override 19 | protected WebContainerConfigurator getWebContainerConfigurator() { 20 | return new Tomcat9Configurator(); 21 | } 22 | 23 | @Override 24 | public void validateSessionAccessTime(HazelcastSession session1, HazelcastSession session2) { 25 | assertEquals("Session lastAccessTime should be equal", session1.getLastAccessedTime(), session2.getLastAccessedTime()); 26 | assertEquals("Session thisAccessedTime should be equal", session1.getThisAccessedTime(), session2.getThisAccessedTime()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/springboot/AbstractSpringBootConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.springboot; 2 | 3 | import com.hazelcast.core.DistributedObject; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import com.hazelcast.map.IMap; 6 | import org.apache.http.client.CookieStore; 7 | import org.apache.http.client.HttpClient; 8 | import org.apache.http.client.methods.HttpGet; 9 | import org.apache.http.impl.client.BasicCookieStore; 10 | import org.apache.http.impl.client.HttpClientBuilder; 11 | import org.junit.Test; 12 | import org.springframework.context.ApplicationContext; 13 | 14 | import java.util.LinkedList; 15 | 16 | import static org.junit.Assert.assertEquals; 17 | import static org.junit.Assert.assertNotNull; 18 | 19 | public abstract class AbstractSpringBootConfigurationTest { 20 | ApplicationContext applicationContext; 21 | 22 | abstract void setup(); 23 | 24 | abstract void clean(); 25 | 26 | @Test() 27 | public void testManagerCustomizerBean() { 28 | assertNotNull(applicationContext.getBean("hazelcastTomcatSessionManagerCustomizer")); 29 | } 30 | 31 | @Test 32 | public void testSessionMapCreated() { 33 | //given 34 | //the Spring Boot application is started 35 | //then 36 | HazelcastInstance hazelcastInstance = (HazelcastInstance) applicationContext.getBean("hazelcastInstance"); 37 | LinkedList distributedObjects = (LinkedList) hazelcastInstance.getDistributedObjects(); 38 | assertEquals("Session map should be created.", 1, distributedObjects.size()); 39 | } 40 | 41 | @Test() 42 | public void testSessionStoredInHazelcast() 43 | throws Exception { 44 | //given 45 | //the Spring Boot application is started 46 | HazelcastInstance hazelcastInstance = (HazelcastInstance) applicationContext.getBean("hazelcastInstance"); 47 | LinkedList distributedObjects = (LinkedList) hazelcastInstance.getDistributedObjects(); 48 | 49 | //when 50 | CookieStore cookieStore = new BasicCookieStore(); 51 | HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build(); 52 | HttpGet request = new HttpGet("http://localhost:9999/set"); 53 | client.execute(request); 54 | 55 | //then 56 | IMap sessionMap = hazelcastInstance.getMap(distributedObjects.get(0).getName()); 57 | assertEquals("Session should be created.",1, sessionMap.size()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/springboot/ClientServerSpringBootConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.springboot; 2 | 3 | import com.hazelcast.core.Hazelcast; 4 | import com.hazelcast.core.HazelcastInstance; 5 | import org.junit.After; 6 | import org.junit.Before; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.PropertySource; 10 | 11 | public class ClientServerSpringBootConfigurationTest 12 | extends AbstractSpringBootConfigurationTest { 13 | 14 | private HazelcastInstance hazelcastInstance; 15 | 16 | @Before 17 | public void setup() { 18 | hazelcastInstance = Hazelcast.newHazelcastInstance(); 19 | applicationContext = SpringApplication.run(ClientServerApplication.class); 20 | } 21 | 22 | @After 23 | public void clean() { 24 | SpringApplication.exit(applicationContext); 25 | hazelcastInstance.shutdown(); 26 | } 27 | 28 | @SpringBootApplication 29 | @PropertySource("classpath:clientServer.properties") 30 | static class ClientServerApplication { 31 | public static void main(String[] args) { 32 | SpringApplication.run(ClientServerApplication.class, args); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/springboot/P2PSpringBootConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.springboot; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.ComponentScan; 8 | import org.springframework.context.annotation.FilterType; 9 | 10 | public class P2PSpringBootConfigurationTest 11 | extends AbstractSpringBootConfigurationTest { 12 | 13 | @Before 14 | public void setup() { 15 | applicationContext = SpringApplication.run(P2PApplication.class); 16 | } 17 | 18 | @After 19 | public void clean() { 20 | SpringApplication.exit(applicationContext); 21 | } 22 | 23 | @SpringBootApplication 24 | @ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, 25 | classes = ClientServerSpringBootConfigurationTest.ClientServerApplication.class)) 26 | static class P2PApplication { 27 | public static void main(String[] args) { 28 | SpringApplication.run(P2PApplication.class, args); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/springboot/TestController.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.springboot; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | import javax.servlet.http.HttpSession; 7 | 8 | @RestController 9 | public class TestController { 10 | 11 | @RequestMapping("/set") 12 | public void defaultMapping(HttpSession session){ 13 | session.setAttribute("testAttr", 1); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/sticky/Tomcat9ClientServerStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat9Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat9ClientServerStickySessionsTest 13 | extends AbstractClientServerStickySessionsTest { 14 | 15 | @Override 16 | protected WebContainerConfigurator getWebContainerConfigurator() { 17 | return new Tomcat9Configurator(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tomcat9/src/test/java/com/hazelcast/session/sticky/Tomcat9P2PStickySessionsTest.java: -------------------------------------------------------------------------------- 1 | package com.hazelcast.session.sticky; 2 | 3 | import com.hazelcast.session.Tomcat9Configurator; 4 | import com.hazelcast.session.WebContainerConfigurator; 5 | import com.hazelcast.test.HazelcastSerialClassRunner; 6 | import com.hazelcast.test.annotation.QuickTest; 7 | import org.junit.experimental.categories.Category; 8 | import org.junit.runner.RunWith; 9 | 10 | @RunWith(HazelcastSerialClassRunner.class) 11 | @Category(QuickTest.class) 12 | public class Tomcat9P2PStickySessionsTest 13 | extends AbstractP2PStickySessionsTest { 14 | 15 | @Override 16 | protected WebContainerConfigurator getWebContainerConfigurator() { 17 | return new Tomcat9Configurator(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tomcat9/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | logging.level.root=INFO 2 | server.port=9999 -------------------------------------------------------------------------------- /tomcat9/src/test/resources/clientServer.properties: -------------------------------------------------------------------------------- 1 | tsm.config.location=classpath:hazelcast-client-default.xml --------------------------------------------------------------------------------