1 2 Previous Next 17 Replies Latest reply on Oct 27, 2007 5:19 AM by alesj

    annotations on properties declared in interfaces

    aloubyansky

      If an interface declares a property and an implementation class has annotations on getter/setter, those annotations are not seen using org.jboss.beans.info.spi API. Is this a bug?

      An example could be
      class org.jboss.metadata.ejb.jboss.JBoss50DTDMetaData
      property enterpriseBeans
      declared by interface IEnterpriseBeanMetaData

      If I add @XmlElement on enterpriseBeans' setter, property.getUnderlyingAnnotation(XmlElement.class) will return null.
      property.getBeanInfo() returns org.jboss.metadata.ejb.jboss.JBoss50DTDMetaData.

        • 1. Re: annotations on properties declared in interfaces

          If you are saying what I think you're saying then yes, but I can't reproduce it?

          I created a test that shows it is picking up the annotations from the implementation class
          not the interface (which is correct).

          https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/container/src/tests/org/jboss/test/beaninfo/support/BeanInfoAnnotatedGetterAndSetterWithInterface.java

          92 DEBUG [BeanInfoUnitTestCase] Checking annotations for something expected: [AnnotationValueImpl@1f26605{name=org.jboss.test.beaninfo.suppo
          rt.BeanInfoAnnotation1}] actual=[AnnotationValueImpl@587c94{name=org.jboss.test.beaninfo.support.BeanInfoAnnotation1}]
          92 DEBUG [BeanInfoUnitTestCase] testBeanAnnotatedGetterAndSetterWithInterface took 92ms
          


          Perhaps you can create a test in the container project that shows what you are seeing?

          • 2. Re: annotations on properties declared in interfaces

            NOTE: Fundamentally, this is using java.lang.Class.getDeclaredMethods()
            and repeating for all super classes and finally matching the total set
            using getters and setters.

            Try doing YourClass.class.getDeclaredMethods() followed by super classes
            and see what it says, or alternatively use BeanInfo.getMethods() to see
            the whole thing.

            • 3. Re: annotations on properties declared in interfaces
              wolfc

              There is something wicked in this corner. If I remove EnterpriseBeanMetaData.getEnterpriseBeansMetaData() the beans info SPI will throw this at me:

              org.jboss.xb.binding.JBossXBException: Failed to parse source: file:/home/carlo/work/metadata/target/eclipse-classes/org/jboss/test/metadata/ejb/EjbJar3xEverything_testEverything.xml@8,26
               at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.parse(SaxJBossXBParser.java:194)
               at org.jboss.xb.binding.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:139)
               at org.jboss.test.metadata.javaee.JBossXBTestDelegate.unmarshal(JBossXBTestDelegate.java:150)
               at org.jboss.test.metadata.javaee.AbstractJavaEEMetaDataTest.unmarshal(AbstractJavaEEMetaDataTest.java:196)
               at org.jboss.test.metadata.javaee.AbstractJavaEEMetaDataTest.unmarshal(AbstractJavaEEMetaDataTest.java:152)
               at org.jboss.test.metadata.javaee.AbstractJavaEEMetaDataTest.unmarshal(AbstractJavaEEMetaDataTest.java:118)
               at org.jboss.test.metadata.ejb.EjbJar3xEverythingUnitTestCase.unmarshal(EjbJar3xEverythingUnitTestCase.java:91)
               at org.jboss.test.metadata.ejb.EjbJar3xEverythingUnitTestCase.testEverything(EjbJar3xEverythingUnitTestCase.java:98)
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
               at java.lang.reflect.Method.invoke(Method.java:585)
               at junit.framework.TestCase.runTest(TestCase.java:154)
               at junit.framework.TestCase.runBare(TestCase.java:127)
               at junit.framework.TestResult$1.protect(TestResult.java:106)
               at junit.framework.TestResult.runProtected(TestResult.java:124)
               at junit.framework.TestResult.run(TestResult.java:109)
               at junit.framework.TestCase.run(TestCase.java:118)
               at junit.framework.TestSuite.runTest(TestSuite.java:208)
               at junit.framework.TestSuite.run(TestSuite.java:203)
               at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
               at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
               at junit.framework.TestResult.runProtected(TestResult.java:124)
               at junit.extensions.TestSetup.run(TestSetup.java:23)
               at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
               at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
              Caused by: java.lang.RuntimeException: Unable to determine right PropertyInfo on AbstractBeanInfo@16e1eea8{name=org.jboss.metadata.ejb.spec.SessionBeanMetaData classInfo= properties=[interceptorBinding, removeMethods, messageDestinationReferences, postConstructs, stateless, ejbReferences, id, home, ejbJarMetaData, preDestroys, persistenceContextRefs, environmentEntries, ejbName, jndiEnvironmentRefsGroup, persistenceUnitRefs, class, entity, methodPermissions, remote, CMT, BMT, ejbClass, securityRoleRefs, initMethods, session, resourceReferences, aroundInvokes, descriptionGroup, containerTransactions, assemblyDescriptor, transactionType, local, stateful, postActivates, localHome, businessLocals, resourceEnvironmentReferences, sessionType, messageDriven, name, ejbLocalReferences, prePassivates, serviceEndpoint, securityIdentity, key, mappedName, businessRemotes, serviceReferences, timeoutMethod, enterpriseBeansMetaData, enterpriseBeansMetaData, excludeList] methods=[setEjbName, hashCode, getBusinessRemotes, setBusinessRemotes, setHome, getMethodPermissions, setPostActivates, getTransactionType, setTimeoutMethod, getPersistenceUnitRefs, getPrePassivates, setMappedName, setEjbClass, getKey, getBusinessLocals, getTimeoutMethod, setAroundInvokes, setDescriptionGroup, getEjbName, getServiceEndpoint, getPreDestroys, getAssemblyDescriptor, getResourceReferenceByName, wait, wait, wait, setJndiEnvironmentRefsGroup, notify, isCMT, getEnvironmentEntries, isEntity, setRemoveMethods, getEjbReferenceByName, getMethodTransactionType, getMethodTransactionType, getResourceEnvironmentReferences, getServiceReferenceByName, setServiceEndpoint, getInitMethods, setPrePassivates, setId, getEjbLocalReferences, setSecurityIdentity, getSessionType, setSecurityRoleRefs, getHome, getExcludeList, isStateful, isStateless, setInitMethods, isBMT, getName, getResourceEnvironmentReferenceByName, setBusinessLocals, getPostActivates, getLocalHome, isMessageDriven, getMappedName, getPostConstructs, clone, getEnvironmentEntryByName, merge, merge, merge, getEjbReferences, getResourceReferences, getEjbLocalReferenceByName, getMessageDestinationReferenceByName, setEnterpriseBeansMetaData, setEnterpriseBeansMetaData, getDescriptionGroup, setTransactionType, getSecurityIdentity, getAroundInvokes, getServiceReferences, equals, getRemote, setSessionType, getId, setLocalHome, getClass, toString, getPersistenceContextReferenceByName, setRemote, getLocal, getEjbJarMetaData, getContainerTransactions, notifyAll, getRemoveMethods, getPersistenceUnitReferenceByName, setName, setLocal, getPersistenceContextRefs, getSecurityRoleRefs, getJndiEnvironmentRefsGroup, isSession, getMessageDestinationReferences, getEjbClass, getInterceptorBinding] constructors=[] events=} by name: enterpriseBeansMetaData
              at org.jboss.metadata.ejb.spec.SessionBeanMetaData.enterpriseBeansMetaData
              at org.jboss.metadata.ejb.spec.EjbJar30MetaData.enterpriseBeans
              at org.jboss.metadata.ejb.spec.EjbJar30MetaData
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.rethrowWithLocation(JBossXBNoSchemaBuilder.java:1806)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createRootElementBinding(JBossXBNoSchemaBuilder.java:285)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createRootElements(JBossXBNoSchemaBuilder.java:260)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.build(JBossXBNoSchemaBuilder.java:184)
               at org.jboss.xb.builder.JBossXBBuilder.build(JBossXBBuilder.java:102)
               at org.jboss.test.metadata.javaee.AbstractJavaEEMetaDataTest$1.resolve(AbstractJavaEEMetaDataTest.java:238)
               at org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.startElement(SundayContentHandler.java:302)
               at org.jboss.xb.binding.parser.sax.SaxJBossXBParser$DelegatingContentHandler.startElement(SaxJBossXBParser.java:412)
               at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
               at org.apache.xerces.xinclude.XIncludeHandler.startElement(Unknown Source)
               at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
               at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source)
               at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
               at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
               at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
               at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
               at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
               at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
               at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
               at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.parse(SaxJBossXBParser.java:190)
               ... 29 more
              Caused by: java.lang.IllegalArgumentException: Unable to determine right PropertyInfo on AbstractBeanInfo@16e1eea8{name=org.jboss.metadata.ejb.spec.SessionBeanMetaData classInfo= properties=[interceptorBinding, removeMethods, messageDestinationReferences, postConstructs, stateless, ejbReferences, id, home, ejbJarMetaData, preDestroys, persistenceContextRefs, environmentEntries, ejbName, jndiEnvironmentRefsGroup, persistenceUnitRefs, class, entity, methodPermissions, remote, CMT, BMT, ejbClass, securityRoleRefs, initMethods, session, resourceReferences, aroundInvokes, descriptionGroup, containerTransactions, assemblyDescriptor, transactionType, local, stateful, postActivates, localHome, businessLocals, resourceEnvironmentReferences, sessionType, messageDriven, name, ejbLocalReferences, prePassivates, serviceEndpoint, securityIdentity, key, mappedName, businessRemotes, serviceReferences, timeoutMethod, enterpriseBeansMetaData, enterpriseBeansMetaData, excludeList] methods=[setEjbName, hashCode, getBusinessRemotes, setBusinessRemotes, setHome, getMethodPermissions, setPostActivates, getTransactionType, setTimeoutMethod, getPersistenceUnitRefs, getPrePassivates, setMappedName, setEjbClass, getKey, getBusinessLocals, getTimeoutMethod, setAroundInvokes, setDescriptionGroup, getEjbName, getServiceEndpoint, getPreDestroys, getAssemblyDescriptor, getResourceReferenceByName, wait, wait, wait, setJndiEnvironmentRefsGroup, notify, isCMT, getEnvironmentEntries, isEntity, setRemoveMethods, getEjbReferenceByName, getMethodTransactionType, getMethodTransactionType, getResourceEnvironmentReferences, getServiceReferenceByName, setServiceEndpoint, getInitMethods, setPrePassivates, setId, getEjbLocalReferences, setSecurityIdentity, getSessionType, setSecurityRoleRefs, getHome, getExcludeList, isStateful, isStateless, setInitMethods, isBMT, getName, getResourceEnvironmentReferenceByName, setBusinessLocals, getPostActivates, getLocalHome, isMessageDriven, getMappedName, getPostConstructs, clone, getEnvironmentEntryByName, merge, merge, merge, getEjbReferences, getResourceReferences, getEjbLocalReferenceByName, getMessageDestinationReferenceByName, setEnterpriseBeansMetaData, setEnterpriseBeansMetaData, getDescriptionGroup, setTransactionType, getSecurityIdentity, getAroundInvokes, getServiceReferences, equals, getRemote, setSessionType, getId, setLocalHome, getClass, toString, getPersistenceContextReferenceByName, setRemote, getLocal, getEjbJarMetaData, getContainerTransactions, notifyAll, getRemoveMethods, getPersistenceUnitReferenceByName, setName, setLocal, getPersistenceContextRefs, getSecurityRoleRefs, getJndiEnvironmentRefsGroup, isSession, getMessageDestinationReferences, getEjbClass, getInterceptorBinding] constructors=[] events=} by name: enterpriseBeansMetaData
               at org.jboss.beans.info.plugins.NestedPropertyInfo.getUnderlyingAnnotation(NestedPropertyInfo.java:201)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateType(JBossXBNoSchemaBuilder.java:1041)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:695)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:683)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateTypeBinding(JBossXBNoSchemaBuilder.java:462)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.resolveTypeBinding(JBossXBNoSchemaBuilder.java:421)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateType(JBossXBNoSchemaBuilder.java:1002)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:695)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:683)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateCollection(JBossXBNoSchemaBuilder.java:626)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateTypeBinding(JBossXBNoSchemaBuilder.java:453)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.resolveTypeBinding(JBossXBNoSchemaBuilder.java:421)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateType(JBossXBNoSchemaBuilder.java:1526)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:695)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:683)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateTypeBinding(JBossXBNoSchemaBuilder.java:462)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.resolveTypeBinding(JBossXBNoSchemaBuilder.java:421)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createElementBinding(JBossXBNoSchemaBuilder.java:300)
               at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createRootElementBinding(JBossXBNoSchemaBuilder.java:280)
               ... 47 more

              I would expect the annotation on the setter to be returned.

              • 4. Re: annotations on properties declared in interfaces

                The NestedPropertyInfo is used when there is more than one setter for the property
                and no getter to resolve which one should get used.

                Instead it tries to guess (using isAssignable) at runtime based on what you pass to the api
                If the parameter is not assignable to any, it throws that exception.

                e.g.

                public void setSomething(Collection c);
                public void setSomething(String s);
                


                is "something' a Collection or a String? The answer is it depends what "value" you
                pass to PropertyInfo.set(Object bean, Object value).

                • 5. Re: annotations on properties declared in interfaces
                  wolfc

                  Just what I thought, both problems are related because of generics.
                  This construct breaks the lot:

                  interface MyInterface<X>
                  {
                   void setA(X x);
                  }
                  
                  class Something implements MyInterface<SomethingElse>
                  {
                   @MyAnnotation
                   void setA(SomethingElse x) { }
                  }


                  • 6. Re: annotations on properties declared in interfaces
                    aloubyansky

                     

                    "adrian@jboss.org" wrote:
                    NOTE: Fundamentally, this is using java.lang.Class.getDeclaredMethods()
                    and repeating for all super classes and finally matching the total set
                    using getters and setters.

                    Try doing YourClass.class.getDeclaredMethods() followed by super classes
                    and see what it says, or alternatively use BeanInfo.getMethods() to see
                    the whole thing.


                    I'll try that. With the introduction of interfaces in metadata API we have a lot of errors because now property infos are reflect the interfaces and not the implementation classes, despite the fact that getProperty(name) is called on the implementation class.

                    • 7. Re: annotations on properties declared in interfaces
                      aloubyansky

                      The following test which fails for me can be used to demonstrate the issue.

                      public void testMain() throws Exception
                       {
                       Configuration configuration = new PropertyConfiguration();
                       BeanInfo beanInfo = configuration.getBeanInfo(MyClass.class);
                       PropertyInfo property = beanInfo.getProperty("property");
                       assertEquals("java.lang.String", property.getType().getName());
                       }
                      
                       public static interface MyInterface<T extends Object>
                       {
                       T getProperty();
                       void setProperty(T value);
                       }
                      
                       public static class MyClass implements MyInterface<String>
                       {
                       public String getProperty()
                       {
                       return null;
                       }
                      
                       public void setProperty(String value)
                       {
                       }
                       }


                      The result is
                      junit.framework.ComparisonFailure: expected:<...String> but was:<...Object>


                      Is this expected? I suspect others may not necessarily get the same result on their machaines otherwise I wouldn't see new ejb tests added in the metadata project?

                      • 8. Re: annotations on properties declared in interfaces
                        aloubyansky

                        The JVM I used

                        java version "1.5.0_08"
                        Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_08-b03)
                        Java HotSpot(TM) Client VM (build 1.5.0_08-b03, mixed mode, sharing)


                        For Carlo with the update 12 the test passes.

                        • 9. Re: annotations on properties declared in interfaces
                          aloubyansky

                          It still fails with the update 12 and 13 on windows.

                          • 10. Re: annotations on properties declared in interfaces
                            starksm64

                            On my windows box i'm also seeing failures. we definitely have a comparison issues that we to drill into and resolve.

                            • 11. Re: annotations on properties declared in interfaces
                              wolfc

                              MethodInfoImpl.equals doesn't take returnType into account.
                              This is just the first step.

                              • 12. Re: annotations on properties declared in interfaces
                                starksm64

                                The problem is in the AbstractBeanInfoFactory.getMethods(ClassInfo classInfo). The ClassInfo.getDeclaredMethods returns 4 methods:

                                [ReflectMethodInfoImpl@691177{name=setProperty[ReflectClassInfoImpl@1f99eea{name=java.lang.String}] return=void}, ReflectMethodInfoImpl@13043d2{name=setProperty[ReflectClassInfoImpl@1b4c1d7{name=java.lang.Object}] return=void}, ReflectMethodInfoImpl@221e9e{name=getProperty[] return=ReflectClassInfoImpl@1b4c1d7{name=java.lang.Object}}, ReflectMethodInfoImpl@83e1e{name=getProperty[] return=ReflectClassInfoImpl@1f99eea{name=java.lang.String}}

                                but the result set only contains 3:
                                [ReflectMethodInfoImpl@1e184cb{name=getProperty[] return=ReflectClassInfoImpl@bb494b{name=java.lang.Object}}, ReflectMethodInfoImpl@d1e233{name=setProperty[ReflectClassInfoImpl@bb494b{name=java.lang.Object}] return=void}, ReflectMethodInfoImpl@7976c1{name=setProperty[ReflectClassInfoImpl@13043d2{name=java.lang.String}] return=void}]

                                The String getProperty() method was dropped as it was seen to be equals to the Object getProperty method. The MethodInfoImpl equals/hashCode need to consider name, parameters and return type.

                                • 13. Re: annotations on properties declared in interfaces
                                  wolfc

                                  Second bridge methods should be ignored.
                                  That should fix all issues.

                                  • 14. Re: annotations on properties declared in interfaces
                                    aloubyansky

                                    I've added the test to
                                    package org.jboss.test.beaninfo.test;
                                    public class BeanInfoUnitTestCase extends AbstractBeanInfoTest
                                    public void testGenericInterfaceImpl() throws Throwable

                                    1 2 Previous Next