Skip to content

Commit

Permalink
Merge pull request #68 from alparslanavci/custom-serialization-support
Browse files Browse the repository at this point in the history
Added support for all serialization methods in Hazelcast
  • Loading branch information
alparslanavci authored Nov 12, 2019
2 parents ac8d5a1 + 54be3dd commit dd7a33e
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The latest tested versions are **6.0.39**, **7.0.40** and **8.0.36**.
***Requirements***

- Tomcat instance must be running with Java 1.6 or higher.
- Session objects that need to be clustered have to be Serializable.
- Session objects that need to be clustered have to be serializable on Hazelcast cluster. Please see <a href="https://docs.hazelcast.org/docs/latest/manual/html-single/#serialization" target="_blank">here</a> for how you can configure and implement serialization for Hazelcast.

# How Tomcat Session Replication Works

Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
<sonar.language>java</sonar.language>
<sonar.verbose>true</sonar.verbose>
<maven.source.plugin.version>2.2.1</maven.source.plugin.version>
<kryo.version>5.0.0-RC4</kryo.version>
</properties>

<licenses>
Expand Down
6 changes: 6 additions & 0 deletions tomcat-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
<version>${tomcat-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>${kryo.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.apache.juli.logging.LogFactory;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.security.Principal;
import java.util.ArrayList;
Expand Down Expand Up @@ -128,16 +127,19 @@ private void serializeMap(Map map, ObjectDataOutput objectDataOutput) throws IOE
Map.Entry entry = (Map.Entry) entryObject;
Object key = entry.getKey();
Object value = entry.getValue();
if (key != null && value != null && key instanceof Serializable && value instanceof Serializable) {
if (key != null && value != null) {
serializableEntries.put(key, value);
}
}

objectDataOutput.writeInt(serializableEntries.size());
for (Map.Entry<Object, Object> entryObject : serializableEntries.entrySet()) {
Map.Entry entry = (Map.Entry) entryObject;
objectDataOutput.writeObject(entry.getKey());
objectDataOutput.writeObject(entry.getValue());
try {
objectDataOutput.writeObject(entryObject.getKey());
objectDataOutput.writeObject(entryObject.getValue());
} catch (Exception e) {
LOG.warn("Unable to serialize object in session", e);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2008-2019, Hazelcast, Inc. All Rights Reserved.
*/

package com.hazelcast.session;

public class CustomAttribute {
private String value;

//Needed for Kryo
public CustomAttribute() {
}

public CustomAttribute(String value) {
this.value = value;
}

@Override
public String toString() {
return "CustomAttribute{" + "value='" + value + '\'' + '}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.hazelcast.session;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.InputChunked;
import com.esotericsoftware.kryo.io.OutputChunked;
import com.hazelcast.nio.ObjectDataInput;
import com.hazelcast.nio.ObjectDataOutput;
import com.hazelcast.nio.serialization.StreamSerializer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class HazelcastGlobalKryoSerializer
implements StreamSerializer {

private final ThreadLocal<Kryo> kryoThreadLocal = new ThreadLocal<Kryo>() {
@Override
protected Kryo initialValue() {
Kryo kryo = new Kryo();
kryo.register(CustomAttribute.class);
return kryo;
}
};

@Override
public int getTypeId() {
return 123;
}

@Override
public void write(ObjectDataOutput objectDataOutput, Object object)
throws IOException {
OutputChunked output = new OutputChunked((OutputStream) objectDataOutput, 4096);
kryoThreadLocal.get().writeClassAndObject(output, object);
output.endChunk();
output.flush();
}

@Override
public Object read(ObjectDataInput objectDataInput)
throws IOException {
InputStream in = (InputStream) objectDataInput;
InputChunked input = new InputChunked(in, 4096);
return kryoThreadLocal.get().readClassAndObject(input);
}

@Override
public void destroy() {
}

}
13 changes: 6 additions & 7 deletions tomcat-core/src/test/java/com/hazelcast/session/TestServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,23 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
if (req.getRequestURI().endsWith("write")) {
session.setAttribute("key", "value");
resp.getWriter().write("true");

} else if (req.getRequestURI().endsWith("read")) {
Object value = session.getAttribute("key");
resp.getWriter().write(value == null ? "null" : value.toString());

} else if (req.getRequestURI().endsWith("remove")) {
session.removeAttribute("key");
resp.getWriter().write("true");

} else if (req.getRequestURI().endsWith("invalidate")) {
session.invalidate();
resp.getWriter().write("true");

} else if (req.getRequestURI().endsWith("update")) {
session.setAttribute("key", "value-updated");
resp.getWriter().write("true");

} else if (req.getRequestURI().endsWith("names")) {
List names = Collections.list(session.getAttributeNames());
String nameList = names.toString();
//return comma separated list of attribute names
resp.getWriter().write(nameList.substring(1, nameList.length() - 1).replace(", ", ","));

} else if (req.getRequestURI().endsWith("reload")) {
session.invalidate();
session = req.getSession();
Expand All @@ -56,8 +50,13 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Se
resp.getWriter().write(String.valueOf(session.getLastAccessedTime()));
} else if (req.getRequestURI().endsWith("nonserializable")) {
session.setAttribute("key", new Object());

resp.getWriter().write("true");
} else if (req.getRequestURI().endsWith("write-custom-attribute")) {
session.setAttribute("key", new CustomAttribute("value"));
resp.getWriter().write("true");
} else if (req.getRequestURI().endsWith("read-custom-attribute")) {
CustomAttribute value = (CustomAttribute) session.getAttribute("key");
resp.getWriter().write(value == null ? "null" : value.toString());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IMap;
import com.hazelcast.session.AbstractHazelcastSessionsTest;
import com.hazelcast.session.CustomAttribute;
import com.hazelcast.session.HazelcastSession;
import com.hazelcast.session.WebContainerConfigurator;
import org.apache.catalina.Manager;
Expand Down Expand Up @@ -41,6 +42,20 @@ public void testReadWriteRead() throws Exception {
assertEquals("value", value);
}

@Test
public void testReadWriteReadWithCustomSerialization() throws Exception {
CustomAttribute expected = new CustomAttribute("value");

CookieStore cookieStore = new BasicCookieStore();
String value = executeRequest("read-custom-attribute", SERVER_PORT_1, cookieStore);
assertEquals("null", value);

executeRequest("write-custom-attribute", SERVER_PORT_1, cookieStore);

value = executeRequest("read-custom-attribute", SERVER_PORT_2, cookieStore);
assertEquals(expected.toString(), value);
}

@Test(timeout = 60000)
public void testAttributeDistribution() throws Exception {
CookieStore cookieStore = new BasicCookieStore();
Expand Down
30 changes: 30 additions & 0 deletions tomcat-core/src/test/resources/hazelcast-client-default.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2008-2019, Hazelcast, Inc. All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<!--suppress XmlDefaultAttributeValue -->
<hazelcast-client xmlns="http://www.hazelcast.com/schema/client-config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.hazelcast.com/schema/client-config
http://www.hazelcast.com/schema/client-config/hazelcast-client-config-3.11.xsd">

<serialization>
<serializers>
<global-serializer>com.hazelcast.session.HazelcastGlobalKryoSerializer</global-serializer>
</serializers>
</serialization>

</hazelcast-client>
8 changes: 7 additions & 1 deletion tomcat-core/src/test/resources/hazelcast.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config hazelcast-config.xsd"
<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/client-config/hazelcast-config-3.11.xsd"
xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<network>
Expand All @@ -26,4 +26,10 @@
</tcp-ip>
</join>
</network>

<serialization>
<serializers>
<global-serializer>com.hazelcast.session.HazelcastGlobalKryoSerializer</global-serializer>
</serializers>
</serialization>
</hazelcast>
6 changes: 6 additions & 0 deletions tomcat8/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
<version>${tomcat-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>${kryo.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
6 changes: 6 additions & 0 deletions tomcat85/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@
<version>${tomcat-version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>${kryo.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>

0 comments on commit dd7a33e

Please sign in to comment.