Я пытаюсь перенести spring-session в существующее веб-приложение, которое использует bean-объекты сессионной области. Это приложение работает на Wildfly 10.1.0.Final
Когда я запускаю приложение, использующее внутреннее управление сессиями wildfly, все работает нормально. Попытка добавить пользовательскую реализацию Spring-Session приводит к потере информации о сессионном компоненте. Когда я отлаживаю приложение, происходит вызов scopedTarget.userSessionData
, однако он относится к базовому классу UserSessionData
, а не к UserSessionData$$EnhancedBySpringCGLIB$$1234
, который содержит фактические данные.
Конфигурация-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userSessionData" scope="session" class="UserSessionData">
<aop:scoped-proxy/>
</bean>
<context:annotation-config />
<bean class="my.MyHttpSessionConfiguration" />
</beans>
Эта конфигурация правильно создает и регистрирует springSessionRepositoryFilter
, используя MyHttpSessionConfiguration
. Однако проблема заключается в том, что когда объект MySession имеет bean-объект области действия UserSessionData
, я получаю необработанный экземпляр прокси-класса, а не декорированный экземпляр, который имеет значения сеанса. Я смог убедиться в этом, отладив приведенный ниже SesssionImpl в методе #setAttribute
class UserSessionData {
private String _myValue;
public void setMyValue(String value) {
_myValue = value;
}
public String getMyValue() {
return _myValue;
}
}
final class MySession implements ExpiringSession {
private final MapSession _delegate;
private final Map<String, Object> _delta = new HashMap<>();
private boolean _isNew;
MySession() {
this(new MapSession());
_isNew = true;
flushImmediateIfNecessary();
}
MySession(MapSession session) {
if (session == null) {
throw new IllegalArgumentException("MapSession cannot be null");
}
_isNew = false;
_delegate = session;
}
public boolean isNew() {
return _isNew;
}
@Override
public String getId() {
return _delegate.getId();
}
@Override
public long getCreationTime() {
return _delegate.getCreationTime();
}
@Override
public long getLastAccessedTime() {
return _delegate.getLastAccessedTime();
}
@Override
public void setLastAccessedTime(long lastAccessedTime) {
_delegate.setLastAccessedTime(lastAccessedTime);
flushImmediateIfNecessary();
}
@Override
public void setMaxInactiveIntervalInSeconds(int interval) {
_delegate.setMaxInactiveIntervalInSeconds(interval);
flushImmediateIfNecessary();
}
@Override
public int getMaxInactiveIntervalInSeconds() {
return _delegate.getMaxInactiveIntervalInSeconds();
}
@Override
public boolean isExpired() {
return _delegate.isExpired();
}
@SuppressWarnings("unchecked")
@Override
public <T> T getAttribute(String attributeName) {
return (T) _delegate.getAttribute(attributeName);
}
@Override
public Set<String> getAttributeNames() {
return _delegate.getAttributeNames();
}
@Override
public void setAttribute(String attributeName, Object attributeValue) {
_delegate.setAttribute(attributeName, attributeValue);
putAndFlush(attributeName, attributeValue);
}
@Override
public void removeAttribute(String attributeName) {
_delegate.removeAttribute(attributeName);
putAndFlush(attributeName, null);
}
Map<String, Object> getDelta() {
return _delta;
}
private void putAndFlush(String attr, Object value) {
_delta.put(attr, value);
flushImmediateIfNecessary();
}
private void flushImmediateIfNecessary() {
if (MySessionRepository.this._flushMode == MyFlushMode.IMMEDIATE) {
MySessionRepository.this.save(this);
}
}
}
Я чувствую, что мне не хватает ни конфигурации, ни чего-то другого, потому что нативный WildFly SessionImpl имеет правильный расширенный объект для сериализации, когда я удаляю springSessionRepositoryFilter и позволяю контейнеру обрабатывать объект сеанса. Кроме того, у контроллеров Spring есть правильный расширенный объект. Это просто MySession
, который, кажется, не получает это. Есть мысли?
EDIT:
Похоже, основная проблема заключается в том, что мой spring-security использует другую версию прокси-класса при настройке членов, поэтому я не получаю их в объекте MySession
. Прилагаются конфигурации для Spring-Security
public class WebSessionInitializer extends AbstractHttpSessionInitializer {
}
@Configuration
@EnableSpringHttpSession
public class MySessionConfiguration {
@Bean
public SessionRepository sessionRepository() {
return new MySessionRepository();
}
}
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="imb"
version="2.5">
<distributable />
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/configuration-spring.xml
</param-value>
</context-param>
Фильтр SpringSession правильно добавлен в мою реализацию. Похоже, корень проблемы в том, что когда я вхожу в Spring-Security, он устанавливает значения для другого экземпляра UserSessionData
, чем тот, что в объекте MySession
. Когда я использую @Autowired
в контроллерах MVC, я получаю правильный.
Версии библиотеки:
- Весна: 3.2.14
- Весенняя сессия: 1.3.2
- WildFly 10.1.0. Финал