Hi, On Wed, Aug 26, 2015 at 4:28 PM, Remi Forax <remi.fo...@u-pem.fr> wrote: > IMO, it seems to be a bug of the CDI implementation, > as you said the method corresponding to the lambda body is synthetized so it > should be ignored by the CDI implementation, no ?
Yes I agree that might be another possibility. I'll bring this to the attention of the CDI and/or Weld people as well. Still, it's a somewhat sudden change and there are many CDI implementations out there. > BTW, it's the wrong list, lambdas are delivered so you should have use > core-lib-dev instead (in CC). core-lib-dev, hmm, who would have thought? But I'll keep it in mind for future messages. Thanks! Kind regards, Arjan Tijms > > cheers, > Rémi > > ----- Mail original ----- > De: "arjan tijms" <arjan.ti...@gmail.com> > À: lambda-...@openjdk.java.net > Envoyé: Mercredi 26 Août 2015 16:04:22 > Objet: U60 change makes annotations visible in synthesized methods, causes > CDI to see lambdas as observer methods > > Hi, > > I'm with the JSF EG/Mojarra team and we're seeing what looks like a > problematic regression in JDK8 u60. > > In a CDI extension we have the following observer method: > > public <T> void processBean(@Observes ProcessBean<T> event, > BeanManager beanManager) { > getAnnotation(beanManager, event.getAnnotated(), FacesDataModel.class) > .ifPresent(d -> > forClassToDataModelClass.put( > d.forClass(), > (Class<? extends DataModel<?>>) > event.getBean().getBeanClass() > ) > ); > } > > With u45 and below this will generate the following (decompiled the > class with javap -v -p -s -c) > > private void lambda$processBean$4(javax.enterprise.inject.spi.ProcessBean, > javax.faces.model.FacesDataModel); > descriptor: > (Ljavax/enterprise/inject/spi/ProcessBean;Ljavax/faces/model/FacesDataModel;)V > flags: ACC_PRIVATE, ACC_SYNTHETIC > Code: > stack=3, locals=3, args_size=3 > 0: aload_0 > 1: getfield #4 // Field > forClassToDataModelClass:Ljava/util/Map; > 4: aload_2 > 5: invokeinterface #57, 1 // InterfaceMethod > javax/faces/model/FacesDataModel.forClass:()Ljava/lang/Class; > 10: aload_1 > 11: invokeinterface #58, 1 // InterfaceMethod > javax/enterprise/inject/spi/ProcessBean.getBean:()Ljavax/enterprise/inject/spi/Bean; > 16: invokeinterface #59, 1 // InterfaceMethod > javax/enterprise/inject/spi/Bean.getBeanClass:()Ljava/lang/Class; > 21: invokeinterface #55, 3 // InterfaceMethod > java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; > 26: checkcast #45 // class java/lang/Class > 29: pop > 30: return > LineNumberTable: > line 110: 0 > line 111: 5 > line 112: 11 > line 110: 21 > LocalVariableTable: > Start Length Slot Name Signature > 0 31 0 this Lcom/sun/faces/cdi/CdiExtension; > 0 31 2 d Ljavax/faces/model/FacesDataModel; > > > U60 however generates the following: > > private void lambda$processBean$4(javax.enterprise.inject.spi.ProcessBean, > javax.faces.model.FacesDataModel); > descriptor: > (Ljavax/enterprise/inject/spi/ProcessBean;Ljavax/faces/model/FacesDataModel;)V > flags: ACC_PRIVATE, ACC_SYNTHETIC > Code: > stack=3, locals=3, args_size=3 > 0: aload_0 > 1: getfield #4 // Field > forClassToDataModelClass:Ljava/util/Map; > 4: aload_2 > 5: invokeinterface #57, 1 // InterfaceMethod > javax/faces/model/FacesDataModel.forClass:()Ljava/lang/Class; > 10: aload_1 > 11: invokeinterface #58, 1 // InterfaceMethod > javax/enterprise/inject/spi/ProcessBean.getBean:()Ljavax/enterprise/inject/spi/Bean; > 16: invokeinterface #59, 1 // InterfaceMethod > javax/enterprise/inject/spi/Bean.getBeanClass:()Ljava/lang/Class; > 21: invokeinterface #55, 3 // InterfaceMethod > java/util/Map.put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; > 26: checkcast #45 // class java/lang/Class > 29: pop > 30: return > LineNumberTable: > line 110: 0 > line 111: 5 > line 112: 11 > line 110: 21 > LocalVariableTable: > Start Length Slot Name Signature > 0 31 0 this Lcom/sun/faces/cdi/CdiExtension; > 0 31 1 event Ljavax/enterprise/inject/spi/ProcessBean; > 0 31 2 d Ljavax/faces/model/FacesDataModel; > RuntimeVisibleParameterAnnotations: > parameter 0: > 0: #79() > parameter 1: > > The difference is that the parameter annotation is made visible for > this synthesized method. The result is that CDI subsequently scans > this class and sees the synthesized method for the lambda as an > observer method, which is of course not the intention. In this > particular case it will result in a definition error: > > "Error occurred during deployment: Exception while loading the app : > > CDI definition failure: > > WELD-000409: Observer method for container lifecycle event > [[BackedAnnotatedMethod] > > private com.sun.faces.cdi.CdiExtension.lambda$processBean$4(@Observes > ProcessBean<Object>, FacesDataModel)] can only inject BeanManager.." > > I think that if the synthesized method happened to be a correct > observer method, e.g. for a no-parameter lambda or one that happens to > have the BeanManager as its first and only parameter, then CDI would > silently start to call this method in response to events, which too is > highly undesirable. > > Kind regards, > Arjan Tijms >