├── .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