Показаны сообщения с ярлыком EJB. Показать все сообщения
Показаны сообщения с ярлыком EJB. Показать все сообщения

пятница, 13 июля 2018 г.

Асинхронный вызов методов

При таком вызове метод выполняется в отдельном потоке не прерывая основной поток приложения. Иногда такой прием называют "паттерн асинхронность".
Spring
Класс конфигурации приложения надо отметить аннотацией @EnableAsync. Если это веб-приложение - то достаточно снабдить метод аннотацией @Async - и любой контейнер сервлетов (например Tomcat) запустит метод в отдельном потоке. Для десктоп-приложения надо будет добавить в класс конфигурации следующий бин:
@Configuration
@EnableAsync
public class AppContext {
   
    @Bean
    public TaskExecutor taskExecutor() {
        return new SimpleAsyncTaskExecutor();
    }
........................................
}

JavaEE
Такой же функционал обеспечивает контейнер EJB из "коробки" без всяких дополнительных настроек (начиная с JavaEE 6 - EJB 3.1 - Например TomEE v1.7.4 с профайлом jaxrs - http://tomee.apache.org/download-archive.html или http://openejb.apache.org/downloads.html ) - достаточно в бине EJB отметить метод аннотацией @Asynchronous - она применима для всех типов бинов EJB - @Stateless, @Stateful, @Singleton. Если отметить весь класс - то все его методы станут асинхронными.

пятница, 22 июня 2018 г.

Зависимые бины и аннотация @DependsOn

Бывают случаи когда ваш бин зависит от 1 или нескольких других бинов приложения Spring - здесь на помощь приходит аннотация @DependsOn, которая заставляет контейнер сначала создавать бины зависимостей - и только потом зависящий от них бин. В параметрах аннотации указываются имена бинов. Аннотацию можно использовать или в файле конфигурации приложения совместно с аннотацией @Bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
 
@Configuration
public class AppConfig {

   @Bean("beanOne")
   @DependsOn(value = { "beanTwo", "beanThree" })
   public BeanOne getBeanOne() {
      return new BeanOne();
   }

   @Bean("beanTwo")
   public BeanTwo getBeanTwo() {
      return new BeanTwo();
   }

   @Bean("beanThree")
   public BeanThree getBeanThree() {
      return new BeanThree();
   }
}
 или аннотировать класс бина:
@Component
@DependsOn(value = { "beanTwo", "beanThree" })
 public class BeanOne {
 
   @Autowired
   private BeanTwo beanTwo;

   @Autowired
   private BeanThree beanThree;

...............
}
Аналогичный механизм есть для синглтонов EJB стека JavaEE - только там в качестве параметров аннотации указывают имена классов и кроме того, учитывая что контейнер EJB по-умолчанию использует ленивое создание бинов (в отличие от Spring - он по-умолчанию создает бины сразу при старте приложения), то аналогичная аннотация используется как правило совместно с аннотацией @Startup, которая заставляет EJB создавать бины сразу при старте приложения - пример:
import javax.ejb.DependsOn;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
@DependsOn("EjbConfig")
public class EjbMain {

    .....................

}

четверг, 24 мая 2018 г.

События жизненного цикла бинов

Spring
В Spring их два - метод выполняемый сразу после создания бина + метод выполняемый перед уничтожением бина. Наиболее простой способ использования этих методов - это аннотировать их с помощью @PostConstruct и @PreDestroy соответственно - это аннотации из JSR-250, который вошел в Java SE начиная с версии 6 а также входит в Java EE CDI (Contexts and Dependency Injection) и который поддерживается Spring. Есть еще 2 способа сделать это (с помощью XML и интерфейсов) - но я специально не говорю об этом чтобы не "грузить" читателей, т к все эти способы эквивалентны.
@Component
public class MyBean {

    @PostConstruct
    public void afterBirn() {
       .....код выполняемый сразу после создания бина....
    }
    ................

    @PreDestroy
    public void beforeKill() {
       .....код выполняемый перед уничтожением бина....
    }

}
Методы должны быть только по 1 на событие + без аргументов + именно void. Методы уничтожения @PreDestroy работают для синглтонов - для бинов со scope=prototype Spring не запускает эти методы согласно проектному решению. Минус обратных вызовов уничтожения в Spring в том, что они не запускаются автоматически - нужно не забыть вызвать AbstractApplicationContext.destroy() перед закрытием приложения. Когда приложение выполняется как сервлет, указанный метод destroy() можно вызвать в методе destroy() сервлета. Для Desktop-приложений чтобы обеспечить выполнение методов @PreDestroy необходимо в контексте Spring зарегистрировать хук:

public static void main(String args[]) {
   // Shutdown Spring container gracefully in non-web applications !!
   //ConfigurableApplicationContext ctx = new
   AbstractApplicationContext ctx = new       AnnotationConfigApplicationContext(AppContext.class);
                ctx.registerShutdownHook();
 // main method exits, hook is called prior to the app shutting down...
 // @PreDestroy methods is called before close App               
}
Теперь перед выходом из метода main будет обеспечено выполнение всех методов отмеченных как @PreDestroy. Вместо AbstractApplicationContext можно использовать ConfigurableApplicationContext.
JavaEE
Точно такие же аннотации ( @PostConstruct и @PreDestroy ) поддерживают бины EJB (Enterprise Java Beans) и CDI (Contexts and Dependency Injection) из стека JavaEE. Stateful-бины EJB (сохраняющие состояние) помимо вышеуказанных 2-х также поддерживают еще 3 события:
@PrePassivate - метод выполняемый перед пассивацией - сериализацией и сохранением на носитель бина;
@PostActivate - метод выполняемый после активации - десериализации и восстановления бина с носителя;
@Remove - после выполнения этого метода контейнер EJB уничтожит бин.

Режимы загрузки бинов: Spring - @Lazy и JavaEE(EJB) - @Startup

Если в Spring бин аннотирован как @Lazy(true), то он будет создан только при первом обращении к нему:
@Component
@Lazy(true)
public class MyBean {
.........
}
Соответственно при @Lazy(false) бин создается сразу при старте приложения (режим по-умолчанию в Spring) - кстати для сравнения - аналогично работает аннотация @Startup для синглтонов EJB стека JavaEE. По умолчанию Spring создает все бины при старте приложения, т е работает режим @Lazy(false) - а вот в CDI и EJB из стека JavaEE все наоборот - там бины создаются лениво при первом обращении к ним. Если c помощью @Lazy аннотирован класс конфигурации Spring - то это будет работать для всех методов отмеченных аннотацией @Bean:
@Lazy(true)
@Configuration
@ComponentScan(basePackages = "my.app")
public class AppConfig {
    @Bean
    public Region getRegion(){
        return new Region();
    }
    @Bean
    public Country getCountry(){
        return new Country();
    }
}
Можно также использовать в классе конфигурации для отдельного бина:
@Configuration
@ComponentScan(basePackages = "my.app")
public class AppConfig {
    @Bean
    @Lazy(true)
    public Region getRegion(){
        return new Region();
    }

}
А также при внедрении совместно с @Autowired или @Inject:
    @Lazy(true)
    @Autowired
    private City city;

среда, 23 мая 2018 г.

Обьявление бинов - аннотирование классов для автоматического определения

 Spring
       По умолчанию аннотация @ComponentScan в классе конфигурации Spring ищет классы, отмеченные одной из аннотаций:
     @Component – универсальная аннотация, указывающая, что класс
     является компонентом Spring;
     @Controller – указывает, что класс определяет контроллер
     Spring MVC;
     @Repository – указывает, что класс определяет репозиторий дан-
     ных;
     @Service – указывает, что класс определяет службу;
     @Named("myBean") - аннотация из JavaEE CDI - Contexts and Dependency Injection (JSR-330) - равнозначна @Component или @Service при аннотировании класса;
     Spring поддерживает аннотации JavaEE CDI (JSR-330 = @Inject, @Named, @Singleton и др) - только для этого необходимо добавить зависимость в Maven:
    <dependency>
      <groupId>javax.inject</groupId>
      <artifactId>javax.inject</artifactId>
      <version>1</version>
    </dependency>

Пример:
@Service("message")
public class HelloWorld {
    ..........
}
     Здесь аннотация @Service указывает на то, что этот бин предоставляет службы, которые используются другими бинами, параметр аннотации - имя бина. Во время начальной загрузки ApplicationContext Spring будет искать эти компоненты и создавать бины с указанными именами.
     Применение @Component дает тот же эффект, что и @Service. Обе аннотации инструктируют Spring о том, что класс является кандидатом на автоматическое обнаружение с применением конфигурации, основанной на аннотациях. На практике @Service является специализацией @Component, отражающей тот факт, что класс предоставляет бизнес-службу другим уровням приложения.
JavaEE
Здесь никакого класса конфигурации не нужно - все предоставляет сервер JavaEE - работает так называемый принцип конфигурации по умолчанию принятый для JavaEE - если вы ничего не настраиваете то работает конфигурация по умолчанию. Только для включения механизма  CDI - Contexts and Dependency Injection необходимо наличие даже пустого файла beans.xml в каталоге META-INF или WEB-INF - вот этот файл:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
после этого все классы (если они не отмечены исключающими аннотациями) будут источниками для бинов CDI.

@Named - бин CDI c именем из имени класса - только первая буква будет малой
@Named("myBean") - бин CDI c заданным именем
@Vetoed - появилась в JavaEE-7 - запрещает создавать бины CDI из отмеченного класса
Для бинов EJB работают аннотации:
@Singleton - без комментариев)
@Stateless - бин без сохранения состояния
@Stateful - бин с сохранением состояния

 

