This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
Change API to allow creating PropertySheets by the use of Annotations. There’s a lot of boilerplate code if you want to display PropertySheets for a Bean in NetBeans. You need to create a nodewrapper and write code to create the PropertySheet. There are some classes like the BeanNode to make things easier, but the functionality is very basic, unless you want to write BeanInfo classes. I’ve got a lot of beans for XML binding in my projects and I never liked the concept of BeanInfo classes, because you have to keep two classes in sync, so I decided to use a different approach. BeanInfo classes are carrying MetaInformation for the Beans and I guess that’s rather a job for Annotations. So it would be best to create a set of Annotations to provide the same MetaInformation in a more appropriate way. I have implemented my own solution and it works fine; I would like to contribute this as a patch if anyone's interested. Proposed Patch adds these classes: * AnnotatedBeanNode: // same as BeanNode with the ability to handle the annotations * AnnotationIntrospector: // AnnotationIntrospector creates generic BeanInfo objects from Annotations when BeanDescriptorAnnotation is present, calls Introspector when no annotation is present Uses these annotations: * BeanDescriptorAnnotation * BeanMethodAnnotation * EventSetDescriptorAnnotation * FeatureDescriptorAnnotation * MethodDescriptorAnnotation * PropertyDescriptorAnnotation First there is a FeatureDescriptorAnnotation that holds the elements shared by all Descriptors. Annotations don’t support inheritance, so this is used as a MetaAnnotation (@Target({ ElementType.ANNOTATION_TYPE})) for the other Descriptors. I created default values for the elements, so the elements do not need to be set in an annotation explicitely. If, for example, the AnnotationIntrospector finds DEFAULT_NAME as name() it will use reflection to set the default name of the Descriptor. 8<——————————————>8 @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.ANNOTATION_TYPE}) public @interface FeatureDescriptorAnnotation { public static String DEFAULT_NAME = "Default_Name"; public static String DEFAULT_DISPLAY_NAME = "Default_Display_ Name"; public static String DEFAULT_DESCRIPTION = "Default_Description"; String displayName() default DEFAULT_DISPLAY_NAME; String name() default DEFAULT_NAME; String shortDescription() default DEFAULT_DESCRIPTION; boolean expert() default false; boolean hidden() default false; boolean preferred() default false; } 8<——————————————>8 Next I needed a BeanDescriptor-equivalent, that can be used to mark up Beans for the AnnotationIntrospector. The PropertyDescriptor is split up into two parts. SimpleProperties refers to properties that only use default methods, names, etc. This will cover most cases, so the code to annotate a bean is very reduced. For Properties with more advanced settings there is the customizedProperties Array. 8<——————————————>8 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface BeanDescriptorAnnotation { public static String DEFAULT_CUSTOMIZER = "Default_Customizer"; FeatureDescriptorAnnotation featureDescriptorAnnotation() default @FeatureDescriptorAnnotation; String customizerClassName() default DEFAULT_CUSTOMIZER; PropertyDescriptorAnnotation [] customizedProperties() default {}; String [] simpleProperties() default {}; } 8<——————————————>8 Next there is the PropertyDescriptorAnnotation ( and the MethodDescriptorAnnotation, ParameterDescriptorAnnotation,EventSetDescriptorAnnotation but I won’t show those now ). It can be used either in the customizedProperties Array, or as a marker for Fields, which would make the code look cleaner: 8<——————————————>8 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE}) public @interface PropertyDescriptorAnnotation { public static String DEFAULT_PROPERTY_EDITOR = "Default_Property_Editor"; public static String DEFAULT_GETTER = "Default_Getter"; public static String DEFAULT_SETTER = "Default_Setter"; FeatureDescriptorAnnotation featureDescriptorAnnotation() default @FeatureDescriptorAnnotation; String propertyEditorClassName() default DEFAULT_PROPERTY_EDITOR; BeanMethodAnnotation readMethod() default @BeanMethodAnnotation(name=DEFAULT_GETTER); BeanMethodAnnotation writeMethod() default @BeanMethodAnnotation(name=DEFAULT_SETTER) ; boolean bound() default false; boolean constrained() default false; } 8<——————————————>8 At last we need an Introspector, that can retrofit those into a generic BeanInfo Here is for example how the simpleProperties are converted to PropertyDescriptors: 8<——————————————>8 String [] simpleProperties = beanAnnotation.simpleProperties(); if (simpleProperties!=null){ for (int i = 0; i < simpleProperties.length; i++) { try { PropertyDescriptor propertyDescriptor=new PropertyDescriptor(simpleProperties[i],beanClass); propertyDescriptors.add(propertyDescriptor ); } catch (IntrospectionException ex) { ex.printStackTrace(); } } } 8<——————————————>8 An example illustrating how a typical use would look like: 8<————– BaseBean.java—————–>8 @BeanDescriptorAnnotation( simpleProperties = {"Text","ReportElement"}) public class StaticText extends BaseBean { 8<——————————————————->8 nested elements 8<———From ReportElement.java—————–>8 @BeanDescriptorAnnotation( featureDescriptorAnnotation=@FeatureDescriptorAnnotation( displayName= "Generic"),simpleProperties = {"X","Y","Width","Height"}) public class ReportElement extends org.netbeans.modules.schema2beans.BaseBean 8<——————————————————->8 Results can be seen here: http://eppleton.com/blog/?p=103 I can upload a Mercurial patch if it's considered worth testing. Sorry for the length of this report. I've created the patch for nodes API, but utilities might be considered since the BeanInfo creation has been moved there.
displayName() and shortDescription() are not good as is since these need to be localizable in general. String customizerClassName() should be Class<? extends Customizer> customizerClass(). Property names should follow Beans conventions, e.g. "reportElement", not "ReportElement". I doubt we really need to implement the full range of options in the Beans spec. Nearly everyone would only use simple properties with default getter/setter names and the occasional customizer. For use in NetBeans there is no need for bean context, method descriptors, etc. I'm sure you could find uses for all these things in e.g. http://commons.apache.org/beanutils/ but we would not need them. Anyway I am dubious that there is much value here for module development. Assuming you have the bean written, your proposal would let me add a few annotations with fixed values, followed by creation of a BeanNode (which we generally discourage the use of). But it is already pretty easy to make a Node with whatever properties you want: AbstractNode n = ...; n.getPropertySheet().add(new PropertySupport.ReadWrite<String>("foo", String.class, NbBundle..., NbBundle...) { public String getValue() {...} public void setValue(String v) {...} }); which is much more flexible as you can choose to include certain properties or not at runtime, add a Reset to Default method, make the short description vary according to runtime criteria, create different Sheet's, etc. Generally annotations are useful for 1. Marking something about the nature of code that should be checked by static analyzers, e.g. @NonNull as a workaround for a deficient type system in the language. 2. Express a cross-cutting concern that can be used by a container, e.g. transaction attributes in EJBs. 3. Indicating declarative registration of objects that could be extracted using an annotation processor to avoid class loading or implement inversion of control. But they should not be used for routine procedures which can be done in a straightforward manner using plain Java code.
Jesse, thanks for the fast feedback! first off, I didn't know that the use of BeanNode is discouraged, and I didn't yet find information about that. But I assume there are not many usecases where you would like to use BeanNode anyway. I agree on that. Actually this is the reason why I wrote this enhancement. You can declare the metadata very efficiently, and most of the time one line of code is enough to expose the properties as you wish. This is extremely helpful when you have a large cllection of domain obejects e.g. xml binding beans. This is often the case in RPC development, especially when you are porting an application. It simplifies plugging large collections of beans into the NetBeans platform. Maybe it won't be as useful for developing the IDE itself, but it definitely simplified RCP development for me. I disagree with you regarding the use of annotations. The declarative nature of annotations is perfect for this kind of job. I would even say that this use of annotations is exactly what annotations are meant for. See JSR 175 and the sun java language guide: "There has been a growing trend towards annotating fields, methods, and classes as having particular attributes that indicate they should be processed in special ways by development tools, deployment tools, or run-time libraries. We call such annotations metadata. For example, the JavaBeansTM architecture introduced various stylistic naming patterns (such as getFoo/setFoo method names) that could be used to indicate that particular methods were used for accessing properties, for registering event handlers, and so forth. [...] In light of this situation, it seems appropriate to add to the Java programming language a means of associating arbitrary attribute information with particular classes/interfaces/methods/fields." [ http://jcp.org/en/jsr/detail?id=175 ] "Other APIs require “side files” to be maintained in parallel with programs. For example JavaBeans requires a BeanInfo class to be maintained in parallel with a bean, and Enterprise JavaBeans (EJB) requires a deployment descriptor. It would be more convenient and less error-prone if the information in these side files were maintained as annotations in the program itself." [ http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html ] The standard method offers more flexibility and internationalization, agreed. But the intention of the proposal is not to replace the standard mechanism, but to make it easy to add Propertysheets to large collections of pojos.
Likely inappropriate for NB IDE. CCing Tim as it might be a useful addition to platformx.
Created attachment 57955 [details] updated patch for XYZoom
Sorry, I attached this patch to the wrong issue!
Generally I agree there is a lot of boilerplate code everyone with a hierarchy of beans they want to wrap in nodes has to write - particularly when it comes to implementing properties; it would also be nice to reduce the number of classes one needs to write - all those PropertySupport.ReadWrite subclasses certainly take up memory (there is PropertySupport.Reflection, but it's somewhat broken - it doesn't actually use BeanInfos). The localization issue could probably be handled fairly easily by providing a bundle key instead of an actual display name, and some convention for where it should be looked for. Another issue worth addressing in a work like this is making it easy to annotate a getter that returns a collection that should be turned into child nodes; in an ideal world, creating a hierarchy of nodes ought to be as simple as a few annotations on a domain object that you pass to some sort of node factory. If you'd be interested in contributing it to the http://platformx.netbeans.org incubator, we'd be happy to host it there - which means there would be platform builds that include these modules, and anyone who wants it can get it and build against it. It's basically a project for contributed extensions to NetBeans that are, which not necessary to the IDE, are useful for building RCP apps. The project is still getting off the ground. Interested?
Tim, thanks for your feedback, especially the hints on how to support internationalization. Although I think in many cases property editor internationalization is odd ( think of property editors in Matisse :-) ), I see that it might be useful in other cases and I'll try to address it . From what I read on the platformx page and wiki contributing it there would be a good solution, and I'm willing to do that. Is there already a repository?
Ok, please incubate in platformx workspace. Come back when ready for API review. Thanks.
It's bin a long time, since I reported this, but the project is available at Kenai now for anyone interested: http://kenai.com/projects/beaninfo-annotations Currently doesn't compile due to #184694
Should not keep this open on netbeans.org if it is hosted elsewhere; use the issue tracker on the Kenai project for any problems or suggestions.
When I understand him right, he will import his project into the netbeans version control once it compiles, which depended on 184694 and is solved now. So why is it resolved invalid? Don't want to offend, just understand. Regards Torsten
(In reply to comment #11) > When I understand him right, he will import his project into the netbeans > version control once it compiles, which depended on 184694 and is solved now. > So why is it resolved invalid? Don't want to offend, just understand. > > Regards > Torsten Hi Torsten, I'm currently hosting this project somewhere else, so I agree with Jesse that closing as invalid here (for NetBeans) is the right solution. If you like to check it out it compiles in 6.9 beta thanks to Jesse's tips. thanks for your interest --Toni