Используя CDI вместо @manageBean: FOBOXYBLEERSOLICEXCECTION, потому что Super Class не имеет конструктора No-Args

StackOverflow https://stackoverflow.com/questions/3840240

  •  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, может быть решена двумя способами:

  1. Удаление final ключевое слово из методов и самого класса
  2. Маркировка такого «спроектированного класса» с @Singleton или @Dependent Псевдо-область (конечно, если это имеет смысл). Он будет работать, потому что CDI не создает прокси-объект для Pseudo-Scoped Beans.

В операционном случае был рекомендован второй подход IMHO, поскольку контроллеры определенно могут быть помечены как Singletons.

Надеюсь, это поможет кому-то

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top