Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.

Commit b2dfa69

Browse files
committed
Utilize container's classloader
Resolves #15
1 parent bc59817 commit b2dfa69

File tree

6 files changed

+204
-3
lines changed

6 files changed

+204
-3
lines changed

src/main/java/org/springframework/session/data/mongo/config/annotation/web/http/MongoHttpSessionConfiguration.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,22 @@
1515
*/
1616
package org.springframework.session.data.mongo.config.annotation.web.http;
1717

18+
import java.time.Duration;
19+
20+
import org.springframework.beans.factory.BeanClassLoaderAware;
1821
import org.springframework.beans.factory.annotation.Autowired;
1922
import org.springframework.context.EmbeddedValueResolverAware;
2023
import org.springframework.context.annotation.Bean;
2124
import org.springframework.context.annotation.Configuration;
2225
import org.springframework.context.annotation.ImportAware;
2326
import org.springframework.core.annotation.AnnotationAttributes;
27+
import org.springframework.core.serializer.support.DeserializingConverter;
28+
import org.springframework.core.serializer.support.SerializingConverter;
2429
import org.springframework.core.type.AnnotationMetadata;
2530
import org.springframework.data.mongodb.core.MongoOperations;
2631
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
2732
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
33+
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
2834
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
2935
import org.springframework.util.StringUtils;
3036
import org.springframework.util.StringValueResolver;
@@ -39,12 +45,13 @@
3945
*/
4046
@Configuration
4147
public class MongoHttpSessionConfiguration extends SpringHttpSessionConfiguration
42-
implements EmbeddedValueResolverAware, ImportAware {
48+
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
4349

4450
private AbstractMongoSessionConverter mongoSessionConverter;
4551
private Integer maxInactiveIntervalInSeconds;
4652
private String collectionName;
4753
private StringValueResolver embeddedValueResolver;
54+
private ClassLoader classLoader;
4855

4956
@Bean
5057
public MongoOperationsSessionRepository mongoSessionRepository(MongoOperations mongoOperations) {
@@ -54,6 +61,12 @@ public MongoOperationsSessionRepository mongoSessionRepository(MongoOperations m
5461

5562
if (this.mongoSessionConverter != null) {
5663
repository.setMongoSessionConverter(this.mongoSessionConverter);
64+
} else {
65+
JdkMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
66+
new SerializingConverter(),
67+
new DeserializingConverter(this.classLoader),
68+
Duration.ofSeconds(MongoOperationsSessionRepository.DEFAULT_INACTIVE_INTERVAL));
69+
repository.setMongoSessionConverter(mongoSessionConverter);
5770
}
5871

5972
if (StringUtils.hasText(this.collectionName)) {
@@ -89,6 +102,12 @@ public void setMongoSessionConverter(AbstractMongoSessionConverter mongoSessionC
89102
this.mongoSessionConverter = mongoSessionConverter;
90103
}
91104

105+
@Override
106+
public void setBeanClassLoader(ClassLoader classLoader) {
107+
this.classLoader = classLoader;
108+
}
109+
110+
@Override
92111
public void setEmbeddedValueResolver(StringValueResolver resolver) {
93112
this.embeddedValueResolver = resolver;
94113
}

src/main/java/org/springframework/session/data/mongo/config/annotation/web/reactive/ReactiveMongoWebSessionConfiguration.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,24 @@
1515
*/
1616
package org.springframework.session.data.mongo.config.annotation.web.reactive;
1717

18+
import java.time.Duration;
19+
20+
import org.springframework.beans.factory.BeanClassLoaderAware;
1821
import org.springframework.beans.factory.annotation.Autowired;
1922
import org.springframework.context.EmbeddedValueResolverAware;
2023
import org.springframework.context.annotation.Bean;
2124
import org.springframework.context.annotation.Configuration;
2225
import org.springframework.context.annotation.ImportAware;
2326
import org.springframework.core.annotation.AnnotationAttributes;
27+
import org.springframework.core.serializer.support.DeserializingConverter;
28+
import org.springframework.core.serializer.support.SerializingConverter;
2429
import org.springframework.core.type.AnnotationMetadata;
2530
import org.springframework.data.mongodb.core.MongoOperations;
2631
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
2732
import org.springframework.session.config.annotation.web.server.SpringWebSessionConfiguration;
2833
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
34+
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
35+
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
2936
import org.springframework.session.data.mongo.ReactiveMongoOperationsSessionRepository;
3037
import org.springframework.util.StringUtils;
3138
import org.springframework.util.StringValueResolver;
@@ -38,7 +45,7 @@
3845
*/
3946
@Configuration
4047
public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfiguration
41-
implements EmbeddedValueResolverAware, ImportAware {
48+
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware {
4249

4350
private AbstractMongoSessionConverter mongoSessionConverter;
4451
private Integer maxInactiveIntervalInSeconds;
@@ -47,6 +54,7 @@ public class ReactiveMongoWebSessionConfiguration extends SpringWebSessionConfig
4754

4855
@Autowired(required = false)
4956
private MongoOperations mongoOperations;
57+
private ClassLoader classLoader;
5058

5159
@Bean
5260
public ReactiveMongoOperationsSessionRepository reactiveMongoOperationsSessionRepository(ReactiveMongoOperations operations) {
@@ -55,6 +63,12 @@ public ReactiveMongoOperationsSessionRepository reactiveMongoOperationsSessionRe
5563

5664
if (this.mongoSessionConverter != null) {
5765
repository.setMongoSessionConverter(this.mongoSessionConverter);
66+
} else {
67+
JdkMongoSessionConverter mongoSessionConverter = new JdkMongoSessionConverter(
68+
new SerializingConverter(),
69+
new DeserializingConverter(this.classLoader),
70+
Duration.ofSeconds(ReactiveMongoOperationsSessionRepository.DEFAULT_INACTIVE_INTERVAL));
71+
repository.setMongoSessionConverter(mongoSessionConverter);
5872
}
5973

6074
if (this.maxInactiveIntervalInSeconds != null) {
@@ -92,6 +106,11 @@ public void setImportMetadata(AnnotationMetadata importMetadata) {
92106

93107
}
94108

109+
@Override
110+
public void setBeanClassLoader(ClassLoader classLoader) {
111+
this.classLoader = classLoader;
112+
}
113+
95114
@Override
96115
public void setEmbeddedValueResolver(StringValueResolver embeddedValueResolver) {
97116
this.embeddedValueResolver = embeddedValueResolver;
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.session.data.mongo.integration;
17+
18+
import static org.assertj.core.api.AssertionsForClassTypes.*;
19+
20+
import java.lang.reflect.Field;
21+
22+
import org.junit.Test;
23+
import org.springframework.beans.factory.annotation.Autowired;
24+
import org.springframework.context.ApplicationContext;
25+
import org.springframework.core.serializer.DefaultDeserializer;
26+
import org.springframework.core.serializer.support.DeserializingConverter;
27+
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
28+
import org.springframework.session.data.mongo.JdkMongoSessionConverter;
29+
import org.springframework.util.ReflectionUtils;
30+
31+
/**
32+
* Verify container's {@link ClassLoader} is injected into session converter (reactive and traditional).
33+
*
34+
* @author Greg Turnquist
35+
*/
36+
public abstract class AbstractClassLoaderTest<T> extends AbstractITest {
37+
38+
@Autowired
39+
T sessionRepository;
40+
41+
@Autowired
42+
ApplicationContext applicationContext;
43+
44+
@Test
45+
public void verifyContainerClassLoaderLoadedIntoConverter() {
46+
47+
Field mongoSessionConverterField = ReflectionUtils.findField(sessionRepository.getClass(), "mongoSessionConverter");
48+
ReflectionUtils.makeAccessible(mongoSessionConverterField);
49+
AbstractMongoSessionConverter sessionConverter = (AbstractMongoSessionConverter) ReflectionUtils.getField(mongoSessionConverterField, this.sessionRepository);
50+
51+
assertThat(sessionConverter).isInstanceOf(JdkMongoSessionConverter.class);
52+
53+
JdkMongoSessionConverter jdkMongoSessionConverter = (JdkMongoSessionConverter) sessionConverter;
54+
55+
Field converterField = ReflectionUtils.findField(JdkMongoSessionConverter.class, "deserializer");
56+
ReflectionUtils.makeAccessible(converterField);
57+
DeserializingConverter deserializingConverter = (DeserializingConverter) ReflectionUtils.getField(converterField, jdkMongoSessionConverter);
58+
59+
Field deserializerField = ReflectionUtils.findField(DeserializingConverter.class, "deserializer");
60+
ReflectionUtils.makeAccessible(deserializerField);
61+
DefaultDeserializer deserializer = (DefaultDeserializer) ReflectionUtils.getField(deserializerField, deserializingConverter);
62+
63+
Field classLoaderField = ReflectionUtils.findField(DefaultDeserializer.class, "classLoader");
64+
ReflectionUtils.makeAccessible(classLoaderField);
65+
ClassLoader classLoader = (ClassLoader) ReflectionUtils.getField(classLoaderField, deserializer);
66+
67+
assertThat(classLoader).isEqualTo(applicationContext.getClassLoader());
68+
}
69+
70+
}

src/test/java/org/springframework/session/data/mongo/integration/MongoRepositoryJdkSerializationITest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.Map;
2222

2323
import org.junit.Test;
24-
2524
import org.springframework.context.annotation.Bean;
2625
import org.springframework.context.annotation.Configuration;
2726
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.session.data.mongo.integration;
17+
18+
import java.io.IOException;
19+
20+
import de.flapdoodle.embed.mongo.MongodExecutable;
21+
import org.springframework.context.annotation.Bean;
22+
import org.springframework.context.annotation.Configuration;
23+
import org.springframework.context.annotation.DependsOn;
24+
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
25+
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
26+
import org.springframework.session.data.mongo.ReactiveMongoOperationsSessionRepository;
27+
import org.springframework.session.data.mongo.config.annotation.web.reactive.EnableMongoWebSession;
28+
import org.springframework.test.context.ContextConfiguration;
29+
import org.springframework.util.SocketUtils;
30+
31+
import com.mongodb.reactivestreams.client.MongoClient;
32+
import com.mongodb.reactivestreams.client.MongoClients;
33+
34+
/**
35+
* @author Greg Turnquist
36+
*/
37+
@ContextConfiguration
38+
public class ReactiveConfigurationTest extends AbstractClassLoaderTest<ReactiveMongoOperationsSessionRepository> {
39+
40+
@Configuration
41+
@EnableMongoWebSession
42+
static class Config {
43+
44+
private int embeddedMongoPort = SocketUtils.findAvailableTcpPort();
45+
46+
@Bean(initMethod = "start", destroyMethod = "stop")
47+
public MongodExecutable embeddedMongoServer() throws IOException {
48+
return MongoITestUtils.embeddedMongoServer(this.embeddedMongoPort);
49+
}
50+
51+
@Bean
52+
@DependsOn("embeddedMongoServer")
53+
public ReactiveMongoOperations mongoOperations() {
54+
55+
MongoClient mongo = MongoClients.create("mongodb://localhost:" + this.embeddedMongoPort);
56+
return new ReactiveMongoTemplate(mongo, "test");
57+
}
58+
59+
}
60+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2018 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
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,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.session.data.mongo.integration;
17+
18+
import org.springframework.context.annotation.Configuration;
19+
import org.springframework.session.data.mongo.MongoOperationsSessionRepository;
20+
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
21+
import org.springframework.session.data.mongo.integration.AbstractMongoRepositoryITest.BaseConfig;
22+
import org.springframework.test.context.ContextConfiguration;
23+
24+
/**
25+
* @author Greg Turnquist
26+
*/
27+
@ContextConfiguration
28+
public class TraditionalConfigurationTest extends AbstractClassLoaderTest<MongoOperationsSessionRepository> {
29+
30+
@Configuration
31+
@EnableMongoHttpSession
32+
static class Config extends BaseConfig {
33+
}
34+
}

0 commit comments

Comments
 (0)