The preceding examples demonstrated how Nucleus can create and initialize components from properties files. While this is itself a powerful function, the true power of Nucleus is its ability to allow components to point to each other through configuration files.
The easiest way to get components to point to each other is through properties. For example, say that a Weather
component is defined in Nucleus, and the Person
component needs a pointer to that Weather
.
The Weather
class might look like this:
public class Weather { String currentWeather; public Weather () { System.out.println ("constructing Weather"); } public String getCurrentWeather () { return currentWeather; } public void setCurrentWeather (String currentWeather) { System.out.println ("setting currentWeather to " + currentWeather); this.currentWeather = currentWeather; } }
For this example, we need an instance of Weather
in Nucleus, called /services/Weather
. This means that you should compile the Weather
Java class and create a Weather
class component with a Weather.properties
file in the same directory as Person.properties
. Note that, as with any Nucleus component, you can create /services/Weather
either with the ATG Control Center’s Generic Component Wizard, or by writing a properties file like this:
$class=Weather
currentWeather=sunny
Now modify the Person
component to contain a property that points to the Weather
:
public class Person { String name; int age; Weather weather; public Person () { System.out.println ("constructing Person"); } public String getName () { return name; } public void setName (String name) { System.out.println ("setting name to " + name); this.name = name; } public int getAge () { return age; } public void setAge (int age) { System.out.println ("setting age to " + age); this.age = age; } public Weather getWeather () { return weather; } public void setWeather (Weather weather) { System.out.println ("setting weather to " + weather.getCurrentWeather ()); this.weather = weather; } }
Finally, the Person
component must be modified so that it has a weather
property that points to the weather
component:
$class=Person
name=Stephen
age=20
weather=Weather
If you have included the Person
component as an initial service (as described in the Starting a Nucleus Component section in this chapter), then, when you start your application, the Person
component will be created and initialized. Its name
and age
properties will be set from the values found in the properties file. But to set the weather
property, Nucleus must resolve the name Weather
. In doing so, Nucleus ends up creating the Weather
component and initializing that component before assigning it to the Person
property. The output should look something like this:
constructing Person setting age to 20 constructing Weather setting currentWeather to sunny setting weather to sunny setting name to Stephen
The first two lines of the output show that Nucleus has created the /services/Person
component and has set the age
property. Then Nucleus attempts to set the weather
property. In doing so, it searches for the component named Weather
. This is a relative name, and so it is resolved relative to the current context /services
, resulting in /services/Weather
.
Nucleus searches its existing components and, finding that there is no /services/Weather
, it attempts to create one from the configuration file found in services/Weather.properties
. This causes Nucleus to construct an instance of the Weather
class and initialize its currentWeather
property, thereby resulting in the third and fourth lines of output.
Now that a /services/Weather
component has been created and initialized, Nucleus can go on to initialize the rest of the Person
component, by setting its weather
and name
properties. This results in the last two lines of output.
Nucleus does not put a “nesting limit” on the number of components that may refer to each other through properties. For example, component 1 may refer to component 2, may refer to component 3, etc. Nucleus also allows circular references. For example, component 1 may have a property that points to component 2, which may have a property that points back to component 1. In fact, component 1 may have a property that points back to itself. Nucleus handles these circular cases without spiraling into infinite loops.
Application errors can sometimes occur, however, if you reference a property of a component before that component is completely configured. To diagnose this type of error, set the loggingInfo
property of the /
Nucleus service to true
, and the ATG platform will print information messages for this situation.
Arrays of components can also be specified in the same way that other array values are specified: as a comma-separated list. For example, the Person
component may have a property called cityWeathers
that contains an array of Weather
components:
public Weather [] getCityWeathers ();
public void setCityWeathers (Weather [] cityWeathers);
This property might be initialized in the configuration file like this:
cityWeathers=\ /services/weather/cities/atlanta,\ /services/weather/cities/boston,\ /services/weather/cities/tampa,\ /services/weather/cities/phoenix
Nucleus handles this by finding each of the components in the list, arranging the found components into a 4-element array, then assigning that array to the cityWeathers
property of the Person
component.