Skip to content

Commit 33f9d4b

Browse files
committed
Fix bug when parsing Spring Boot, spring.session.timeout property with java.time.Duration styling.
Resolves gh-113.
1 parent aabcb04 commit 33f9d4b

11 files changed

+373
-7
lines changed

spring-geode-project/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/SpringSessionAutoConfiguration.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.springframework.data.gemfire.util.CollectionUtils.asSet;
1919

20+
import java.time.Duration;
2021
import java.util.Properties;
2122
import java.util.Set;
2223

@@ -40,6 +41,8 @@
4041
import org.springframework.core.env.PropertySource;
4142
import org.springframework.core.type.AnnotatedTypeMetadata;
4243
import org.springframework.geode.boot.autoconfigure.support.EnableSubscriptionConfiguration;
44+
import org.springframework.lang.NonNull;
45+
import org.springframework.lang.Nullable;
4346
import org.springframework.session.Session;
4447
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
4548
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
@@ -108,11 +111,13 @@ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringAp
108111

109112
if (isSet(environment, SPRING_SESSION_TIMEOUT_PROPERTY)) {
110113
springSessionProperties.setProperty(SPRING_SESSION_DATA_GEMFIRE_SESSION_EXPIRATION_TIMEOUT,
111-
environment.getProperty(SPRING_SESSION_TIMEOUT_PROPERTY));
114+
toSecondsAsString(environment.getProperty(SPRING_SESSION_TIMEOUT_PROPERTY, Duration.class,
115+
getDefaultSessionTimeout())));
112116
}
113117
else if (isSet(environment, SERVER_SERVLET_SESSION_TIMEOUT_PROPERTY)) {
114118
springSessionProperties.setProperty(SPRING_SESSION_DATA_GEMFIRE_SESSION_EXPIRATION_TIMEOUT,
115-
environment.getProperty(SERVER_SERVLET_SESSION_TIMEOUT_PROPERTY));
119+
toSecondsAsString(environment.getProperty(SERVER_SERVLET_SESSION_TIMEOUT_PROPERTY,
120+
Duration.class, getDefaultSessionTimeout())));
116121
}
117122

118123
if (!springSessionProperties.isEmpty()) {
@@ -127,6 +132,20 @@ private PropertySource<?> newPropertySource(String name, Properties properties)
127132
}
128133
}
129134

135+
protected static @NonNull Duration getDefaultSessionTimeout() {
136+
return Duration.ofSeconds(GemFireHttpSessionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS);
137+
}
138+
139+
protected static int toSeconds(@Nullable Duration duration) {
140+
141+
return duration != null ? Long.valueOf(duration.getSeconds()).intValue()
142+
: GemFireHttpSessionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS;
143+
}
144+
145+
protected static @NonNull String toSecondsAsString(@Nullable Duration duration) {
146+
return String.valueOf(toSeconds(duration));
147+
}
148+
130149
protected static boolean isNotSet(ConfigurableEnvironment environment, String propertyName) {
131150
return !isSet(environment, propertyName);
132151
}

spring-geode-project/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/configuration/SpringSessionProperties.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,14 @@
1515
*/
1616
package org.springframework.geode.boot.autoconfigure.configuration;
1717

18+
import java.time.Duration;
19+
1820
import org.apache.geode.cache.RegionShortcut;
1921
import org.apache.geode.cache.client.ClientRegionShortcut;
2022

2123
import org.springframework.boot.context.properties.ConfigurationProperties;
2224
import org.springframework.boot.context.properties.NestedConfigurationProperty;
25+
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
2326

