Статьи

Пример устранения неоднозначности в отношении программной зависимости Java EE CDI — проверка точки ввода

В этом уроке мы увидим, как мы можем избежать неоднозначности программных зависимостей при внедрении компонентов Java EE CDI. Мы уже показали в примере устранения неоднозначности зависимостей Jave EE, как избежать устранения неоднозначности зависимостей в компонентах CDI. Здесь мы покажем вам, как избежать двусмысленности зависимостей динамическим способом. Мы добьемся этого, проверив точку внедрения компонента, который внедряет реализацию другого компонента.

Программная неоднозначность с проверкой точки впрыска будет исследована путем создания простого сервиса с двумя реализациями. Затем мы создадим метод Producer для создания и внедрения обеих реализаций в приложении.

Нашей предпочтительной средой разработки является Eclipse . Мы используем версию Eclipse Juno (4.2) вместе с плагином Maven Integration версии 3.1.0. Вы можете скачать Eclipse отсюда и Maven Plugin для Eclipse отсюда . Установка плагина Maven для Eclipse выходит за рамки данного руководства и не будет обсуждаться. Tomcat 7 — это используемый сервер приложений.

Давайте начнем,

1. Создайте новый проект Maven

Перейдите в Файл -> Проект -> Maven -> Проект Maven.

New-Maven-проект

На странице мастера «Выберите имя проекта и местоположение» убедитесь, что опция «Создать простой проект (пропустить выбор архетипа») не отмечена , нажмите «Далее», чтобы продолжить со значениями по умолчанию.

новый проект

Здесь должен быть добавлен архетип maven для создания веб-приложения. Нажмите «Добавить архетип» и добавьте архетип. Установите переменную «Archetype Group Id» на "org.apache.maven.archetypes" , переменную «Archetype ardact Id» на "maven-archetype-webapp" и «Archetype Version» на "1.0" . Нажмите «ОК», чтобы продолжить.

Maven-архетип-WebApp

На странице мастера «Введите идентификатор артефакта» вы можете определить имя и основной пакет вашего проекта. Установите для переменной «Group Id» значение "com.javacodegeeks.snippets.enterprise" а для переменной «Artifact Id» — "cdibeans" . Вышеупомянутые варианты составляют основной пакет проекта как "com.javacodegeeks.snippets.enterprise.cdibeans" а имя проекта — "cdibeans" . Установите для переменной «Package» значение "war" , чтобы создать файл war для развертывания на сервере tomcat. Нажмите «Готово», чтобы выйти из мастера и создать свой проект.

newcdiproject1

Структура проекта Maven показана ниже:

newcdiproject2

    Он состоит из следующих папок:

  • Папка / src / main / java, которая содержит исходные файлы для динамического содержимого приложения,
  • Папка / src / test / java содержит все исходные файлы для модульных тестов,
  • Папка / src / main / resources содержит файлы конфигурации,
  • Папка / target содержит скомпилированные и упакованные результаты,
  • Папка / src / main / resources / webapp / WEB-INF содержит дескрипторы развертывания для веб-приложения,
  • pom.xml — это файл объектной модели проекта (POM). Единственный файл, который содержит все связанные с проектом конфигурации.

2. Добавьте все необходимые зависимости

Вы можете добавить зависимости в файле Maven pom.xml , отредактировав его на странице «Pom.xml» редактора POM, как показано ниже:

pom.xml:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.javacodegeeks.snippets.enterprise.cdi</groupId>
    <artifactId>cdibeans</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>cdibeans Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.jboss.weld.servlet</groupId>
            <artifactId>weld-servlet</artifactId>
            <version>1.1.10.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.faces</artifactId>
            <version>2.1.7</version>
        </dependency>
    </dependencies>
 
    <build>
        <finalName>cdibeans</finalName>
    </build>
</project>

Как видите, Maven декларативно управляет библиотечными зависимостями. Создается локальный репозиторий (по умолчанию в папке {user_home} /. M2), и все необходимые библиотеки загружаются и помещаются туда из общедоступных репозиториев. Кроме того, внутрибиблиотечные зависимости автоматически разрешаются и обрабатываются.

3. Создать простой Сервис

GreetingCard.java простой сервис, который создает приветственное сообщение для приложения, которое его использует. Это интерфейс с методом, который создает приветственное сообщение.

GreetingCard.java

1
2
3
4
5
6
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
public interface GreetingCard {
 
    void sayHello();
}

Реализации сервиса показаны ниже:

GreetingCardImpl.java

01
02
03
04
05
06
07
08
09
10
11
package com.javacodegeeks.snippets.enterprise.cdibeans.impl;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingCard;
 
public class GreetingCardImpl implements GreetingCard {
 
    public void sayHello() {
        System.out.println("Hello!!!");
    }
 
}

AnotherGreetingCardImpl.java

