Utilizzando CDI invece di @ManagedBean: UnproxyableResolutionException perché super classe non ci sono no-args costruttore

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

  •  27-09-2019
  •  | 
  •  

Domanda

Sto cercando di usare CDI per la mia JSF / applicazione Java EE. Ho la seguente gerarchia di classe:

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

Quando si tenta di distribuire l'applicazione su GF 3.1, ottengo la seguente eccezione CDI / Salda:

  

GRAVI: eccezione durante il caricamento del   app: WELD-001.435 normale ambito di fagioli   classe   com.web.AbstractCrudController   Non è proxyable perché non ha   no-args costruttore.   org.jboss.weld.exceptions.UnproxyableResolutionException:   WELD-001.435 Normale ambito classe bean   com.web.AbstractCrudController   Non è proxyable perché non ha   no-args costruttore.           a org.jboss.weld.util.Proxies.getUnproxyableClassException (Proxies.java:215)           a org.jboss.weld.util.Proxies.getUnproxyableTypeException (Proxies.java:166)           a org.jboss.weld.util.Proxies.getUnproxyableTypesException (Proxies.java:191)           a org.jboss.weld.bootstrap.Validator.validateBean (Validator.java:134)           a org.jboss.weld.bootstrap.Validator.validateRIBean (Validator.java:148)           a org.jboss.weld.bootstrap.Validator.validateBeans (Validator.java:363)           a org.jboss.weld.bootstrap.Validator.validateDeployment (Validator.java:349)           a org.jboss.weld.bootstrap.WeldBootstrap.validateBeans (WeldBootstrap.java:416)           a org.glassfish.weld.WeldDeployer.event (WeldDeployer.java:178)           a org.glassfish.kernel.event.EventsImpl.send (EventsImpl.java:128)           a org.glassfish.internal.data.ApplicationInfo.start (ApplicationInfo.java:265)           a com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:402)           a com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:221)           a org.glassfish.deployment.admin.DeployCommand.execute (DeployCommand.java:351)           a com.sun.enterprise.v3.admin.CommandRunnerImpl $ 1.execute (CommandRunnerImpl.java:360)           a com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:375)           a com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:1072)           a com.sun.enterprise.v3.admin.CommandRunnerImpl.access $ 1200 (CommandRunnerImpl.java:101)           a com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1221)           a com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1210)           a com.sun.enterprise.v3.admin.AdminAdapter.doCommand (AdminAdapter.java:375)           a com.sun.enterprise.v3.admin.AdminAdapter.service (AdminAdapter.java:209)           a com.sun.grizzly.tcp.http11.GrizzlyAdapter.service (GrizzlyAdapter.java:166)           a com.sun.enterprise.v3.server.HK2Dispatcher.dispath (HK2Dispatcher.java:117)           a com.sun.enterprise.v3.services.impl.ContainerMapper.service (ContainerMapper.java:234)           a com.sun.grizzly.http.ProcessorTask.invokeAdapter (ProcessorTask.java:824)           a com.sun.grizzly.http.ProcessorTask.doProcess (ProcessorTask.java:721)           a com.sun.grizzly.http.ProcessorTask.process (ProcessorTask.java:1014)           a com.sun.grizzly.http.DefaultProtocolFilter.execute (DefaultProtocolFilter.java:220)           a com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter (DefaultProtocolChain.java:135)           a com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:102)           a com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:88)           a com.sun.grizzly.http.HttpProtocolChain.execute (HttpProtocolChain.java:76)           a com.sun.grizzly.ProtocolChainContextTask.doCall (ProtocolChainContextTask.java:53)           a com.sun.grizzly.SelectionKeyContextTask.call (SelectionKeyContextTask.java:57)           a com.sun.grizzly.ContextTask.run (ContextTask.java:69)           a com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork (AbstractThreadPool.java:530)           a com.sun.grizzly.util.AbstractThreadPool $ Worker.run (AbstractThreadPool.java:511)           a java.lang.Thread.run (Thread.java:637)

Anche se posso aggiungere un costruttore no-args alla classe di base, Weld lamenta ancora con la stessa eccezione che la classe non è proxyable perché ha metodi finali. Perché WELD mi costringono a cambiare il mio design di classe? Tutto ha funzionato bene usando l'annotazione JSF @ManagedBean.

Gradirei qualsiasi aiuto. Grazie, Theo

È stato utile?

Soluzione

  

Perché WELD mi costringono a cambiare il mio design di classe? Tutto ha funzionato bene usando l'annotazione JSF @ManagedBean.

Bene, Weld / CDI non funziona allo stesso modo. La mia comprensione è che quando si utilizza l'iniezione per ottenere un riferimento a un fagiolo, quello che si ottiene è in maggior parte dei casi un oggetto proxy. Questo oggetto proxy sottoclassi il bean e sovrascrive i metodi per implementare la delega. E questo introduce alcune restrizioni sulla lattina delega classi CDI.

Il CDI spec si esprime così:

  

5.4.1. tipi di fagioli Unproxyable

     

Alcuni tipi di fagioli di legge non può essere   proxy dal contenitore:

     
      
  • classi che non hanno un costruttore non privata senza   parametri,
  •   
  • classi che sono dichiarati finale o hanno metodi finali,
  •   
  • tipi primitivi,
  •   
  • e array di tipi.
  •   
     

Se un punto di iniezione la cui dichiarata   tipo non può essere approssimata dalla   risolve Contenitore per un bean con   portata normale, il contenitore   rileva automaticamente il problema e   considera come un problema di distribuzione.

Il mio suggerimento sarebbe quello di rendere i metodi non finale.

Bibliografia

  • CDI Specification
    • Sezione 5.4. "Proxy client"
    • Sezione 5.4.1 "tipi di fagioli Unproxyable"
    • Sezione 6.3. "Ambiti normali e pseudo-scope"

Altri suggerimenti

Sono in fase di migrazione da JSF Managed fagioli per CDI gestito fagioli, e ho appena confermato che sono in grado di utilizzare Super con successo in un fagiolo discendente CDI (con 'su misura' qualificatore @Descendant), che 'estende' un bean antenato CDI (con qualificatore @Default).

antenato di fagioli CDI con qualificatore @Default:

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

Antenato fagiolo ha la seguente:

@PostConstruct
protected void init() {

discendente di fagioli CDI con qualificatore @Descendant:

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

fagioli Discendente ha il seguente:

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

ho dovuto aggiungere / uso super.init (), perché i metodi nel bean antenato CDI sono state alzando NullPointerException, dal momento che @PostConstruct antenato del bean non viene eseguito in CDI @Descendant fagiolo.

Ho visto / sentito / letto che si raccomanda di usare @PostConstruct al posto di metodo di costruzione quando si utilizza CDI, in modo costruttore antenato di fagiolo ha avuto la logica 'di inizializzazione', e il costruttore antenato di fagiolo è stato invocato automaticamente / eseguiti quando si usa JSF gestito fagioli.

A causa risposta accettato è corretta ma incompleta penso di poter aggiungere i miei due centesimi solo per i futuri lettori.

Il problema che OP riscontrato può essere risolto in due modi:

  1. Rimuovendo final parola chiave da metodi e classe stessa
  2. Marcatura tale "classe unproxyable" con @Singleton o @Dependent pseudo-scope (ovviamente se ha senso). Esso funziona perché CDI non crea un oggetto proxy per i fagioli pseudo-ambito.

Nel caso dell'uso OP è stato raccomandato secondo IMHO approccio, come controller sicuramente possono essere contrassegnati come singletons.

La speranza aiuta qualcuno

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top