Geertjan's Blog

  • September 11, 2009


Geertjan Wielenga
Product Manager
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;
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> {
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();
CountryBean bean2 = new CountryBean();
bean2.setFood("fish & chips");
} else {
for (CountryBean persistedBean : coll) {
//Create a new bean for each persisted bean:
CountryBean bean = new CountryBean();
return true;
protected Node createNodeForKey(final CountryBean countryBean) {
AbstractNode countryNode = new AbstractNode(Children.LEAF) {
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Set set = sheet.createPropertiesSet();
set.put(new FoodProperty(countryBean));
return sheet;
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();
public void setValue(String t) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
try {
InstanceDataObject.create(DataFolder.findFolder(FileUtil.getConfigFile("Services")), bean.getName(), bean, null);
} catch (IOException 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:

Join the discussion

Comments ( 3 )
  • Jesse Glick Friday, September 11, 2009

    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.

  • Geertjan Wielenga Friday, September 11, 2009

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

  • Jesse Glick Monday, September 14, 2009

    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.

Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.