SessionScoped не работает GAE+Jersey+Guice

У меня есть проект Java, в котором я использую Jersey (1.17) и Guice (3.0). Компоненты SessionScoped работают в локальной среде разработки, но не работают при развертывании в GAE. Проблема в том, что они не сохраняют состояние сеанса.

Сеансы включены в web.xml: <sessions-enabled>true</sessions-enabled>

Мой сеансовый компонент (SessionService):

@SessionScoped
public class SessionService implements Serializable {
    @Inject transient Logger log;
    private Locale locale = Locale.US;
    public synchronized Locale getLocale() { return locale; }
    public synchronized void setLocale(Locale locale) { this.locale = locale; }
}

и он привязан к области сеанса в ServletModule bind(SessionService.class).in(ServletScopes.SESSION);

Контроллер, где я его использую:

@Path("/settings")  
public class SettingsController {
    @Inject SessionService sessionService;

    @GET
    @Path("/setLocale")
    public Object setLocale(@QueryParam("languageTag") String languageTag) {
        sessionService.setLocale(Locale.forLanguageTag(languageTag));
        return "OK";
    }

     @GET
    @Path("/getLocale")
    public Object getLocale() { return sessionService.getLocale().getLanguage(); }
}

С локальным сервером разработки все работает нормально. При развертывании в GAE (1.9.5) он устанавливает локаль в первый раз, а затем остается неизменной навсегда, хотя я снова и снова вызываю setLocale. Почему это не работает?

Как ни странно, я нашел малоизвестный способ заставить его работать, но я не знаю, почему он заставляет его работать. Чтобы он работал, необходимо коснуться HttpSession перед установкой локали. Как request.getSession(true).setAttribute("whatever", "bar"). Как будто серверу нужно было напомнить, что SessionService хочет что-то сделать с Session. Почему это?


person michal sankot    schedule 12.06.2014    source источник
comment
Я испытываю точно такую ​​​​же проблему. Я использую GAE 1.9.10, Guice 3.0, но не Джерси. Разобрались с этим?   -  person roemer    schedule 06.09.2014
comment
поскольку у меня есть этот обходной путь, я больше не экспериментировал. Я был бы рад узнать, как это сделать правильно.   -  person michal sankot    schedule 10.09.2014


Ответы (1)


Я нашел способ получить желаемую функциональность, подобную SessionScoped. Не используйте @SessionScoped, так как он явно не работает в GAE, а вместо этого используйте Provider<HttpSession>.

Итак, ваш код будет похож на

public class SessionService {
    @Inject Provider<HttpSession> httpSessionProvider;

    public void saveSecurityInfo(Object securityInfo) {
        httpSessionProvider.get().setAttribute('sec_info', securityInfo);
    }

    public Object loadSecurityInfo() {
        return httpSessionProvider.get().getAttribute('sec_info');
    }
}

В контроллере вы бы вставили его как @Inject SessionService sessionService;

Я протестировал этот подход на GAE, и он работает (сохраняет информацию в сеансе браузера).

person michal sankot    schedule 24.03.2016