01
02
03
04
05
06
07
08
09
10
11
12
package com.javacodegeeks.snippets.enterprise.cdibeans.impl;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingCard;
 
 
public class AnotherGreetingCardImpl implements GreetingCard {
 
    public void sayHello() {
        System.out.println("Have a nice day!!!");
    }
 
}

4. Создайте метод Producer для внедрения компонента

Чтобы добавить сервис другому бину, мы создаем собственную аннотацию. CDI позволяет нам создавать нашу собственную аннотацию Java, то есть GreetingType.java , а затем использовать ее в точке внедрения нашего приложения, чтобы получить правильную реализацию GreetingCard соответствии с GreetingType компонента.

Greetings — это перечисление, параметризованное реализациями службы, как показано ниже:

GreetingType.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;
 
@Retention(RUNTIME)
@Target({ FIELD, TYPE, METHOD })
public @interface GreetingType {
 
    Greetings value();
     
    public enum Greetings {
         
        HELLO(GreetingCardImpl.class), HI(AnotherGreetingCardImpl.class);
         
        Class<? extends GreetingCard> clazz;
         
        private Greetings(Class<? extends GreetingCard> clazz){
            this.clazz = clazz;
        }
 
        public Class<? extends GreetingCard> getClazz() {
            return clazz;
        }
    }
}

Теперь мы можем создать Producer для предоставления приложениям экземпляров реализаций службы GreetingCard . Класс GreetingCardFactory.java является источником, у которого есть метод getGreetingCard . Метод принимает два параметра. Первый параметр — это javax.enterprise.inject.Instance параметризованный с требуемым типом бина, то есть здесь GreetingCard . Он аннотируется аннотацией @Any которая позволяет точке внедрения ссылаться на все bean-компоненты или все события определенного типа bean-компонента. Второй параметр — это javax.enterprise.inject.spi.InjectionPoint который является полем в клиентском приложении, которое будет вводить компонент с @Inject аннотации @Inject . Таким образом, метод вернет правильную реализацию сервиса в соответствии с типом сервиса и аннотациями в точке внедрения.

GreetingCardFactory.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.InjectionPoint;
 
public class GreetingCardFactory {
 
    @Produces
    @GreetingsProducer
    public GreetingCard getGreetingCard(@Any Instance<GreetingCard> instance, InjectionPoint ip){
         
        Annotated gtAnnotated = ip.getAnnotated();
        GreetingType gtAnnotation = gtAnnotated.getAnnotation(GreetingType.class);
        Class<? extends GreetingCard> greetingCard = gtAnnotation.value().getClazz();
        return instance.select(greetingCard).get();
    }
}

Обратите внимание, что метод @Produces дополнительной аннотацией, кроме аннотации @Produces которая определяет метод как источник. Аннотация @GreetingsProducer используется для точки внедрения, чтобы определить, что она использует указанный метод Producer для внедрения экземпляра компонента. Это фактически CDI Qualifier, показанный ниже:

GreetingsProducer.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
import javax.inject.Qualifier;
 
@Qualifier
@Retention(RUNTIME)
@Target({ FIELD, TYPE, METHOD })
public @interface GreetingsProducer {
 
}

5. Запустите приложение

Чтобы запустить приложение, мы создали простой сервлет.

В сервлете ниже обе реализации внедрены. Каждая точка внедрения в сервлете является полем, в котором @Inject аннотация @Inject . Он также аннотируется аннотацией @GreetingsProducer для указания источника, который будет использоваться, а также аннотацией @GreetingType , указывающей, какая реализация будет произведена источником.

GreetingServlet.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package com.javacodegeeks.snippets.enterprise.cdibeans.servlet;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingCard;
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingType;
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingType.Greetings;
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingsProducer;
 
@WebServlet(name = "greetingServlet", urlPatterns = {"/sayHello"})
public class GreetingServlet extends HttpServlet {
 
    private static final long serialVersionUID = 2280890757609124481L;
     
    @Inject
    @GreetingsProducer
    @GreetingType(Greetings.HELLO)
    private GreetingCard greetingCard;
 
    @Inject
    @GreetingsProducer
    @GreetingType(Greetings.HI)
    private GreetingCard anotherGreetingCard;
 
      public void init() throws ServletException {
      }
 
      public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
          response.setContentType("text/html");
          PrintWriter out = response.getWriter();
          out.println("<h1>" + greetingCard.sayHello() + "</h1>");
          out.println("<h1>" + anotherGreetingCard.sayHello() + "</h1>");
      }
       
      public void destroy(){
      }
 
}

Чтобы запустить пример, мы должны построить проект с Maven, а затем поместить файл war созданный в папке webbaps на tomcat. Тогда мы можем нажать на:

http://localhost/8080/cdibeans/sayHello

и результат показан ниже:

тычок

Это было учебное руководство по устранению неоднозначности программных зависимостей CDI Java EE с проверкой точки внедрения

Загрузите исходный код этого учебника: CDIDependencyDisambiguationIPInspection.zip