Skip to content

Commit 74595ea

Browse files
committed
Add support for configuring JDBC session cleanup cron
1 parent f8583bb commit 74595ea

File tree

6 files changed

+202
-238
lines changed

6 files changed

+202
-238
lines changed

spring-session-jdbc/src/main/java/org/springframework/session/jdbc/JdbcOperationsSessionRepository.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import org.springframework.jdbc.core.ResultSetExtractor;
4949
import org.springframework.jdbc.support.lob.DefaultLobHandler;
5050
import org.springframework.jdbc.support.lob.LobHandler;
51-
import org.springframework.scheduling.annotation.Scheduled;
5251
import org.springframework.session.FindByIndexNameSessionRepository;
5352
import org.springframework.session.MapSession;
5453
import org.springframework.session.Session;
@@ -535,7 +534,6 @@ public Map<String, JdbcSession> findByIndexNameAndIndexValue(String indexName,
535534
return sessionMap;
536535
}
537536

538-
@Scheduled(cron = "${spring.session.cleanup.cron.expression:0 * * * * *}")
539537
public void cleanUpExpiredSessions() {
540538
Integer deletedCount = this.transactionOperations.execute(transactionStatus ->
541539
JdbcOperationsSessionRepository.this.jdbcOperations.update(

spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/EnableJdbcHttpSession.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2016 the original author or authors.
2+
* Copyright 2014-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -58,8 +58,8 @@
5858
* More advanced configurations can extend {@link JdbcHttpSessionConfiguration} instead.
5959
*
6060
* For additional information on how to configure data access related concerns, please
61-
* refer to the
62-
* <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html">
61+
* refer to the <a href=
62+
* "http://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html">
6363
* Spring Framework Reference Documentation</a>.
6464
*
6565
* @author Vedran Pavic
@@ -80,11 +80,16 @@
8080
String tableName() default JdbcOperationsSessionRepository.DEFAULT_TABLE_NAME;
8181

8282
/**
83-
* The session timeout in seconds. By default, it is set to 1800 seconds (30 minutes).
84-
* This should be a non-negative integer.
85-
*
83+
* The session timeout in seconds. By default, it is set to 1800 seconds (30
84+
* minutes). This should be a non-negative integer.
8685
* @return the seconds a session can be inactive before expiring
8786
*/
8887
int maxInactiveIntervalInSeconds() default MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
8988

89+
/**
90+
* The cron expression for expired session cleanup job. By default runs every minute.
91+
* @return the session cleanup cron expression
92+
*/
93+
String cleanupCron() default JdbcHttpSessionConfiguration.DEFAULT_CLEANUP_CRON;
94+
9095
}

spring-session-jdbc/src/main/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfiguration.java

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import org.springframework.context.annotation.Bean;
2929
import org.springframework.context.annotation.Configuration;
3030
import org.springframework.context.annotation.ImportAware;
31-
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
3231
import org.springframework.core.annotation.AnnotationAttributes;
3332
import org.springframework.core.convert.ConversionService;
3433
import org.springframework.core.convert.support.GenericConversionService;
@@ -37,6 +36,9 @@
3736
import org.springframework.core.type.AnnotationMetadata;
3837
import org.springframework.jdbc.support.lob.LobHandler;
3938
import org.springframework.scheduling.annotation.EnableScheduling;
39+
import org.springframework.scheduling.annotation.SchedulingConfigurer;
40+
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
41+
import org.springframework.session.MapSession;
4042
import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration;
4143
import org.springframework.session.jdbc.JdbcOperationsSessionRepository;
4244
import org.springframework.transaction.PlatformTransactionManager;
@@ -59,38 +61,37 @@
5961
@Configuration
6062
@EnableScheduling
6163
public class JdbcHttpSessionConfiguration extends SpringHttpSessionConfiguration
62-
implements BeanClassLoaderAware, ImportAware, EmbeddedValueResolverAware {
64+
implements BeanClassLoaderAware, EmbeddedValueResolverAware, ImportAware,
65+
SchedulingConfigurer {
6366

64-
private String tableName;
67+
static final String DEFAULT_CLEANUP_CRON = "0 * * * * *";
6568

66-
private Integer maxInactiveIntervalInSeconds;
69+
private String tableName = JdbcOperationsSessionRepository.DEFAULT_TABLE_NAME;
6770

68-
private LobHandler lobHandler;
71+
private Integer maxInactiveIntervalInSeconds = MapSession.DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS;
6972

70-
@Autowired(required = false)
71-
@Qualifier("conversionService")
72-
private ConversionService conversionService;
73+
private String cleanupCron = DEFAULT_CLEANUP_CRON;
74+
75+
private DataSource dataSource;
76+
77+
private PlatformTransactionManager transactionManager;
78+
79+
private LobHandler lobHandler;
7380

7481
private ConversionService springSessionConversionService;
7582

83+
private ConversionService conversionService;
84+
7685
private ClassLoader classLoader;
7786

7887
private StringValueResolver embeddedValueResolver;
7988

8089
@Bean
81-
public JdbcOperationsSessionRepository sessionRepository(
82-
@SpringSessionDataSource ObjectProvider<DataSource> springSessionDataSource,
83-
ObjectProvider<DataSource> dataSource,
84-
PlatformTransactionManager transactionManager) {
85-
DataSource dataSourceToUse = springSessionDataSource.getIfAvailable();
86-
if (dataSourceToUse == null) {
87-
dataSourceToUse = dataSource.getObject();
88-
}
90+
public JdbcOperationsSessionRepository sessionRepository() {
8991
JdbcOperationsSessionRepository sessionRepository = new JdbcOperationsSessionRepository(
90-
dataSourceToUse, transactionManager);
91-
String tableName = getTableName();
92-
if (StringUtils.hasText(tableName)) {
93-
sessionRepository.setTableName(tableName);
92+
this.dataSource, this.transactionManager);
93+
if (StringUtils.hasText(this.tableName)) {
94+
sessionRepository.setTableName(this.tableName);
9495
}
9596
sessionRepository
9697
.setDefaultMaxInactiveInterval(this.maxInactiveIntervalInSeconds);
@@ -104,35 +105,38 @@ else if (this.conversionService != null) {
104105
sessionRepository.setConversionService(this.conversionService);
105106
}
106107
else {
107-
GenericConversionService conversionService = createConversionServiceWithBeanClassLoader();
108-
sessionRepository.setConversionService(conversionService);
108+
sessionRepository
109+
.setConversionService(createConversionServiceWithBeanClassLoader());
109110
}
110111
return sessionRepository;
111112
}
112113

113-
/**
114-
* This must be a separate method because some ClassLoaders load the entire method
115-
* definition even if an if statement guards against it loading. This means that older
116-
* versions of Spring would cause a NoSuchMethodError if this were defined in
117-
* {@link #sessionRepository(ObjectProvider, ObjectProvider, PlatformTransactionManager)}.
118-
*
119-
* @return the default {@link ConversionService}
120-
*/
121-
private GenericConversionService createConversionServiceWithBeanClassLoader() {
122-
GenericConversionService conversionService = new GenericConversionService();
123-
conversionService.addConverter(Object.class, byte[].class,
124-
new SerializingConverter());
125-
conversionService.addConverter(byte[].class, Object.class,
126-
new DeserializingConverter(this.classLoader));
127-
return conversionService;
114+
public void setTableName(String tableName) {
115+
this.tableName = tableName;
128116
}
129117

130-
/* (non-Javadoc)
131-
* @see org.springframework.beans.factory.BeanClassLoaderAware#setBeanClassLoader(java.lang.ClassLoader)
132-
*/
133-
@Override
134-
public void setBeanClassLoader(ClassLoader classLoader) {
135-
this.classLoader = classLoader;
118+
public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
119+
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
120+
}
121+
122+
public void setCleanupCron(String cleanupCron) {
123+
this.cleanupCron = cleanupCron;
124+
}
125+
126+
@Autowired
127+
public void setDataSource(
128+
@SpringSessionDataSource ObjectProvider<DataSource> springSessionDataSource,
129+
ObjectProvider<DataSource> dataSource) {
130+
DataSource dataSourceToUse = springSessionDataSource.getIfAvailable();
131+
if (dataSourceToUse == null) {
132+
dataSourceToUse = dataSource.getObject();
133+
}
134+
this.dataSource = dataSourceToUse;
135+
}
136+
137+
@Autowired
138+
public void setTransactionManager(PlatformTransactionManager transactionManager) {
139+
this.transactionManager = transactionManager;
136140
}
137141

138142
@Autowired(required = false)
@@ -147,48 +151,53 @@ public void setSpringSessionConversionService(ConversionService conversionServic
147151
this.springSessionConversionService = conversionService;
148152
}
149153

150-
public void setTableName(String tableName) {
151-
this.tableName = tableName;
154+
@Autowired(required = false)
155+
@Qualifier("conversionService")
156+
public void setConversionService(ConversionService conversionService) {
157+
this.conversionService = conversionService;
152158
}
153159

154-
public void setMaxInactiveIntervalInSeconds(Integer maxInactiveIntervalInSeconds) {
155-
this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds;
160+
@Override
161+
public void setBeanClassLoader(ClassLoader classLoader) {
162+
this.classLoader = classLoader;
156163
}
157164

158-
private String getTableName() {
159-
String systemProperty = System.getProperty("spring.session.jdbc.tableName", "");
160-
if (StringUtils.hasText(systemProperty)) {
161-
return systemProperty;
162-
}
163-
return this.tableName;
165+
@Override
166+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
167+
this.embeddedValueResolver = resolver;
164168
}
165169

166170
@Override
167171
public void setImportMetadata(AnnotationMetadata importMetadata) {
168-
Map<String, Object> enableAttrMap = importMetadata
172+
Map<String, Object> attributeMap = importMetadata
169173
.getAnnotationAttributes(EnableJdbcHttpSession.class.getName());
170-
AnnotationAttributes enableAttrs = AnnotationAttributes.fromMap(enableAttrMap);
171-
String tableNameValue = enableAttrs.getString("tableName");
174+
AnnotationAttributes attributes = AnnotationAttributes.fromMap(attributeMap);
175+
String tableNameValue = attributes.getString("tableName");
172176
if (StringUtils.hasText(tableNameValue)) {
173177
this.tableName = this.embeddedValueResolver
174178
.resolveStringValue(tableNameValue);
175179
}
176-
this.maxInactiveIntervalInSeconds = enableAttrs
180+
this.maxInactiveIntervalInSeconds = attributes
177181
.getNumber("maxInactiveIntervalInSeconds");
182+
String cleanupCron = attributes.getString("cleanupCron");
183+
if (StringUtils.hasText(cleanupCron)) {
184+
this.cleanupCron = this.embeddedValueResolver.resolveStringValue(cleanupCron);
185+
}
178186
}
179187

180188
@Override
181-
public void setEmbeddedValueResolver(StringValueResolver resolver) {
182-
this.embeddedValueResolver = resolver;
189+
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
190+
taskRegistrar.addCronTask(() -> sessionRepository().cleanUpExpiredSessions(),
191+
this.cleanupCron);
183192
}
184193

185-
/**
186-
* Property placeholder to process the @Scheduled annotation.
187-
* @return the {@link PropertySourcesPlaceholderConfigurer} to use
188-
*/
189-
@Bean
190-
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
191-
return new PropertySourcesPlaceholderConfigurer();
194+
private GenericConversionService createConversionServiceWithBeanClassLoader() {
195+
GenericConversionService conversionService = new GenericConversionService();
196+
conversionService.addConverter(Object.class, byte[].class,
197+
new SerializingConverter());
198+
conversionService.addConverter(byte[].class, Object.class,
199+
new DeserializingConverter(this.classLoader));
200+
return conversionService;
192201
}
193202

194203
}

spring-session-jdbc/src/test/java/org/springframework/session/jdbc/config/annotation/web/http/JdbcHttpSessionConfigurationCustomCronTests.java

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)