Доступ к bean-объекту в области запросов в другом потоке (который обрабатывает трафик websocket) - PullRequest
0 голосов
/ 23 ноября 2018

У меня проблемы с доступом к bean-компоненту, который определен с областью, ориентированной на запрос, в потоке, который не является потоком запроса.

Мой сценарий выглядит следующим образом:

  1. Выполнение начинается с запроса REST, поступающего от клиента.В этом запросе я определяю компонент, который позволяет мне получать доступ к данным в БД.Расположение БД зависит от пользователя, выполняющего сам запрос, следовательно, почему bean-компонент, к которому осуществляется доступ к БД, связан с самим запросом.Я получаю данные пользователя из авторизации запроса и использую их для инициализации компонента.

  2. Во время HTTP-запроса код может вызывать внешнюю службу через соединение через веб-сокет.Трафик ws обрабатывается различными StompFrameHandler классами.Когда они обрабатывают трафик, они делают это в выделенном потоке, который не совпадает с первоначальным запросом http (и это справедливо!).

  3. Некоторым из этих StompFrameHandler классов необходим доступ к БДактуально для пользователя в контексте текущего (REST) ​​запроса.

В точке 3 я сталкиваюсь с проблемой:

Нет запроса с привязкой к потоку: Вы ссылаетесь на атрибуты запроса вне фактического веб-запроса или обрабатываетезапросить за пределами изначально полученного потока?Если вы действительно работаете в веб-запросе и по-прежнему получаете это сообщение, ваш код, вероятно, выполняется за пределами DispatcherServlet / DispatcherPortlet: в этом случае используйте RequestContextListener или RequestContextFilter для предоставления текущего запроса.

Iпонять, что говорит мне ошибка, и тот факт, что из-за того, как я определил свой bean-компонент (ограниченный областью действия запроса), Spring не позволяет мне обращаться к нему в других потоках.Однако мне все еще нужно использовать этот компонент доступа к базе данных из потока обработки трафика ws.

Вот упрощенная версия моего кода:

Конфигурация компонента:

@Configuration
public class DbClientRequestScopeConfiguration {

    private DbClientFactoryI dbClientFactory;           
    private AuthenticationFacadeI authenticatedUserInfo;

    @Autowired
    public DbClientRequestScopeConfiguration(DbClientFactoryI dbClientFactory, AuthenticationFacadeI authenticatedUserInfo) {
        this.dbClientFactory = dbClientFactory;
        this.authenticatedUserInfo = authenticatedUserInfo;
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
    public DbClientI getDbClient() {        

        Authentication auth = authenticatedUserInfo.getAuthentication();        

        return dbClientFactory.getDbClient(auth.getDetails());              
    }
}

Служба DataService с использованием компонента (выполняется в потоке запроса)

@Service
public class DataService {

    private DbClientI dbClient;     

    @Autowired
    public DataService(DbClientI dbClient) {

        this.dbClient = dbClient;       
    }

    ...
}

Обработчик фрейма, работающий с трафиком WS Обратите внимание, что это не инициализируется в контексте Spring, вместо этого он инициализируется вручную классомвыполняется в потоке запроса, который дает ему экземпляр @DataService из контекста.

public class SaveDataFrameHandler implements StompFrameHandler{

    private DataService dataService;

    public SaveDataFrameHandler(DataService dataService) {      
        this.dataService = dataService;
    }

    @Override
    public Type getPayloadType(StompHeaders headers) {
        return JsonNode.class;
    }

    @Override
    public void handleFrame(StompHeaders headers, Object payload) {
        // This method will be called on a separate thread
        JsonNode jsonPayload = (JsonNode) payload;
        dataService.saveRecord(jsonPayload);            
    }
}

Я ищу предложения о том, как на самом деле использовать этот bean-компонент в моем потоке ws или как изменить архитектуру решения, чтобы я не столкнулся с этой проблемой.

Спасибо зазаранее!

ОБНОВЛЕНИЕ:

Пока мне удалось обойти проблему, хотя я не на 100% доволен решением.Чтобы избежать повторения, я опубликовал свое текущее решение в новом вопросе, поскольку я сталкиваюсь с другой проблемой, которая все еще связана с этим кодом: Прокси-компонент-прототип создается каждый раз, когда из него вызывается метод

...