LINUX.ORG.RU

Обработка событий в многопоточном приложении

 eventbus, guava, , ,


0

2

Итак, в приложении используется Vaadin 7. Во время логина идентификатор пользователя сохраняется в куки, откуда потом извлекается путем VaadinService.getCurrentRequest(). Если покопаться в исходниках ваадина (или применить логику, на выбор), становится ясно, что Request этот ThreadLocal.

А теперь ближе к сути: в EventBus постится ивент, после чего хендлер должен его обработать в каждом из потоков приложения. Как я понял из спек, в Guava EventBus для этого используется AsyncEventBus, а хендлер помимо @Subscribe аннотируется еще и @AllowConcurrentEvents. Итак, постится ивент, хендлер для каждого потока его обрабатывает и вроде бы все замечательно, но нет. Хендлер запускается в потоке, который не имеет доступа к Request'у и соответственно не может получить куки, которые ему нужны. Вся логика рушится, я агрессивно лысею в интимных местах и наступает полное уныние. Пока свой EventBus велосипедить не берусь, прошу совета.

★★★★★

Блин ну возьми оберни обработчик события так чтобы он захватывал из контекста создания нужные ему вещи и пихал в «VaadinService.getCurrentRequest()» при получении сообщения, если ваадин оказался нерасширяемым говном то придется еще колхозить обертку над «VaadinService.getCurrentRequest()»

да, при этом тебе придется отказаться от аннотаций гуявы и писать и регистрировать обработчик вручную

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

так чтобы он захватывал из контекста создания нужные ему вещи

А можно пример того, как что-либо захватить из контекста создания?

да, при этом тебе придется отказаться от аннотаций гуявы и писать и регистрировать обработчик вручную

Да там и так приходится вручную регистрировать обработчики. Сейчас я это делаю в спринговом BeanPostProcessor (проверяю, есть ли в классе методы, аннотированные @Subscribe, и если есть, регистрирую класс в EventBus'е). Ес-но, EventBus и все хендлеры это бины в контексте спринга.

f1xmAn ★★★★★
() автор топика
Ответ на: комментарий от f1xmAn

А можно пример того, как что-либо захватить из контекста создания?

ЭЭ?

//было
eventBus.addListener(originalListener);
//стало
eventBus.addListener(new Listener(originalListener) {
  //захват текущего контекста
  final Request request = VaadinService.getCurrentRequest();
  public void listen() {
    //в другом потоке установка контекста
    VaadinService.setCurrentRequest(request);
    try {
      originalListener.listen();
    } finally {
    //в другом потоке обязательная очистка, контекста, обязательно в finally
      VaadinService.setCurrentRequest(null);
    }
  }
})
Deleted
()
Ответ на: комментарий от Deleted

Я думал там что-то хитрожопое в java.util.concurrent. Вообще я планировал несколько иначе с ивентами работать, там спринг так замечательно все регистрирует:

@Component
public class EventHandlerReceptionist implements BeanPostProcessor {

    public static final Logger log = LoggerFactory.getLogger(EventHandlerReceptionist.class);
    private AsyncEventBus eventBus;

    @Autowired
    public void setEventBus(AsyncEventBus eventBus) {
        this.eventBus = eventBus;
    }

    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        for (Method method : o.getClass().getMethods()) {
            if (method.isAnnotationPresent(Subscribe.class)) {
                eventBus.register(o);
                log.debug("[{}] handler registered", method.getParameterTypes()[0].getName());
            }
        }
        return o;
    }
}
но, видимо, придется от того варианта отойти.

В ваадине есть возможность повесить листнер на завершение создания сессии. А там на сессию можно повесить RequestHandler, в котором и будет создаваться и регистрироваться обработчик события. Но как-то это совсем не круто. :(

f1xmAn ★★★★★
() автор топика
Ответ на: комментарий от f1xmAn

там спринг так замечательно все регистрирует:

буэ же, но я не вижу чем это мешает - объект события также может хватать контекст

Deleted
()
Ответ на: комментарий от Deleted

Cмущает

method.getParameterTypes()[0].getName()
?

f1xmAn ★★★★★
() автор топика
Ответ на: комментарий от f1xmAn

ну потому что у тебя есть пачка инструментов, основная задача которых делать удобно разработчику (IoC) и на пересечении их у тебя получился фееричный костыль с явным использованием рефлекшена, регистрацией одного листенера несколько раз и кучей неявных соглашений.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.