Ограниченные дженерики с CDI

В спецификации JSR-299 в & # xA7; 3.1 говорится:

If the managed bean class is a generic type, it must have scope @Dependent. If a managed bean with a parameterized bean class declares any scope other than @Dependent, the container automatically detects the problem and treats it as a definition error.

Фактически это означает, что вы не можете сделать это:

@Named
@SessionScoped or @RequestScoped or similar
public class MyProducer<T> {...}

Каковы технические причины этого решения?

Будет ли это исправлено в следующей версии CDI случайно?

Есть ли лучшая практика для решения / работы вокруг этого?

Спасибо

EDIT - Обходной путь, который я часто могу использовать, - это введение общего POJO-бина в бин с необходимой областью действия. Часто, но не всегда.

 Tom Anderson21 июн. 2012 г., 19:07
Отличный вопрос, кстати. Я не знал об этом ограничении, и оно действительно заставляет вас задуматься.

Ответы на вопрос(2)

Решение Вопроса

Вот обобщенный, независимый класс бина:

@ApplicationScoped
public class FavouriteChooser<T> {
    public T getFavourite() {
        // ...
    }
}

Сколько экземпляров этого компонента будет в приложении?

Вот место инъекции:

@Inject
private FavouriteChooser<String> favouriteWord;

А вот еще один:

@Inject
private FavouriteChooser<Integer> favouriteNumber;

Хотите изменить свой ответ? : D

О, а вот еще:

@Inject
private FavouriteChooser<CharSequence> favouriteLetters;

РЕДАКТИРОВАТЬ. Если вы хотите найти решение, я бы предложил сделать ваш обобщенный класс абстрактным и добавить конкретные подклассы, которые связывают тип. Так:

public abstract class MyProducer<T> {...}

@Named
@SessionScoped
public class MyStringProducer extends MyProducer<String> {}

@Named
@SessionScoped
public class MyIntegerProducer extends MyProducer<Integer> {}

Это стандартный шаблон, но он имеет только три строки для каждого типа. Имейте в виду, что это даст вам один экземпляр на сеанс для каждого типа, который вы можете не захотеть.

 21 июн. 2012 г., 19:05
Извините, что не прояснил, что я пытался сказать, когда писал этот ответ. Я просто поторопился, не успев должным образом объяснить.
 21 июн. 2012 г., 19:10
Кроме того, есть простой, но уродливый обходной путь / решение, которое я добавил.
 kostja21 июн. 2012 г., 18:11
Хорошо - так что, пока вы не сделаете бин именованным, его можно вводить? Если область видимости сохраняется (верно? - каждая ли область FavouriteChooser вводится в область действия приложения?), То единственным ограничением будет то, что я не могу получить к ним доступ с помощью выражений EL? И разве это не противоречит спецификации? В конце концов, это должен быть управляемый боб.
 21 июн. 2012 г., 19:04
Нет, я хочу сказать, что этот код не может работать! Я объявилFavouriteChooser область применения, что означает, что может быть только один экземпляр. Но есть два места для инъекций, которыеcannot be satisfied by the same object, И именно поэтому я думаю, что вы не можете внедрять экземпляры универсальных классов в любую область, кроме зависимой.
 21 июн. 2012 г., 19:07
Теперь одна вещь, которая приходит на ум, это идея нового вида области видимости, которая является областью привязки переменной типа; если бы у вас была область действия, которая была «где T - строка», то в этой области вы могли бы иметь экземплярFavouriteChooser который может быть введен в любом месте, где нужноFavouriteChooser<String>, Но это сугубо теоретическая идея!

Все независимые bean-объекты должны быть проксированы - AFAIK это невозможно с универсальными типами.

ОБНОВИТЬ:

Я хотел бы иметь возможность объяснить это более подробно, но я не ;-) Weld используетJavassistи они заявляют, чтопроксирование общих типов возможно в принципе - хотя напрямую не поддерживается API верхнего уровня. Но речь идет о спецификации, а не о реализации Weld ...

Может быть, кто-то еще может заполнить пробел?

 kostja21 июн. 2012 г., 16:51
Спасибо, Ян. Это уже проливает некоторый свет на этот вопрос - было бы замечательно, если бы вы могли также объяснить, почему универсальные типы не могут быть проксированы (я думаю, это связано с основным стиранием типа java nemesis, но не могу указать на это).

Ваш ответ на вопрос