Bean Scope

Spring:
По умолчанию все компоненты Spring единичны.
Обьявление в бине:
@Component
@Scope("prototype")
public class Primer {
.........
}
или так:
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Начиная с версии 4.3 в web-приложении можно также использовать аннотации:
@ApplicationScope
@RequestScope
@SessionScope
 Бывают:
- singleton = В каждом контейнере Spring может быть создан только
один компонент (по умолчанию);
- prototype = Позволяет создавать произвольное количество
компонентов (по одному на каждое обращение)
- request = Область действия ограничивается HTTP-запросом.         Применяется только в веб-приложениях Spring (Spring MVC);
- session = Область действия ограничивается HTTP-сеансом. Применяется только в веб-приложениях Spring (Spring MVC);
- global-session = Область действия ограничивается
глобальным HTTP-сеансом. Применяется только в портлетах;
      Понятие единичных компонентов ограничено областью действия контекста Spring. В отличие от истинных классов-одиночек, гарантирующих существование единственного экземпляра на каждый загрузчик классов (classloader), для единичных компонентов в Spring гарантируется только наличие единственного экземпляра компонента в контексте приложения – ничто не мешает создать экземпляр того же класса традиционным способом или даже создать несколько объявлений бина для одного и того же класса.
          Теперь для сравнения стек JavaEE:
JavaEE CDI:
@RequestScoped
@SessionScoped
@ApplicationScoped
@Dependent - по умолчанию - аналог "prototype" в Spring
@Singleton - В реализации CDI данного скоупа есть одна особенность: в процессе инъекции клиент получает ссылку на реальный объект созданный контейнером, а не proxy. В результате чего могут быть проблемы неоднозначности данных, если состояние синглтона будет меняться, а использующие его бины, например, были или будут сериализованы. 
JavaEE EJB:
@Stateful - сохраняющие состояние бины;
@Stateless - не сохраняющие состояние бины;
@Singleton  
И еще - по своей природе Request-бины потокобезопасны - отработал запрос и удалился.
 

Взаимодействие между приложениями и Watch Service

Взаимодействие между разными приложениями Java можно сделать с помощью файловой системы, базы данных и JMS. Рассмотрим случай ФС - в Java ...