Topology, Dependencies, and Management Policies
Applications written in YAML can similarly be written in Java. However, the YAML approach is recommended.
Define your Application Blueprint
The example below creates a three tier web service, composed of an Nginx load-balancer, a cluster of Tomcat app-servers, and a MySQL database. It is similar to the YAML policies example, but also includes the MySQL database to demonstrate the use of dependent configuration.
package com.acme.autobrick;
import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.policy.PolicySpec;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.api.sensor.EnricherSpec;
import org.apache.brooklyn.core.entity.AbstractApplication;
import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.enricher.stock.Enrichers;
import org.apache.brooklyn.entity.database.mysql.MySqlNode;
import org.apache.brooklyn.entity.group.DynamicCluster;
import org.apache.brooklyn.entity.proxy.nginx.NginxController;
import org.apache.brooklyn.entity.webapp.tomcat.TomcatServer;
import org.apache.brooklyn.policy.autoscaling.AutoScalerPolicy;
import org.apache.brooklyn.policy.ha.ServiceFailureDetector;
import org.apache.brooklyn.policy.ha.ServiceReplacer;
import org.apache.brooklyn.policy.ha.ServiceRestarter;
import org.apache.brooklyn.util.time.Duration;
public class ExampleWebApp extends AbstractApplication {
    @Override
    public void init() {
        AttributeSensor<Double> reqsPerSecPerNodeSensor = Sensors.newDoubleSensor(
                "webapp.reqs.perSec.perNode",
                "Reqs/sec averaged over all nodes");
        MySqlNode db = addChild(EntitySpec.create(MySqlNode.class)
                .configure(MySqlNode.CREATION_SCRIPT_URL, "https://bit.ly/brooklyn-visitors-creation-script"));
        DynamicCluster cluster = addChild(EntitySpec.create(DynamicCluster.class)
                .displayName("Cluster")
                .configure(DynamicCluster.MEMBER_SPEC, EntitySpec.create(TomcatServer.class)
                        .configure(TomcatServer.ROOT_WAR, 
                                "https://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.12.0/brooklyn-example-hello-world-sql-webapp-0.12.0.war" /* BROOKLYN_VERSION */ )
                        .configure(TomcatServer.JAVA_SYSPROPS.subKey("brooklyn.example.db.url"),
                                DependentConfiguration.formatString("jdbc:%s%s?user=%s&password=%s",
                                        DependentConfiguration.attributeWhenReady(db, MySqlNode.DATASTORE_URL),
                                        "visitors", "brooklyn", "br00k11n"))
                        .policy(PolicySpec.create(ServiceRestarter.class)
                                .configure(ServiceRestarter.FAIL_ON_RECURRING_FAILURES_IN_THIS_DURATION, Duration.minutes(5)))
                        .enricher(EnricherSpec.create(ServiceFailureDetector.class)
                                .configure(ServiceFailureDetector.ENTITY_FAILED_STABILIZATION_DELAY, Duration.seconds(30))))
                .policy(PolicySpec.create(ServiceReplacer.class))
                .policy(PolicySpec.create(AutoScalerPolicy.class)
                        .configure(AutoScalerPolicy.METRIC, reqsPerSecPerNodeSensor)
                        .configure(AutoScalerPolicy.METRIC_LOWER_BOUND, 1)
                        .configure(AutoScalerPolicy.METRIC_UPPER_BOUND, 3)
                        .configure(AutoScalerPolicy.RESIZE_UP_STABILIZATION_DELAY, Duration.seconds(2))
                        .configure(AutoScalerPolicy.RESIZE_DOWN_STABILIZATION_DELAY, Duration.minutes(1))
                        .configure(AutoScalerPolicy.MAX_POOL_SIZE, 3))
                .enricher(Enrichers.builder().aggregating(TomcatServer.REQUESTS_PER_SECOND_IN_WINDOW)
                        .computingAverage()
                        .fromMembers()
                        .publishing(reqsPerSecPerNodeSensor)
                        .build()));
        addChild(EntitySpec.create(NginxController.class)
                .configure(NginxController.SERVER_POOL, cluster)
                .configure(NginxController.STICKY, false));
    }
}
To describe each part of this:
- The application extends AbstractApplication.
- It implements init(), to add its child entities. Theinitmethod is called only once, when instantiating the entity instance.
- The addChildmethod takes anEntitySpec. This describes the entity to be created, defining its type and its configuration.
- The brooklyn.example.db.urlis a system property that will be passed to eachTomcatServerinstance. Its value is the database's URL (discussed below).
- The policies and enrichers provide in-life management of the application, to restart failed instances and to replace those components that repeatedly fail.
- The NginxControlleris the load-balancer and reverse-proxy: by default, it round-robins to the ip:port of each member of the cluster configured as theSERVER_POOL.
Dependent Configuration
Often a component of an application will depend on another component, where the dependency information is only available at runtime (e.g. it requires the IP of a dynamically provisioned component). For example, the app-servers in the example above require the database URL to be injected.
The "DependentConfiguration" methods returns a future (or a "promise" in the language of 
some other programming languages): when the  value is needed, the caller will block to wait for
the future to resolve. It will block only "at the last moment" when the value is needed (e.g. 
after the VMs have been provisioned and the software is installed, thus optimising the 
provisioning time). It will automatically monitor the given entity's sensor, and generate the 
value when the sensor is populated.
The attributeWhenReady is used to generate a configuration value that depends on the dynamic 
sensor value of another entity - in the example above, it will not be available until that 
MySqlNode.DATASTORE_URL sensor is populated. At that point, the JDBC URL will be constructed 
(as defined in the formatString method, which also returns a future).
