Usando CDI en lugar de @ManagedBean: UnproxyableResolutionException porque superclase no tiene ningún constructor-args

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

  •  27-09-2019
  •  | 
  •  

Pregunta

Estoy tratando de utilizar CDI para aplicaciones Java EE mi JSF /. Tengo la siguiente jerarquía de clases:

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

Cuando intento de implementar la aplicación en GF 3.1, se produce la siguiente excepción CDI / Weld:

  

GRAVES: Excepción durante la carga de la   aplicación: Weld-001435 normal con ámbito de frijol   clase   com.web.AbstractCrudController   No es proxyable porque no tiene   sin argumentos constructor.   org.jboss.weld.exceptions.UnproxyableResolutionException:   Weld-001435 normal de ámbito clase de bean   com.web.AbstractCrudController   No es proxyable porque no tiene   sin argumentos constructor.           en org.jboss.weld.util.Proxies.getUnproxyableClassException (Proxies.java:215)           en org.jboss.weld.util.Proxies.getUnproxyableTypeException (Proxies.java:166)           en org.jboss.weld.util.Proxies.getUnproxyableTypesException (Proxies.java:191)           en org.jboss.weld.bootstrap.Validator.validateBean (Validator.java:134)           en org.jboss.weld.bootstrap.Validator.validateRIBean (Validator.java:148)           en org.jboss.weld.bootstrap.Validator.validateBeans (Validator.java:363)           en org.jboss.weld.bootstrap.Validator.validateDeployment (Validator.java:349)           en org.jboss.weld.bootstrap.WeldBootstrap.validateBeans (WeldBootstrap.java:416)           en org.glassfish.weld.WeldDeployer.event (WeldDeployer.java:178)           en org.glassfish.kernel.event.EventsImpl.send (EventsImpl.java:128)           en org.glassfish.internal.data.ApplicationInfo.start (ApplicationInfo.java:265)           en com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:402)           en com.sun.enterprise.v3.server.ApplicationLifecycle.deploy (ApplicationLifecycle.java:221)           en org.glassfish.deployment.admin.DeployCommand.execute (DeployCommand.java:351)           en com.sun.enterprise.v3.admin.CommandRunnerImpl $ 1.Ejecute (CommandRunnerImpl.java:360)           en com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:375)           en com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:1072)           en com.sun.enterprise.v3.admin.CommandRunnerImpl.access $ 1200 (CommandRunnerImpl.java:101)           en com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1221)           en com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1210)           en com.sun.enterprise.v3.admin.AdminAdapter.doCommand (AdminAdapter.java:375)           en com.sun.enterprise.v3.admin.AdminAdapter.service (AdminAdapter.java:209)           en com.sun.grizzly.tcp.http11.GrizzlyAdapter.service (GrizzlyAdapter.java:166)           en com.sun.enterprise.v3.server.HK2Dispatcher.dispath (HK2Dispatcher.java:117)           en com.sun.enterprise.v3.services.impl.ContainerMapper.service (ContainerMapper.java:234)           en com.sun.grizzly.http.ProcessorTask.invokeAdapter (ProcessorTask.java:824)           en com.sun.grizzly.http.ProcessorTask.doProcess (ProcessorTask.java:721)           en com.sun.grizzly.http.ProcessorTask.process (ProcessorTask.java:1014)           en com.sun.grizzly.http.DefaultProtocolFilter.execute (DefaultProtocolFilter.java:220)           en com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter (DefaultProtocolChain.java:135)           en com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:102)           en com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:88)           en com.sun.grizzly.http.HttpProtocolChain.execute (HttpProtocolChain.java:76)           en com.sun.grizzly.ProtocolChainContextTask.doCall (ProtocolChainContextTask.java:53)           en com.sun.grizzly.SelectionKeyContextTask.call (SelectionKeyContextTask.java:57)           en com.sun.grizzly.ContextTask.run (ContextTask.java:69)           en com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork (AbstractThreadPool.java:530)           en com.sun.grizzly.util.AbstractThreadPool $ Worker.run (AbstractThreadPool.java:511)           en java.lang.Thread.run (Thread.java:637)

Incluso si añado un constructor sin argumentos a la clase base, Weld todavía se queja con la misma salvedad que la clase no es proxyable porque tiene métodos finales. ¿Por qué me obligan soldadura para cambiar mi diseño de la clase? Todo funcionaba bien utilizando la anotación JSF @ManagedBean.

Le agradecería cualquier ayuda. Gracias, Theo

¿Fue útil?

Solución

  

¿Por qué me obliga soldadura para cambiar mi diseño de la clase? Todo funcionaba bien utilizando la anotación JSF @ManagedBean.

Bueno, Weld / CDI no funciona de la misma manera. Mi opinión es que cuando se utiliza la inyección para obtener una referencia a un bean, lo que se obtiene es en mayoría de los casos un objeto proxy. Este objeto proxy subclases bean y omite los métodos para implementar la delegación. Y esto introduce algunas restricciones en la lata de proxy clases CDI.

El CDI especificación expresa así:

  

5.4.1. tipos de frijol Unproxyable

     

Algunos tipos de frijol legales no puede ser   aproximada por el contenedor:

     
      
  • clases que no tienen un constructor no privada sin   parámetros,
  •   
  • clases que son declaradas final o tienen métodos finales,
  •   
  • tipos primitivos,
  •   
  • y matrices de tipos.
  •   
     

Si un punto de inyección cuya declaró   tipo no puede ser aproximado por la   resuelve recipiente a un bean con una   alcance normal, el recipiente   detecta automáticamente el problema y   lo trata como un problema de implementación.

Mi sugerencia sería que los métodos no final.

Referencias

  • CDI Especificación
    • Sección 5.4. "Proxies de cliente"
    • Sección 5.4.1 "tipos de frijol Unproxyable"
    • Sección 6.3. "Ámbitos normales y pseudo-ámbitos"

Otros consejos

Estoy en el proceso de migración de los granos de JSF Managed al CDI logró granos, y me acaba de confirmar que estoy en condiciones de uso super con éxito en un grano descendiente CDI (con 'costumbre' calificador @Descendant) que 'se extiende' un bean antepasado CDI (con @Default calificador).

CDI ancestro de frijoles con @Default calificador:

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

frijol antepasado tiene la siguiente:

@PostConstruct
protected void init() {

CDI descendiente de frijoles con @Descendant calificador:

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

frijol Descendiente tiene la siguiente:

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

he tenido que añadir / uso super.init (), ya que los métodos del bean ancestro CDI estaban criando NullPointerException, ya @PostConstruct del ancestro frijol no se ejecuta en el frijol CDI @Descendant.

He visto / oído / leído que es recomendable utilizar @PostConstruct en lugar de Método constructor cuando se utiliza CDI, por lo que el constructor del antecesor de frijol tenía la lógica 'inicialización', y el constructor del antecesor de frijol se invoca automáticamente / ejecutada cuando se utiliza JSF habas administrado.

Debido respuesta aceptada es correcta pero incompleta creo que puedo añadir mi granito de arena sólo para los futuros lectores.

El problema que se encontró con OP se pueden resolver de dos maneras:

  1. Al eliminar la palabra clave final de métodos y clase en sí
  2. Marcado tales "clase unproxyable" con @Singleton o @Dependent pseudo-alcance (por supuesto si tiene sentido). Se va a funcionar porque CDI no crea un objeto proxy para los granos de seudo con ámbito.

En el caso de uso OP se recomienda el segundo enfoque en mi humilde opinión, como controladores sin duda se pueden marcar como simple.

Esperamos que ayude a alguien

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top