Java / Spring MVC: предоставить контекст запроса дочерним потокам - PullRequest
0 голосов
/ 25 сентября 2018

У меня проблема в том, что я хочу перенести некоторые процессы моего приложения Spring WebMVC в отдельные потоки.Это было достаточно просто и работает, пока я не хочу использовать класс userRightService, который использует глобальный запрос.Это не доступно в темах, и мы получаем проблему, это в значительной степени понятно.

Это моя ошибка:

java.lang.RuntimeException:
org.springframework.beans.factory.BeanCreationException: Error creating bean
with name 'scopedTarget.userRightsService': Scope 'request' is not active
for the current thread; consider defining a scoped proxy for this bean if
you intend to refer to it from a singleton; nested exception is 
java.lang.IllegalStateException: Cannot ask for request attribute - 
request is not active anymore!

Хорошо, достаточно ясно.Я пытаюсь сохранить контекст запроса, реализуя это решение:

Как включить область запроса в асинхронном исполнителе задач

Это мой исполняемый класс:

@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class myThread implements Runnable {

  private RequestAttributes context;

  public DataExportThread(RequestAttributes context) {
    this.context = context;
  }

  public void run() {
    RequestContextHolder.setRequestAttributes(context);

И вот где он появляется:

final DataExportThread dataExportThread = 
   new myThread(RequestContextHolder.currentRequestAttributes());

final Thread thread = new Thread(myThread);
thread.setUncaughtExceptionHandler((t, e) -> {...});
thread.start();

Насколько я понял, мы храним атрибуты currentRequestAttributes в потоке, а затем, при запуске, восстанавливаем их currentRequestAttributes ...меня, но ошибка все еще там.Я думаю, что сделал ошибку, адаптировав решение для моего случаяМожет быть, кто-то может помочь мне найти ошибку.

До того, как я прошел через много потоков-потоков-потоков с различными решениями (см. ниже), я мог бы попробовать что-то еще, но этот вариант казался наиболее простым и понятным.я, поэтому я надеюсь, что кто-то может помочь мне найти ошибку в реализации или объяснить, почему это неправильный подход.

Я уже пробовал этот безуспех:

Если это важно:

<org.springframework-version>4.3.4.RELEASE</org.springframework-version>

Кстати:Я знаю, что было бы лучше реструктурировать приложение таким образом, чтобы запрос не требовался в потоке, но это очень сложно в этом случае, и я очень надеюсь, что смогу избежать этого.

-

Edit1:

ThBean, который не может быть создан в потоке, начинается следующим образом:

@Service("userRightsService")
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserRightsService {

-

Edit2:

Я также пробовал это:

Но контекст всегда пуст ...

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Для тех, кто ищет.С помощью подсказок Master_Ex я нашел решение:

В runnable:

private HttpServletRequest request;

public void run() {

    final RequestContextListener rcl = new RequestContextListener();
    final ServletContext sc = request.getServletContext();
    rcl.requestInitialized(new ServletRequestEvent(sc, request));

А в UserRightService я вызываю функцию, которая выполняет следующие действия:

    SecurityContext context = SecurityContextHolder.getContext();
    Authentication auth = context.getAuthentication();

    context.setAuthentication(getDataExportAuthentication(exportingUser));

@ Master_Ex's Спасибо, ваш пост был очень полезным.Извините, что я слишком поздно, чтобы дать вам награду, иначе я бы пометил ее как правильную.

0 голосов
/ 29 сентября 2018

Я не смог воспроизвести проблему, так как я не уверен, как вы создаете / вводите UserRightsService, но у меня есть пара предложений, которые вы можете попробовать.

Я полагаю, что проблема в том, чтоRequestAttributes становится недействительным, поскольку запрос завершен (поэтому исключение говорит Cannot ask for request attribute - request is not active anymore), что происходит во время выполнения вашей задачи.

Вместо этого вы можете попробовать ввести UserRightsService там, где находится ваш потокпорождать и передавать этот экземпляр в качестве аргумента в поток.Таким образом, UserRightsService должен быть создан без проблем, так как запрос все еще должен быть доступен.

Даже в этом случае попытка доступа к RequestAttributes после завершения запроса, вероятно, завершится неудачей.В этом случае я предлагаю сделать копию всех необходимых вам значений до того, как запрос будет завершен, то есть до того, как вы запустите поток.

Если это не сработает, пожалуйста, предоставьте дополнительную информацию о том, каквы инициализируете UserRightsService внутри задачи.

Удачи!

PS: Я думаю, что аннотация области в вашем классе потока бесполезна, поскольку объект задачи создается вручную и не управляетсявесна.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...