Mit CDI statt @ManagedBean: UnproxyableResolutionException weil Superklasse hat keine No-args Konstruktor

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

  •  27-09-2019
  •  | 
  •  

Frage

Ich versuche CDI für meine JSF / Java EE-Anwendung zu verwenden. Ich habe die folgende Klassenhierarchie:

/**
 * 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);
  }
  //...
}

Wenn ich versuche, die Anwendung auf GF 3.1 zu implementieren, ich folgende CDI / Weld Ausnahme erhalten:

  

SCHWERE: Ausnahme beim Laden   App: WELD-001435 Normale scoped Bohne   Klasse   com.web.AbstractCrudController   nicht proxyable ist, weil es nicht hat   no-args-Konstruktor.   org.jboss.weld.exceptions.UnproxyableResolutionException:   WELD-001435 Normale scoped Bean-Klasse   com.web.AbstractCrudController   nicht proxyable ist, weil es nicht hat   no-args-Konstruktor.           bei org.jboss.weld.util.Proxies.getUnproxyableClassException (Proxies.java:215)           bei org.jboss.weld.util.Proxies.getUnproxyableTypeException (Proxies.java:166)           bei org.jboss.weld.util.Proxies.getUnproxyableTypesException (Proxies.java:191)           bei org.jboss.weld.bootstrap.Validator.validateBean (Validator.java:134)           bei org.jboss.weld.bootstrap.Validator.validateRIBean (Validator.java:148)           bei org.jboss.weld.bootstrap.Validator.validateBeans (Validator.java:363)           bei org.jboss.weld.bootstrap.Validator.validateDeployment (Validator.java:349)           bei org.jboss.weld.bootstrap.WeldBootstrap.validateBeans (WeldBootstrap.java:416)           bei org.glassfish.weld.WeldDeployer.event (WeldDeployer.java:178)           bei org.glassfish.kernel.event.EventsImpl.send (EventsImpl.java:128)           bei org.glassfish.internal.data.ApplicationInfo.start (ApplicationInfo.java:265)           bei com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:402)           bei com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:221)           bei org.glassfish.deployment.admin.DeployCommand.execute (DeployCommand.java:351)           bei com.sun.enterprise.v3.admin.CommandRunnerImpl $ 1.execute (CommandRunnerImpl.java:360)           bei com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:375)           bei com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:1072)           bei com.sun.enterprise.v3.admin.CommandRunnerImpl.access $ 1200 (CommandRunnerImpl.java:101)           bei com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1221)           bei com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1210)           bei com.sun.enterprise.v3.admin.AdminAdapter.doCommand (AdminAdapter.java:375)           bei com.sun.enterprise.v3.admin.AdminAdapter.service (AdminAdapter.java:209)           bei com.sun.grizzly.tcp.http11.GrizzlyAdapter.service (GrizzlyAdapter.java:166)           bei com.sun.enterprise.v3.server.HK2Dispatcher.dispath (HK2Dispatcher.java:117)           bei com.sun.enterprise.v3.services.impl.ContainerMapper.service (ContainerMapper.java:234)           bei com.sun.grizzly.http.ProcessorTask.invokeAdapter (ProcessorTask.java:824)           bei com.sun.grizzly.http.ProcessorTask.doProcess (ProcessorTask.java:721)           bei com.sun.grizzly.http.ProcessorTask.process (ProcessorTask.java:1014)           bei com.sun.grizzly.http.DefaultProtocolFilter.execute (DefaultProtocolFilter.java:220)           bei com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter (DefaultProtocolChain.java:135)           bei com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:102)           bei com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:88)           bei com.sun.grizzly.http.HttpProtocolChain.execute (HttpProtocolChain.java:76)           bei com.sun.grizzly.ProtocolChainContextTask.doCall (ProtocolChainContextTask.java:53)           bei com.sun.grizzly.SelectionKeyContextTask.call (SelectionKeyContextTask.java:57)           bei com.sun.grizzly.ContextTask.run (ContextTask.java:69)           bei com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork (AbstractThreadPool.java:530)           bei com.sun.grizzly.util.AbstractThreadPool $ Worker.run (AbstractThreadPool.java:511)           bei java.lang.Thread.run (Thread.java:637)

Auch wenn ich einen No-args Konstruktor der Basisklasse hinzufügen, Weld klagt immer noch mit der gleichen Ausnahme, dass die Klasse nicht proxyable ist, weil es letztes Verfahren hat. Warum WELD mich zwingen, meine Klasse Design zu ändern? Alles hat gut funktioniert die JSF @ManagedBean Annotation verwenden.

würde ich jede Hilfe dankbar. Danken, Theo

War es hilfreich?

Lösung

  

Warum WELD mich zwingen, meine Klasse Design zu ändern? Alles hat gut funktioniert die JSF @ManagedBean Anmerkung verwendet wird.

Nun, Weld / CDI nicht die gleiche Art und Weise arbeiten. Mein Verständnis ist, dass, wenn Sie Injektion verwenden, um einen Verweis auf eine Bohne zu erhalten, was man bekommt, ist in den meisten Fällen ein Proxy-Objekt. Diese Proxy-Objekt Unterklassen Bean und überschreibt die Methoden Delegation zu implementieren. Und das bringt einige Einschränkungen für die Klassen CDI kann Proxy.

Die CDI-Spezifikation legt es wie folgt aus:

  

5.4.1. Unproxyable Bohnenarten

     

Bestimmte Rechtsbohnentypen können nicht sein   durch den Behälter proxied:

     
      
  • Klassen, die keine nicht-privaten Konstruktor ohne   Parameter,
  •   
  • Klassen, die als final deklariert werden oder haben endgültige Methoden,
  •   
  • primitive Typen,
  •   
  • und Array-Typen.
  •   
     

Wenn eine Injektionsstelle, deren erklärte   Typ kann nicht durch die Proxy-Klasse zugänglich werden   Behälter Entschlüssen zu einer Bohne mit einem   normaler Umfang, der Behälter   automatisch erkennt das Problem und   behandelt es als ein Verteilungsproblem.

wäre mein Vorschlag, um die Verfahren nicht endgültig zu machen.

Referenzen

  • CDI Spezifikation
    • Abschnitt 5.4. "Client-Proxies"
    • Abschnitt 5.4.1 "Unproxyable Bohnenarten"
    • Abschnitt 6.3. "Normale Bereiche und pseudo-Bereiche"

Andere Tipps

Ich bin in dem Prozess von JSF Managed Beans von Migration auf CDI Bohnen verwaltet, und ich nur bestätigt, dass ich Gebrauch der Lage bin, Super erfolgreich in einem Nachkommen CDI Bean (mit 'custom' @Descendant Qualifier), dass '' erstreckt ein Vorfahre CDI Bean (mit @Default Qualifier).

CDI Bean Vorfahren mit @Default Qualifier:

@Default
@Named("pf_pointOfContactController")
@SessionScoped
public class pf_PointOfContactController implements Serializable {

Vorfahr Bohne hat die folgende:

@PostConstruct
protected void init() {

CDI Bean Nachkomme mit @Descendant Qualifier:

@Descendant
@Named("pf_orderCustomerPointOfContactController")
@SessionScoped
public class pf_OrderCustomerPointOfContactController extends pf_PointOfContactController {

Nachkomme Bohne hat die folgende:

@PostConstruct
public void init(){
    super.init();

Ich hatte hinzufügen / Verwendung super.init (), weil Methoden in der Vorfahr CDI Bean Nullpointer wurden erhöht, da Vorfahren @PostConstruct Bean wird in CDI @Descendant Bohne nicht ausgeführt wird.

Ich habe gelesen, gesehen / gehört / dass es empfohlen wird anstelle von Constructor-Methode zu verwenden @PostConstruct wenn CDI verwendet wird, so Vorfahren Bean Konstruktor die ‚Initialisierung‘ Logik hatte, und Vorfahren Konstrukteurs-Bean wurde automatisch aufgerufen / ausgeführt wird, wenn JSF mit Managed beans.

Da akzeptierte Antwort ist richtig, aber unvollständig ich glaube, ich kann meinen zwei Cent nur für zukünftige Leser hinzufügen.

Das Problem, das OP auftreten kann auf zwei Arten gelöst werden:

  1. Durch das Entfernen final Stichwort von Methoden und Klasse selbst
  2. solche "unproxyable Klasse" mit @Singleton oder @Dependent Pseudo-scope-Kennzeichnung (natürlich nur, wenn es Sinn macht). Es wird funktionieren, weil CDI kein Proxy-Objekt für pseudo-scoped Bohnen erstellen.

Im OP Anwendungsfall der zweite Ansatz IMHO empfohlen wurde, als Controller können auf jeden Fall als Singletons markiert werden.

Hope es hilft jemand

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top