2427
/**
2528
* Spring Boot {@link ConfigurationProperties} used to configure Spring Session for Apache Geode (SSDG) in order to
@@ -190,6 +193,15 @@ public int getMaxInactiveIntervalSeconds() {
190193
public void setMaxInactiveIntervalSeconds(int maxInactiveIntervalSeconds) {
191194
this.maxInactiveIntervalSeconds = maxInactiveIntervalSeconds;
192195
}
196+
197+
public void setMaxInactiveInterval(Duration duration) {
198+
199+
int maxInactiveIntervalInSeconds = duration != null
200+
? Long.valueOf(duration.toSeconds()).intValue()
201+
: GemFireHttpSessionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS;
202+
203+
setMaxInactiveIntervalSeconds(maxInactiveIntervalInSeconds);
204+
}
193205
}
194206

195207
public static class SessionRegionProperties {

spring-geode-project/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/configuration/SpringSessionPropertiesIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public void clientCacheConfigurationIsCorrect() {
113113
PdxSerializer pdxSerializer = this.clientCache.getPdxSerializer();
114114

115115
assertThat(pdxSerializer).isInstanceOf(PdxSerializerSessionSerializerAdapter.class);
116-
assertThat(((PdxSerializerSessionSerializerAdapter) pdxSerializer).getSessionSerializer())
116+
assertThat(((PdxSerializerSessionSerializerAdapter<?>) pdxSerializer).getSessionSerializer())
117117
.isEqualTo(mockSessionSerializer);
118118
}
119119

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2017-present 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+
* https://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
13+
* or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
package org.springframework.geode.boot.autoconfigure.session;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import org.junit.Test;
21+
22+
import org.springframework.beans.factory.annotation.Autowired;
23+
import org.springframework.boot.autoconfigure.SpringBootApplication;
24+
import org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport;
25+
import org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects;
26+
import org.springframework.session.Session;
27+
import org.springframework.session.SessionRepository;
28+
import org.springframework.session.data.gemfire.GemFireOperationsSessionRepository;
29+
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
30+
31+
/**
32+
* Abstract base test class for {@link Session} {@literal} in the configured {@literal time unit},
33+
* for example: seconds, minutes, etc.
34+
*
35+
* @author John Blum
36+
* @see org.junit.Test
37+
* @see org.springframework.boot.autoconfigure.SpringBootApplication
38+
* @see org.springframework.data.gemfire.tests.integration.IntegrationTestsSupport
39+
* @see org.springframework.data.gemfire.tests.mock.annotation.EnableGemFireMockObjects
40+
* @see org.springframework.session.Session
41+
* @see org.springframework.session.SessionRepository
42+
* @see org.springframework.session.data.gemfire.GemFireOperationsSessionRepository
43+
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
44+
* @since 2.0.0
45+
*/
46+
@SuppressWarnings("unused")
47+
public abstract class AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests extends IntegrationTestsSupport {
48+
49+
@Autowired
50+
private GemFireHttpSessionConfiguration configuration;
51+
52+
@Autowired
53+
private SessionRepository<Session> repository;
54+
55+
protected int getExpectedMaxInactiveIntervalInSeconds() {
56+
return GemFireHttpSessionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL_IN_SECONDS;
57+
}
58+
59+
@Test
60+
public void sessionTimeoutConfigurationIsCorrect() {
61+
62+
int expectedMaxInactiveIntervalInSeconds = getExpectedMaxInactiveIntervalInSeconds();
63+
64+
assertThat(this.configuration).isNotNull();
65+
assertThat(this.configuration.getMaxInactiveIntervalInSeconds()).isEqualTo(expectedMaxInactiveIntervalInSeconds);
66+
assertThat(this.repository).isInstanceOf(GemFireOperationsSessionRepository.class);
67+
68+
Session session = this.repository.createSession();
69+
70+
assertThat(session).isNotNull();
71+
assertThat(session.getMaxInactiveInterval().getSeconds()).isEqualTo(expectedMaxInactiveIntervalInSeconds);
72+
}
73+
74+
@SpringBootApplication
75+
@EnableGemFireMockObjects
76+
static class TestConfiguration { }
77+
78+
}

