Используя CDI вместо @manageBean: FOBOXYBLEERSOLICEXCECTION, потому что Super Class не имеет конструктора No-Args
-
27-09-2019 - |
Вопрос
Я пытаюсь использовать CDI для моего приложения JSF / Java EE. У меня есть следующая класса иерархии:
/**
* base controller class
* also contains some final methods and an inner enum class declaration
*/
public abstract class AbstractCrudController<K, E> implements Serializable {
private Class<E> entityClass;
public AbstractCrudController(Class<E> entityClass) {
this.entityClass = entityClass;
}
// ...
}
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
@Named
@SessionScoped
public class CategoryController extends AbstractCrudController<Long, Category> implements Serializable {
public CategoryController() {
super(Category.class);
}
//...
}
Когда я пытаюсь развернуть приложение на GF 3.1, я получаю следующее исключение CDI / WELD:
Syrese: Исключение При загрузке приложения: WELD-001435 NORMAL COMPED COM.WEB COMPED COM.WEB.ABSTACTCRUDCONTROLLER не прокси, потому что он не имеет конструктора No-Args. org.jboss.weld.exceptions.unproxyableResoluteException: WELD-001435 Нормальный уклон COM.web.AbstractCrudController не прокси, потому что он не имеет конструктора No-args. на org.jboss.weld.util.proxies.getunproxyableClassexception (proxies.java:215) на org.jboss.weld.util.proxies.getunproxyableTypeexception (proxies.java:166) на org.jboss.weld.Util.proxies.getunproxyabletypesexception. (Proxies.java:191) на org.jboss.weld.bootstrap.validator.validateBean (Validator.java:134) на org.jboss.weld.bootstrap.validator.validatoribean (Validator.java:148) на org.jboss. weld.bootstrap.validator.validabebeans (Validator.java:363) на org.jboss.weld.bootstrap.validator.validatevatewordment (Validator.java:349) на org.jboss.weld.bootstrap.weldbootstrap.validatebeans (weldbootstrap.java: 416) на org.glassfish.weld.welddeployer.event (welddeployer.java:178) на org.glassfish.kernel.event.eventsimpl.send (corversimpl.java:128) в org.glassfish.internal.data.ApplicationInfo.start (Applicationinfo.java:265) на com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:402) на com.sun.enterprise.v3.server.Applicationlifecycle.deploy (applicationlifecycle.java:221) в org.glassfish. .Commandrunnerimpl.docommand (commandrunnerimpl.java:375) на com.sun.enterprise.v3.admin.commandrunnerimpl.docommand (commandrunnerimpl.java:1072) на com.sun.enterprise.v3.admin.commandrunnerympl.Access $ 1200 (commandrunnerimpl. Java: 101) в com.sun.enterprise.v3.admin.commandrunnerympl $ ExecutionContext.execute (commandrunnerympl.java:1221) на com.sun.enterprise.v3.admin.commandrunnerympl $ executionContext.java:1210) at com.sun.enterprise.v3.admin.adminadapter.docommand (adminadapter.java:375) на com.sun.enterprise.v3.admin.adminadapter.service (adminadapter.java:209) на com.sun.grizzly.tcp .http11.grizzlyAdapter.service (grizzlyAdapter.java:166) на com.sun.enterprise.v3.server.hk2dispatcher.dispath (hk2dispatcher.java:117) на com.sun.enterprise.v3.services.impl.containermapper .se RVICE (Containermapper.java:234) на com.sun.grizzly.http.processortask.invoxeAdapter (Processortask.java:824) на com.sun.grizzly.http.processortask.doprocess (Processordask.java:721) в Com.sun .Grizzly.http.processortask.process (Processordask.java:1014) на com.sun.grizzly.http.defaultprotocolfilter.efecuteprotocolfilter.efecute (defaultprotocolfilter.java:220) на com.sun.grizzly.defaultprotocolChain.executeProtocolfilter. ) на com.sun.grizzly.defaultProtocolChain.efecute (defaldprotcrotocolchain.java:102) на com.sun.grizzly.defaultprotocolcheain.efecute (default protocolchain.java:88) на com.sun.grizzly.http.httpprotocolChain.execute (httpprotocolChain. Java: 76) на com.sun.grizzly.protocolChainContextTask.docall (protocolchaincontexttask.java:53) на com.sun.grizzly.selioucekeyCokekekekekekekekekekekekekeke.Call (SelectionkeyContextTask.java:57) в Com.sun.grizzly.contextTask.run (Contexttask .java: 69) на com.sun.grizzly.util.abstractTracttreadpool $ Worker.dowork (AlludeThreadpool.java:530) в com.sun.grizzly.util.abst RactThreadPool $ Worker.run (AlludeThreadpool.java:511) в Java.lang.thread.run (Thread.java:637)
Даже если я добавлю конструктор NO-ARGS в базовый класс, сварные сварные приводы до сих пор жалуются с тем же исключением, что класс не прокси, поскольку имеет конечные методы. Почему сварки заставляют меня изменить свой класс дизайн? Все работало нормально, используя аннотацию JSF @manedBean.
Буду признателен за любую помощь. Спасибо, Тео
Решение
Почему сварки заставляют меня изменить свой класс дизайн? Все работало нормально, используя аннотацию JSF @manedBean.
Ну, сварки / CDI не работают так же. Мое понимание в том, что когда вы используете инъекцию, чтобы получить ссылку на бону, то, что вы получаете в большинство случаев прокси-объект. Этот прокси-объект подкладывает ваш боб и переопределяет методы реализации делегирования. И это вводит некоторые ограничения на классы CDI CAN Proxy.
CDI SPEC ставит это так:
5.4.1. Скажинные виды бобов
Некоторые юридические типы бобов не могут быть закреплены контейнером:
- классы, которые не имеют не частного конструктора без параметров,
- классы, которые объявлены окончательными или имеют конечные методы,
- Примитивные типы,
- и типы массива.
Если точка инъекции, заявленный тип которого не может быть закреплен контейнером, решает к бобовому компонеру с нормальным объемом, контейнер автоматически обнаруживает проблему и обрабатывает его как проблема развертывания.
Мое предложение было бы сделать методы не окончательными.
использованная литература
- Спецификация CDI.
- Раздел 5.4. «Клиентские прокси»
- Раздел 5.4.1 "Сопровижные типы бобов"
- Раздел 6.3. «Нормальные области и псевдо-спецификации»
Другие советы
Я в процессе миграции из JSF управляемых бобов для CDI управляемых бобов, и я только что подтвердил, что я могу использовать супер Успешно в потомке CDI Bean (с «пользовательским» квалификатором @DEScendant), что «расширяет» фасоль CDI предка (с Qualifier @Default).
Раздан CDI Bean с Qualifier @Default:
@Default
@Named("pf_pointOfContactController")
@SessionScoped
public class pf_PointOfContactController implements Serializable {
Бин предка имеет следующее:
@PostConstruct
protected void init() {
CDI Bean Cosendant с @descendant квалификатор:
@Descendant
@Named("pf_orderCustomerPointOfContactController")
@SessionScoped
public class pf_OrderCustomerPointOfContactController extends pf_PointOfContactController {
Потомкая фасоль имеет следующее:
@PostConstruct
public void init(){
super.init();
Мне пришлось добавить / использовать super.init (), потому что методы в предложении CDI Bean были подняты NullPointerException, поскольку @postconstconstruct @postconstluct не выполняется в CDI @Descendant Bean.
Я видел / слышал / читал, что рекомендуется использовать @postconstruct вместо метода конструктора при использовании CDI, поэтому конструктор предков бобов имел логику «Инициализация», а конструктор «Инициализации», а конструктор пренского компонента был автоматически вызван / выполнен при использовании JSF Managed Beans.
Поскольку принятый ответ правильный, но неполный, я думаю, что могу добавить свои два цента только для будущих читателей.
Проблема, которая столкнулась с OP, может быть решена двумя способами:
- Удаление
final
ключевое слово из методов и самого класса - Маркировка такого «спроектированного класса» с
@Singleton
или@Dependent
Псевдо-область (конечно, если это имеет смысл). Он будет работать, потому что CDI не создает прокси-объект для Pseudo-Scoped Beans.
В операционном случае был рекомендован второй подход IMHO, поскольку контроллеры определенно могут быть помечены как Singletons.
Надеюсь, это поможет кому-то