@ConvertAsJavaBean

A first (and potentially wrong) experiment with the new 6.8 @ConvertAsJavaBean annotation.

I annotate my business object ("CountryBean", which has a name property to hold the name of the country and a food property to hold the country's national food, e.g., "Germany/sauerkraut") with the new annotation:

import org.netbeans.api.settings.ConvertAsJavaBean;

@ConvertAsJavaBean
public class CountryBean {
    String name;
    String food;
    public String getFood() {return food;}
    public void setFood(String food) {this.food = food;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
}

I then use the country name to set the display name of the node. I use the country food to set a property in the property sheet. When the property changes, a new ".settings" file is created in the "Services" folder, which is a folder that is available to "Lookup.getDefault()", where we retrieve our persisted bean:

public class CountryChildFactory extends ChildFactory<CountryBean> {

    @Override
    protected boolean createKeys(List<CountryBean> list) {
        Collection<? extends CountryBean> coll = Lookup.getDefault().lookupAll(CountryBean.class);
        if (coll.isEmpty()) {
            //Create some dummy data:
            CountryBean bean1 = new CountryBean();
            bean1.setName("Germany");
            bean1.setFood("sauerkraut");
            list.add(bean1);
            CountryBean bean2 = new CountryBean();
            bean2.setName("England");
            bean2.setFood("fish & chips");
            list.add(bean2);
        } else {
            for (CountryBean persistedBean : coll) {
                //Create a new bean for each persisted bean:
                CountryBean bean = new CountryBean();
                bean.setName(persistedBean.getName());
                bean.setFood(persistedBean.getFood());
                list.add(bean);
            }
        }
        return true;
    }

    @Override
    protected Node createNodeForKey(final CountryBean countryBean) {
        AbstractNode countryNode = new AbstractNode(Children.LEAF) {
            @Override
            protected Sheet createSheet() {
                Sheet sheet = super.createSheet();
                Set set = sheet.createPropertiesSet();
                set.put(new FoodProperty(countryBean));
                sheet.put(set);
                return sheet;
            }
        };
        countryNode.setDisplayName(countryBean.getName());
        return countryNode;
    }

    private class FoodProperty extends PropertySupport.ReadWrite<String> {

        private final CountryBean bean;

        public FoodProperty(CountryBean bean) {
            super("firstBean", String.class, "Favorite food", "Displays favorite food of country");
            this.bean = bean;
        }

        public String getValue() throws IllegalAccessException, InvocationTargetException {
            return bean.getFood();
        }

        @Override
        public void setValue(String t) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            bean.setFood(t);
            try {
                InstanceDataObject.create(DataFolder.findFolder(FileUtil.getConfigFile("Services")), bean.getName(), bean, null);
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
        
    }
    
}

Here's what's in the "Services" folder, i.e., the magical folder available to "Lookup.getDefault()" and where I write to when the user changes the food property in the property sheet:

Comments:

Don't really recommend you use this annotation. Probably better to just store information using NbPreferences. Use of \*.settings files generally is discouraged for new code; they are still used for persisting TopComponent's because no one has bothered to write a saner system. The Services folder is also semideprecated, really only used for JavaHelp and MIMEResolver registrations at this point.

Could use PersistedBean.clone() if it were Cloneable [sic].

PropertySupport.Reflection can be useful on conventionally-structured beans.

Posted by Jesse Glick on September 10, 2009 at 11:40 PM PDT #

But it's a brand new annotation. How can it make sense to recommend to not use a brand new annotation?

Posted by Geertjan Wielenga on September 11, 2009 at 04:35 AM PDT #

Just because it's there does not mean you have to use it. If you are committed to storing \*.settings files - either because some infrastructure like the Window System requires it, or because you find this style especially convenient for your use case - @ConvertAsJavaBean and @ConvertAsProperties are the most sensible options, with @ConvertAsJavaBean being most appropriate for fairly complex formats involving nested trees of beans that could take advantage of the features of the XML bean serializer.

In my experience (e.g. implementing project groups) it can be just as straightforward to persist a set of simple objects using NbPreferences, whether using one preferences node per object or representing many objects within one node using key names. You have to explicitly write code to get and put properties when model objects are loaded or stored, but this is typically very simple code; and it is easy to make changes to the format in the future as you are in full control of what is stored where and how. In other words, my judgment would be that explicit key/value-based persistence may be a little more work to prototype as compared to using settings files, but will be easier to comprehend and maintain in the long run.

Posted by Jesse Glick on September 14, 2009 at 01:34 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
12
13
14
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today