spring-geode-project/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/session/CustomConfiguredSessionCachingIntegrationTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private static Properties singletonProperties(String propertyName, String proper
109109
private Function<SpringApplicationBuilder, SpringApplicationBuilder> newSpringBootSessionPropertiesConfigurationFunction() {
110110

111111
return springApplicationBuilder ->
112-
springApplicationBuilder.properties(singletonProperties("spring.session.timeout", "300"));
112+
springApplicationBuilder.properties(singletonProperties("spring.session.timeout", "300s"));
113113
}
114114

115115
private Function<ConfigurableApplicationContext, ConfigurableApplicationContext> newSpringSessionGemFirePropertiesConfigurationFunction() {
@@ -134,7 +134,7 @@ private Function<ConfigurableApplicationContext, ConfigurableApplicationContext>
134134
private Function<SpringApplicationBuilder, SpringApplicationBuilder> newWebServerSessionPropertiesConfigurationFunction() {
135135

136136
return springApplicationBuilder ->
137-
springApplicationBuilder.properties(singletonProperties("server.servlet.session.timeout", "3600"));
137+
springApplicationBuilder.properties(singletonProperties("server.servlet.session.timeout", "3600s"));
138138
}
139139

140140
@Override
@@ -259,10 +259,10 @@ public void springSessionExpirationTimeoutConfiguredWithWebContainerProperties()
259259
.isEqualTo(3600);
260260
}
261261

262+
//@SpringBootApplication
262263
@SpringBootConfiguration
263264
@EnableAutoConfiguration
264265
@EnableGemFireMockObjects
265-
//@SpringBootApplication
266266
static class TestConfiguration {
267267

268268
@Bean("MockSessionSerializer")

spring-geode-project/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure/session/SessionExpirationIntegrationTests.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.assertj.core.api.Assertions.assertThat;
1919

20+
import java.time.Duration;
2021
import java.util.concurrent.TimeUnit;
2122

2223
import jakarta.annotation.Resource;
@@ -62,9 +63,10 @@
6263
*/
6364
@RunWith(SpringRunner.class)
6465
@SpringBootTest(
66+
classes = SessionExpirationIntegrationTests.TestConfiguration.class,
6567
properties = {
6668
"spring.session.data.gemfire.cache.client.region.shortcut=LOCAL",
67-
"spring.session.timeout=1",
69+
"spring.session.timeout=1s",
6870
},
6971
webEnvironment = SpringBootTest.WebEnvironment.MOCK
7072
)
@@ -98,6 +100,7 @@ public void sessionExpirationIsCorrect() {
98100
assertThat(session).isNotNull();
99101
assertThat(session.getId()).isNotBlank();
100102
assertThat(session.isExpired()).isFalse();
103+
assertThat(session.getMaxInactiveInterval()).isEqualTo(Duration.ofSeconds(1));
101104

102105
this.sessionRepository.save(session);
103106

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2017-present 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+
* https://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
13+
* or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
package org.springframework.geode.boot.autoconfigure.session;
17+
18+
import java.time.Duration;
19+
20+
import org.junit.runner.RunWith;
21+
22+
import org.springframework.boot.test.context.SpringBootTest;
23+
import org.springframework.session.Session;
24+
import org.springframework.test.context.junit4.SpringRunner;
25+
26+
/**
27+
* Integration Tests for {@link Session} {@literal expiration timeout} in {@literal days}.
28+
*
29+
* @author John Blum
30+
* @see java.time.Duration
31+
* @see org.springframework.boot.test.context.SpringBootTest
32+
* @see org.springframework.geode.boot.autoconfigure.session.AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests
33+
* @see org.springframework.session.Session
34+
* @see org.springframework.test.context.junit4.SpringRunner
35+
* @since 2.0.0
36+
*/
37+
@RunWith(SpringRunner.class)
38+
@SpringBootTest(
39+
classes = AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests.TestConfiguration.class,
40+
properties = "spring.session.timeout=5d",
41+
webEnvironment = SpringBootTest.WebEnvironment.MOCK
42+
)
43+
public class SessionExpirationTimeoutInDaysIntegrationTests
44+
extends AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests {
45+
46+
@Override
47+
protected int getExpectedMaxInactiveIntervalInSeconds() {
48+
return Long.valueOf(Duration.ofDays(5).toSeconds()).intValue();
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2017-present 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+
* https://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
13+
* or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
package org.springframework.geode.boot.autoconfigure.session;
17+
18+
import java.time.Duration;
19+
20+
import org.junit.runner.RunWith;
21+
22+
import org.springframework.boot.test.context.SpringBootTest;
23+
import org.springframework.session.Session;
24+
import org.springframework.test.context.junit4.SpringRunner;
25+
26+
/**
27+
* Integration Tests for {@link Session} {@literal expiration timeout} in {@literal hours}.
28+
*
29+
* @author John Blum
30+
* @see java.time.Duration
31+
* @see org.springframework.boot.test.context.SpringBootTest
32+
* @see org.springframework.geode.boot.autoconfigure.session.AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests
33+
* @see org.springframework.session.Session
34+
* @see org.springframework.test.context.junit4.SpringRunner
35+
* @since 2.0.0
36+
*/
37+
@RunWith(SpringRunner.class)
38+
@SpringBootTest(
39+
classes = AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests.TestConfiguration.class,
40+
properties = "spring.session.timeout=2h",
41+
webEnvironment = SpringBootTest.WebEnvironment.MOCK
42+
)
43+
public class SessionExpirationTimeoutInHoursIntegrationTests
44+
extends AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests{
45+
46+
@Override
47+
protected int getExpectedMaxInactiveIntervalInSeconds() {
48+
return Long.valueOf(Duration.ofHours(2).toSeconds()).intValue();
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2017-present 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+
* https://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
13+
* or implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
package org.springframework.geode.boot.autoconfigure.session;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import java.time.Duration;
21+
22+
import org.junit.runner.RunWith;
23+
24+
import org.springframework.boot.test.context.SpringBootTest;
25+
import org.springframework.session.Session;
26+
import org.springframework.test.context.junit4.SpringRunner;
27+
28+
/**
29+
* Integration Tests for {@link Session} {@literal expiration timeout} in {@literal milliseconds}.
30+
*
31+
* @author John Blum
32+
* @see java.time.Duration
33+
* @see org.springframework.boot.test.context.SpringBootTest
34+
* @see org.springframework.geode.boot.autoconfigure.session.AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests
35+
* @see org.springframework.session.Session
36+
* @see org.springframework.test.context.junit4.SpringRunner
37+
* @since 2.0.0
38+
*/
39+
@RunWith(SpringRunner.class)
40+
@SpringBootTest(
41+
classes = AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests.TestConfiguration.class,
42+
properties = "spring.session.timeout=250ms",
43+
webEnvironment = SpringBootTest.WebEnvironment.MOCK
44+
)
45+
public class SessionExpirationTimeoutInMillisecondsIntegrationTests
46+
extends AbstractSessionExpirationTimeoutInTimeUnitIntegrationTests {
47+
48+
@Override
49+
protected int getExpectedMaxInactiveIntervalInSeconds() {
50+
int maxInactiveIntervalInSeconds = Long.valueOf(Duration.ofMillis(250).toSeconds()).intValue();
51+
assertThat(maxInactiveIntervalInSeconds).isZero();
52+
return maxInactiveIntervalInSeconds;
53+
}
54+
}

0 commit comments

Comments
 (0)