En utilisant CDI au lieu de @ManagedBean: UnproxyableResolutionException parce que super-classe n'a pas de constructeur sans args

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

  •  27-09-2019
  •  | 
  •  

Question

Je suis en train d'utiliser le CDI pour mon JSF / application Java EE. J'ai la hiérarchie des classes suivantes:

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

Lorsque je tente de déployer l'application sur GF 3.1, je reçois l'exception CDI / soudage suivant:

  

GRAVE: Exception lors du chargement du   app: WELD-001435 haricots scope normale   classe   com.web.AbstractCrudController   n'est pas proxyable parce qu'il n'a pas   constructeur sans args.   org.jboss.weld.exceptions.UnproxyableResolutionException:   WELD-001435 normale scope classe haricot   com.web.AbstractCrudController   n'est pas proxyable parce qu'il n'a pas   constructeur sans 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.validateRIBean (Validator.java:148)           à org.jboss.weld.bootstrap.Validator.validateBeans (Validator.java:363)           à org.jboss.weld.bootstrap.Validator.validateDeployment (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 (EventsImpl.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.deployment.admin.DeployCommand.execute (DeployCommand.java:351)           à com.sun.enterprise.v3.admin.CommandRunnerImpl 1.execute de $ (CommandRunnerImpl.java:360)           à com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:375)           à com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand (CommandRunnerImpl.java:1072)           à com.sun.enterprise.v3.admin.CommandRunnerImpl.access 1200 $ (CommandRunnerImpl.java:101)           à com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1221)           à com.sun.enterprise.v3.admin.CommandRunnerImpl $ ExecutionContext.execute (CommandRunnerImpl.java:1210)           à 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.service (ContainerMapper.java:234)           à com.sun.grizzly.http.ProcessorTask.invokeAdapter (ProcessorTask.java:824)           à com.sun.grizzly.http.ProcessorTask.doProcess (ProcessorTask.java:721)           à com.sun.grizzly.http.ProcessorTask.process (ProcessorTask.java:1014)           à com.sun.grizzly.http.DefaultProtocolFilter.execute (DefaultProtocolFilter.java:220)           à com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter (DefaultProtocolChain.java:135)           à com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:102)           à com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:88)           à com.sun.grizzly.http.HttpProtocolChain.execute (HttpProtocolChain.java:76)           à com.sun.grizzly.ProtocolChainContextTask.doCall (ProtocolChainContextTask.java:53)           à com.sun.grizzly.SelectionKeyContextTask.call (SelectionKeyContextTask.java:57)           à com.sun.grizzly.ContextTask.run (ContextTask.java:69)           à com.sun.grizzly.util.AbstractThreadPOOL $ Worker.doWork (AbstractThreadPool.java:530)           à com.sun.grizzly.util.AbstractThreadPool $ Worker.run (AbstractThreadPool.java:511)           à java.lang.Thread.run (Thread.java:637)

Même si j'ajoute un constructeur sans args à la classe de base, Weld se plaint toujours avec la même exception que la classe n'est pas proxyable parce qu'il a des méthodes finales. Pourquoi WELD me forcer à changer ma conception de classe? Tout fonctionnait bien en utilisant l'annotation JSF @ManagedBean.

J'apprécierait toute aide. Remercier, Theo

Était-ce utile?

La solution

  

Pourquoi WELD me forcer à changer ma conception de classe? Tout fonctionnait bien en utilisant l'annotation JSF @ManagedBean.

Eh bien, Weld / CDI ne fonctionne pas de la même façon. Je crois comprendre que lorsque vous utilisez l'injection pour obtenir une référence à un haricot, ce que vous obtenez est la plupart des cas un objet proxy. Cet objet proxy sous-classes bean et bloque les méthodes pour mettre en œuvre la délégation. Et cela introduit des restrictions sur les classes CDI peut proxy.

Les puts du CDI comme ceci:

  

5.4.1. types de haricots Unproxyable

     

Certains types de haricots juridiques ne peut pas être   approximé par le conteneur:

     
      
  • les classes qui ne disposent pas d'un constructeur non-privé sans   paramètres,
  •   
  • les classes qui sont déclarées méthodes finale ou finale ont,
  •   
  • les types primitifs,
  •   
  • et types tableau.
  •   
     

Si un point d'injection dont déclarée   type ne peut pas être mesurée par le   décide de conteneur à un haricot avec un   portée normale, le conteneur   détecte automatiquement le problème et   le traite comme un problème de déploiement.

Ma suggestion serait de rendre les méthodes non finale.

Références

  • CDI Spécification
    • Section 5.4. "Proxy client"
    • Section 5.4.1 "Types de haricots Unproxyable"
    • Section 6.3. "Portées normales et pseudo-champs d'application"

Autres conseils

Je suis en train de migrer de JSF géré les haricots au CDI a réussi les haricots, et je viens de confirmer que je suis en mesure d'utiliser super avec succès dans un bean CDI descendant (avec le qualificatif 'custom' @Descendant) qui 'étend' un ancêtre de grains de CDI (avec le qualificatif @default).

CDI ancêtre de haricot avec le qualificatif @default:

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

haricot ancêtre n'a le suivant:

@PostConstruct
protected void init() {

CDI descendant de haricot avec le qualificatif @Descendant:

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

haricot décroissant a le suivant:

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

Je devais ajouter / utiliser super.init (), parce que les méthodes de l'ancêtre de haricot CDI soulevaient NullPointerException, puisque @PostConstruct ancêtre de haricot n'est pas exécuté dans le haricot CDI @Descendant.

Je l'ai vu / entendu / lu qu'il est recommandé d'utiliser @PostConstruct au lieu de la méthode Constructor lors de l'utilisation CDI, avait donc la logique « d'initialisation », et a été automatiquement invoqué / exécuté le constructeur ancêtre haricot constructeur de l'ancêtre haricots lors de l'utilisation JSF gestion des haricots.

Parce que la réponse acceptée est correcte mais incomplète, je pense que je peux ajouter mes deux cents seulement pour les lecteurs futurs.

Le problème rencontré OP peut être résolu de deux manières:

  1. En supprimant mot-clé final de méthodes et se classe
  2. Marquage comme « classe unproxyable » avec pseudo-portée @Singleton ou @Dependent (bien sûr, s'il est logique). Il fonctionnera parce que le CDI ne crée pas un objet proxy pour les haricots scope pseudo.

Dans l'utilisation OP cas, la seconde à mon humble avis d'approche a été recommandée, car les contrôleurs peuvent certainement être marqués comme singletons.

it helps quelqu'un

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top