Skip to content

Bean properties

ljacqu edited this page Dec 10, 2016 · 9 revisions

ConfigMe allows you to use properties of a custom JavaBean class type. Let's look at an example:

Given the following JavaBean:

public class Country {
  private String name;
  private int population;

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }

  public int getPopulation() {
    return population;
  }
  public void setPopulation(int population) {
    this.population = population;
  }
}

The following yml file:

country:
  name: 'Denmark'
  population: 5614000
neighbor:
  name: 'Sweden'
  population: 9593000

In a SettingsHolder class:

public class Countries implements SettingsHolder {
  public static final Property<Country> COUNTRY =
    newBeanProperty(Country.class, "country", new Country());

  public static final Property<Country> NEIGHBOR =
    newBeanProperty(Country.class, "neighbor", new Country());
}

If we set up a SettingsManager with the above yml file, we will get the following:

// Denmark
String countryName = settingsManager.getProperty(Countries.COUNTRY).getName();

// Country object for Sweden
Country neighbor = settingsManager.getProperty(Countries.NEIGHBOR);
int neighborPop = neighbor.getPopulation(); // 9593000

JavaBeans

JavaBeans are simple Java classes with getters and setters. As you can see in the Country example, each property is private and has a getter and setter method with standard naming conventions. ConfigMe picks up on properties which have both a getter and a setter and will look in the YML file for those property names to create a new bean object.

Error handling

As with all other properties, resolving a bean property will never return null. If the content in the YML file cannot be used to create a bean (e.g. because a field is missing), the default object passed to the constructor will be used.

You can define a default value by assigning it directly to a field. For example, if the name of a country should be optional, we could assign it to an empty string at the beginning:

public class Country {
  private String name = "";
  private int population;

  // getters and setters
}

Now if your YML reads something like:

country:
  population: 1234

The Countries.COUNTRY property will resolve to a Country object that has an empty name and its population set to 1234. We could also omit the population, since the field is a primitive it will automatically be assigned a value of 0 on initialization.

ConfigMe will never return a bean having a field with null. If it does not succeed to set the value for a field, the mapping is considered to have failed and the default object is used. It is therefore important to initialize fields as shown with the country name above if you don't want the absence of a field to stop the mapping process.

Collections

You can use collections (such as List and Set) in your beans. For example, we can change the country class to contain a list of neighbors:

public class Country {
  private String name;
  private int population;
  private List<String> neighbors;

  // getters and setters for all three properties
}

Given the YML:

country:
  name: Denmark
  population: 5614000
  neighbors:
  - Sweden
  - Norway
  - Germany

This will create a Country object with getNeighbors() containing a list of "Sweden", "Norway", "Germany". Again, if this property should be optional, you can set private List<String> neighbors = new ArrayList<>(); in the bean class.

Restrictions

  • The generic type of a collection must always be present on the field, i.e. you cannot have a field List<?> neighbors or List neighbors. The specific type must be declared, e.g. List<Country> neighbors.
  • Fields with a type more specific than List or Set are not supported. For instance, e.g. Iterable<String> neighbors, Collection<String>, Set<String> are fine, but specific types such as TreeSet<String> are not.
  • You can declare collections of other bean types, e.g. List<Country> is possible. If an entry in the YML cannot be mapped to a Country, the entire entry is skipped. TODO example

Maps

You can also use Map properties in your beans. Only maps with String as key are supported, e.g. Map<String, Integer> or Map<String, Country> are fine, but something like Map<Integer, Country> is not supported. Maps are useful when you want to support arbitrary keys in a section, e.g.:

country:
  name: Denmark
  population: 123
  neighbors:
    sweden:
      name: Sweden
    norway:
      name: Norway

Under neighbors you want to support any key that is defined. This is typically the most user-friendly way when you want to have a dynamic section of a bean type. In the Java code, this would look as follows:

**TODO TODO **

Clone this wiki locally