Как написать main() с помощью CDI в Java EE?

У меня есть неклиентское приложение, которое я хочу запустить. У него не будет клиентов, но он будет совершать HTTP-вызовы и действовать как клиент для других служб. Он будет работать, возможно, несколько часов или дней (но это не потребует периодических запусков — только один раз).

Я хочу запустить его в контейнере Java EE 7 из-за преимуществ стандартного внедрения зависимостей контекста (CD) и стандартного клиента JAX-RS (нового со времен Java EE 7). Также приятно иметь такие сервисы, как JMS, JPA.

Вопрос в том, как мне написать/аннотировать основной метод стандартным образом? @Inject в методе не годится, потому что такие методы должны возвращаться быстро. @Schedule не идеален, потому что он запускается периодически, если я программно не определяю текущее системное время.

Лучшее, что я мог придумать, это установить одноразовый Timer в методе @Inject и аннотировать мой основной метод с помощью @Timeout.

Почему-то это кажется немного хрупким или неэлегантным. Есть ли лучший стандартный способ запуска службы? Какая-то аннотация, которая просто заставит ее запуститься и начать работать?

Кроме того, как каков наилучший стандартный способ прерывания и закрытия службы при отмене развертывания?


person necromancer    schedule 10.05.2013    source источник
comment
Ваш вопрос немного извилистый. Если вы запускаете приложение в контейнере приложения, то почему вы определяете основной метод? Просто создайте стартовый singleton EJB с методом @Schedule. .   -  person Perception    schedule 11.05.2013
comment
@ Восприятие извилистости является отражением моей неясности, отсюда и вопрос. @Schedule требует времени. В какое время я должен аннотировать метод? Я не хочу, чтобы он запускался периодически. Метод нужно запустить ровно один раз. Если @Schedule принимает интервал после развертывания, это было бы идеально, но это не так. Могу ли я использовать @Schedule ... myfunc (Timer timer) и отменить входящий таймер и использовать TimerService установить интервальный таймер для запуска @Timeout ... mymain () задействованных звуков.   -  person necromancer    schedule 11.05.2013
comment
Не знаю, отредактировали ли вы свой вопрос или я пропустил нижнюю часть. Клянусь, это читается по-другому. Так или иначе, одна идея - использовать стартап, singleton bean и создать таймер в его методе @PostConstruct. Или встройте стороннюю библиотеку, такую ​​как Quartz, и запланируйте неповторяющееся задание, чтобы оно запускалось при развертывании вашего приложения. Каковы требования к расписанию для задания (при развертывании приложения, в определенный день, запуск по запросу?).   -  person Perception    schedule 11.05.2013
comment
@ Восприятие, возможно, это было ваше восприятие ;-) Я не редактировал, и если бы я это сделал, правки были бы доступны. Я ДЕЙСТВИТЕЛЬНО отредактировал свое имя пользователя после вашего последнего комментария. Требование расписания относится к развертыванию приложения. Спасибо за предложения. Я предпочитаю не использовать стороннюю библиотеку, но попробую таймер @PostConstruct.   -  person necromancer    schedule 11.05.2013
comment
@ Восприятие (продолжение) относительно выключения, нормально ли, чтобы @PreDestroy установил флаг и ждал блокировки, удерживаемой основным методом, который освобождается, когда основной замечает флаг и завершает работу? По сути, я хочу остановиться на undeploy и начать развертывание без каких-либо других ручных или нестандартных методов.   -  person necromancer    schedule 11.05.2013
comment
На мое восприятие может повлиять весь сироп от кашля, который я пью. Если ваша работа будет выполняться долго, вам может быть лучше вызвать метод @Asynchronous из @PostConstruct вашего SLSB. Вам нужно будет спроектировать свою задачу так, чтобы ее можно было прервать, и вызвать указанное прерывание из обратного вызова @PreDestroy.   -  person Perception    schedule 11.05.2013
comment
отличное предложение на @Asynchronous! но я не знаю, как вызвать его асинхронно из @PostConstruct - без прокси работает синхронный вызов. мой основной метод и постконструкция находятся в одном классе @Singleton. нужен самопрокси в postconstruct.   -  person necromancer    schedule 11.05.2013
comment
@Perception надеюсь, ты чувствуешь себя лучше. @Asynchronous помогло, но у меня другая проблема. Я могу обойти это, но я хотел бы сообщить об этом Glassfish как об ошибке, если это действительно так: stackoverflow.com/questions/16493381/   -  person necromancer    schedule 11.05.2013
comment
@Perception - это не ошибка, кстати. Кроме того, с @Asynchronous см. Мой комментарий к ответу @JanGalinsky ниже. Спасибо!   -  person necromancer    schedule 12.05.2013


Ответы (2)


Если вы можете использовать EJB с (или вместо) CDI, попробуйте аннотации @Singleton + @Startup для вашего компонента и @PostConstruct для вашего метода main().

@Singleton
@Startup
public class YourBean {

@Stateless
public static class BeanWithMainMethod{

    @Asynchronous
    public void theMainMethod(){
        System.out.println("Async invocation");
     }
}

    @EJB
    private BeanWithMainMethod beanWithMainMethod;

    @PostConstruct
    private void launchMainMethod(){
        beanWithMainMethod.theMainMethod();
    }
}
person gluckonavt    schedule 11.05.2013
comment
Я думал, что контейнер убьет его, если @PostConstruct не вернется достаточно скоро. Вы пробовали это с помощью длительного метода? - person necromancer; 12.05.2013
comment
Развертывание завершится ошибкой, если метод MainMethod не вернется в течение длительного времени, поэтому лучше использовать события @Asyncronous или CDI. - person gluckonavt; 12.05.2013
comment
спасибо за разъяснения, проголосовали за исправление (было бы неплохо, если бы вы тоже могли отредактировать свой ответ!) - person necromancer; 12.05.2013
comment
код в порядке, но текст над кодом не соответствует коду. он должен сказать: аннотируйте свой основной метод с помощью @Asynchronous и вызовите его из метода @PostConstruct после самостоятельной инъекции компонента с помощью @EJB - person necromancer; 14.05.2013

Когда PostConstruct работает долго, отделяйте его от событий:

@Singleton
@Startup
public class YourBean{
@Inject
private Event<XXX> started; 
@PostConstruct
private void theMainMethod(){
    started.fire(new XXX());
}
public void handleStarted(@Observes XXX started) {
    // the real main method.
}

}

person Jan Galinski    schedule 11.05.2013
comment
Спасибо, @JanGalinski, кстати, другим вариантом было использование @Asynchronous public void handleStarted (), но я не мог заставить его вызываться асинхронно из метода @PostConstruct. Как вы думаете, что лучше - @Asynchronous или @Observes? Любая идея, что мне нужно сделать, чтобы сделать асинхронный вызов метода в том же bean-компоненте изнутри @PostConstruct в том же bean-компоненте? Спасибо за отличное предложение. - person necromancer; 12.05.2013
comment
Ну, нет стандартного способа запросить отмену метода @Observes. С помощью @Asynchronous можно запросить отмену метода через возвращаемый Future. Хотя это можно смоделировать нестандартным способом, в будущей версии Java EE программист, вероятно, сможет запросить, чтобы стандартный запрос на отмену фактически прервал поток, пока он находится в блокирующем вызове, что значительно улучшит его реакцию. и очистить структуру тоже. Эта ожидаемая функциональность не может быть реализована программистом самостоятельно. Таким образом, @Asynchronous выигрывает ИМО. - person necromancer; 12.05.2013