Skip to content

Commit

Permalink
ATS-21 + upgrade to hazelcast 4
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthias Müller authored and Matthias Müller committed Feb 7, 2020
1 parent e823c78 commit 4e711b1
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 61 deletions.
17 changes: 7 additions & 10 deletions README.adoc
Expand Up @@ -4,7 +4,7 @@ image::https://www.aiticon.com/assets/images/appng_logo_760px.jpg[]
:mongo-version: 3.10.2
:jedis-version: 3.1.0
:pool2-version: 2.6.2
:hazelcast-version: 3.12.3
:hazelcast-version: 4.0

== appNG Tomcat Session
This library contains implementations of http://tomcat.apache.org/[Apache Tomcat^]s
Expand Down Expand Up @@ -85,7 +85,7 @@ Reboot the server, and sessions should now be stored in MongoDB.

== Using Hazelcast
The implementation is based on https://hazelcast.org[Hazelcast^],
using a https://docs.hazelcast.org/docs/{hazelcast-version}/javadoc/com/hazelcast/core/ReplicatedMap.html[ReplicatedMap]
using an https://docs.hazelcast.org/docs/{hazelcast-version}/javadoc/com/hazelcast/map/IMap.html[IMap].

=== Configuration
Add the following into your Tomcat `context.xml` (or the context block of the `server.xml` if applicable.)
Expand All @@ -96,25 +96,25 @@ Add the following into your Tomcat `context.xml` (or the context block of the `s
<Manager className="org.appng.tomcat.session.hazelcast.HazelcastPersistentManager">
<!-- standard configuration, using multicast -->
<Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="multicast" port="5701" instanceName="appNG" group="dev"
<Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="multicast" port="5701" instanceName="dev" clusterName="appNG"
multicastGroup="224.2.2.3" multicastPort="54327" multicastTimeoutSeconds="2" multicastTimeToLive="32" />
<!-- optionally, for all modes except 'classpath':
managementCenterUrl="http://localhost:8080/hazelcast-mancenter"
managementCenterEnabled="true"
-->
<!-- uses a config file from the classpath -->
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="classpath" configFile="hazelcast.xml" /-->
<!-- uses tcp, allowing to use a comma separated list of addresses -->
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="tcp" port="5701" instanceName="appNG" group="dev"
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="tcp" port="5701" instanceName="dev" clusterName="appNG"
tcpMembers="localhost:5701" /-->
<!-- client mode, allowing to use a comma separated list of addresses -->
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="client" instanceName="appNG" group="dev"
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="client" instanceName="dev" clusterName="appNG"
addresses="localhost:5701" /-->
<!-- standalone mode, for development purposes -->
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="standalone" port="5701" instanceName="appNG" group="dev" /-->
<!-- Store className="org.appng.tomcat.session.hazelcast.HazelcastStore" mode="standalone" port="5701" instanceName="dev" clusterName="appNG" /-->
</Manager>
----

Expand All @@ -123,9 +123,6 @@ Copy the following files into the `TOMCAT_BASE/lib` directory:
* appng-tomcat-session-{version}.jar
* http://repo1.maven.org/maven2/com/hazelcast/hazelcast/{hazelcast-version}/hazelcast-{hazelcast-version}.jar[hazelcast-{hazelcast-version}.jar]

When using `client`-mode, you also need
* http://repo1.maven.org/maven2/com/hazelcast/hazelcast-client/{hazelcast-version}/hazelcast-client-{hazelcast-version}.jar[hazelcast-client-{hazelcast-version}.jar]

Reboot the server, and sessions are now stored in Hazelcast.

== License
Expand Down
4 changes: 2 additions & 2 deletions pom.xml
Expand Up @@ -229,8 +229,8 @@
</dependency>
<dependency>
<groupId>com.hazelcast</groupId>
<artifactId>hazelcast-client</artifactId>
<version>3.12.3</version>
<artifactId>hazelcast</artifactId>
<version>4.0</version>
</dependency>
</dependencies>
</project>
68 changes: 68 additions & 0 deletions src/main/java/org/appng/tomcat/session/SessionData.java
@@ -0,0 +1,68 @@
/*
* Copyright 2015-2020 the original author or authors.
*
* 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.
*/
package org.appng.tomcat.session;

import java.io.Serializable;

/**
* Used to persist the binary representation of {@link org.apache.catalina.Session}.
*/
public class SessionData implements Serializable {

private String id;
private String site;
private byte[] data;

public SessionData() {

}

public SessionData(String id, String site, byte[] data) {
this.id = id;
this.site = site;
this.data = data;
}

public String getSite() {
return site;
}

public void setSite(String site) {
this.site = site;
}

public byte[] getData() {
return data;
}

public void setData(byte[] data) {
this.data = data;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

@Override
public String toString() {
return String.format("[%s] %s (%skb)", site, id, data.length / 1000);
}

}
49 changes: 46 additions & 3 deletions src/main/java/org/appng/tomcat/session/Utils.java
Expand Up @@ -26,6 +26,7 @@
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;

import org.apache.catalina.Container;
import org.apache.catalina.Context;
Expand Down Expand Up @@ -67,8 +68,7 @@ public static boolean isTemplateRequest(Request request) {

public static String getTemplatePrefix(ServletContext servletContext) {
try {
@SuppressWarnings("unchecked")
Map<String, Object> platformProperties = (Map<String, Object>) servletContext.getAttribute("PLATFORM");
Map<String, Object> platformProperties = getPlatform(servletContext);
if (null != platformProperties) {
Object platformConfig = platformProperties.get("platformConfig");
return (String) platformConfig.getClass().getMethod("getString", String.class).invoke(platformConfig,
Expand All @@ -80,6 +80,11 @@ public static String getTemplatePrefix(ServletContext servletContext) {
return null;
}

@SuppressWarnings("unchecked")
public static Map<String, Object> getPlatform(ServletContext servletContext) {
return (Map<String, Object>) servletContext.getAttribute("PLATFORM");
}

public static ObjectInputStream getObjectInputStream(ClassLoader classLoader, ServletContext ctx, byte[] data)
throws IOException {
return getObjectInputStream(classLoader, ctx, new ByteArrayInputStream(data));
Expand All @@ -92,7 +97,6 @@ public static ObjectInputStream getObjectInputStream(ClassLoader classLoader, Se
Constructor<ObjectInputStream> constructor = (Constructor<ObjectInputStream>) classLoader
.loadClass(Constants.INPUT_STREAM_CLASS)
.getDeclaredConstructor(InputStream.class, ServletContext.class);

return constructor.newInstance(data, ctx);
} catch (ReflectiveOperationException e) {
// ignore, webapp is not appNG
Expand Down Expand Up @@ -234,4 +238,43 @@ public static Session[] findSessions(Manager manager, String[] keys, Log log) {
return sessions.toArray(new Session[0]);
}

public static String getSiteName(HttpSession session) {
Object metaData = session.getAttribute("metaData");
if (null != metaData) {
try {
return (String) metaData.getClass().getMethod("getSite").invoke(metaData);
} catch (ReflectiveOperationException e) {
// ignore
}
}
return null;
}

@SuppressWarnings("rawtypes")
private static ClassLoader getClassLoader(String siteName, Context context) {
Map<String, Object> platform = getPlatform(context.getServletContext());
if (null != platform && null != siteName) {
Object siteMap = (Map) platform.get("sites");
Object site;
if (null != siteMap && (site = ((Map) siteMap).get(siteName)) != null) {
try {
return (ClassLoader) site.getClass().getMethod("getSiteClassLoader").invoke(site);
} catch (ReflectiveOperationException e) {
// ignore
}
}
}
return context.getLoader().getClassLoader();
}

public static ObjectInputStream getObjectInputStream(InputStream in, String siteName, Context context)
throws IOException {
final ClassLoader classLoader = getClassLoader(siteName, context);
return new ObjectInputStream(in) {
protected Class<?> resolveClass(java.io.ObjectStreamClass desc) throws IOException, ClassNotFoundException {
return Class.forName(desc.getName(), false, classLoader);
}
};
}

}
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2019 the original author or authors.
* Copyright 2015-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -34,6 +34,11 @@ protected void destroyInternal() throws LifecycleException {
getStore().destroy();
}

@Override
public void processExpires() {
// nothing to do here, we use a EntryEvictedListener!
}

@Override
public HazelcastStore getStore() {
return (HazelcastStore) super.getStore();
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2015-2019 the original author or authors.
* Copyright 2015-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -44,10 +44,10 @@ public void invoke(Request request, Response response) throws IOException, Servl
Session session = request.getSessionInternal(false);
if (session != null) {
if (session.isValid()) {
log.debug(String.format("Request with session completed, saving session %s", session.getId()));
log.trace(String.format("Request with session completed, saving session %s", session.getId()));
manager.getStore().save(session);
} else {
log.debug(String.format("HTTP Session has been invalidated, removing %s", session.getId()));
log.trace(String.format("HTTP Session has been invalidated, removing %s", session.getId()));
manager.remove(session);
}
}
Expand Down

0 comments on commit 4e711b1

Please sign in to comment.