You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/06/16 15:21:50 UTC

[10/28] brooklyn-docs git commit: Refactor Blueprinting

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/example_yaml/vanilla-bash-netcat-w-client.yaml
----------------------------------------------------------------------
diff --git a/guide/blueprints/example_yaml/vanilla-bash-netcat-w-client.yaml b/guide/blueprints/example_yaml/vanilla-bash-netcat-w-client.yaml
new file mode 100644
index 0000000..75d2b79
--- /dev/null
+++ b/guide/blueprints/example_yaml/vanilla-bash-netcat-w-client.yaml
@@ -0,0 +1,78 @@
+name: Netcat Example with Client
+
+location: localhost
+
+services:
+
+# the netcat server instance, running in listener mode (-l)
+- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+  id: netcat-server
+  name: Simple Netcat Server
+  launch.command: |
+    echo hello | nc -l 4321 >> server-input &
+    echo $! > $PID_FILE
+
+  # a failure detector and a service restarter work together
+  brooklyn.enrichers:
+  - type: org.apache.brooklyn.policy.ha.ServiceFailureDetector
+    brooklyn.config:
+      # wait 15s after service fails before propagating failure
+      serviceFailedStabilizationDelay: 15s
+
+  brooklyn.policies:
+  - type: org.apache.brooklyn.policy.ha.ServiceRestarter
+    brooklyn.config:
+      # repeated failures in a time window can cause the restarter to abort,
+      # propagating the failure; a time window of 0 will mean it always restarts!
+      failOnRecurringFailuresInThisDuration: 0
+      
+  brooklyn.initializers:
+  # two sensors, recording the data sent to this netcat server:
+  
+  - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor
+    brooklyn.config:
+      name: output.last
+      period: 1s
+      command: tail -1 server-input
+      
+  - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor
+    brooklyn.config:
+      name: output.all
+      period: 1s
+      command: cat server-input
+
+# a client to hit netcat
+- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+  name: Simple Pinger
+  
+  # set the hostname of the netcat instance as an env var for the scripts 
+  env:
+    TARGET_HOSTNAME: 
+      $brooklyn:entity("netcat-server").
+        attributeWhenReady("host.name")
+    
+  # start/check/stop are no-op
+  launch.command: ""
+  checkRunning.command: ""
+  stop.command: ""
+  
+  brooklyn.initializers:
+  # but there is a sample effector which runs nc in client mode
+  
+  - type: org.apache.brooklyn.core.effector.ssh.SshCommandEffector
+    brooklyn.config:
+      name: sayHiNetcat
+      description: Echo a small hello string to the netcat entity
+      command: |
+        echo $message | nc $TARGET_HOSTNAME 4321
+      parameters:
+        message:
+          description: The string to pass to netcat
+          defaultValue: hi netcat
+
+# and add an enricher at the root so all sensors from netcat-server are visible on the root
+brooklyn.enrichers:
+- enricherType: org.apache.brooklyn.enricher.stock.Propagator
+  brooklyn.config:
+    enricher.producer: $brooklyn:entity("netcat-server")
+    enricher.propagating.propagatingAll: true

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/example_yaml/vanilla-bash-netcat.yaml
----------------------------------------------------------------------
diff --git a/guide/blueprints/example_yaml/vanilla-bash-netcat.yaml b/guide/blueprints/example_yaml/vanilla-bash-netcat.yaml
new file mode 100644
index 0000000..df616af
--- /dev/null
+++ b/guide/blueprints/example_yaml/vanilla-bash-netcat.yaml
@@ -0,0 +1,8 @@
+name: Simple Netcat Server Example
+location: localhost
+services:
+- type: org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess
+  name: Simple Netcat Server
+  launch.command: |
+    echo hello | nc -l 4321 &
+    echo $! > $PID_FILE

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/index.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/index.md b/guide/blueprints/index.md
new file mode 100644
index 0000000..caf0294
--- /dev/null
+++ b/guide/blueprints/index.md
@@ -0,0 +1,28 @@
+---
+title: Writing Blueprints
+layout: website-normal
+children:
+- creating-yaml.md
+- entity-configuration.md
+- setting-locations.md
+- configuring-vms.md
+- multiple-services.md
+- custom-entities.md
+- catalog/
+- clusters.md
+- enrichers.md
+- policies.md
+- clusters-and-policies.md
+- java/
+- winrm/
+- test/
+- ansible/
+- chef/
+- salt/
+- advanced-example.md
+- blueprinting-tips.md
+- { path: yaml-reference.md, title: YAML Blueprint Reference }
+---
+
+
+{% include list-children.html %}

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/archetype.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/archetype.md b/guide/blueprints/java/archetype.md
new file mode 100644
index 0000000..176e662
--- /dev/null
+++ b/guide/blueprints/java/archetype.md
@@ -0,0 +1,114 @@
+---
+title: Creating from a Maven Archetype
+layout: website-normal
+toc: ../guide_toc.json
+categories: [use, guide, defining-applications]
+---
+
+### Maven Archetype
+
+Brooklyn includes a maven archetype, which can be used to create the project structure for 
+developing a new Java entity, and generating the OSGi bundle for it.
+
+
+#### Generating the Project
+
+The archetype can be used interactively, by running:
+{% highlight bash %}
+$ mvn archetype:generate
+{% endhighlight %}
+
+The user will be prompted for the archetype to use (i.e. group "org.apache.brooklyn" 
+and artifact "brooklyn-archetype-quickstart"), as well as options for the project 
+to be created.
+
+Alternatively, all options can be supplied at the command line. For example, 
+if creating a project named "autobrick" for "com.acme":
+
+{% highlight bash %}
+$ BROOKLYN_VERSION={{ site.brooklyn-version }}
+$ mvn archetype:generate \
+	-DarchetypeGroupId=org.apache.brooklyn \
+	-DarchetypeArtifactId=brooklyn-archetype-quickstart \
+	-DarchetypeVersion=${BROOKLYN_VERSION} \
+	-DgroupId=com.acme \
+	-DartifactId=autobrick \
+	-Dversion=0.1.0-SNAPSHOT \
+	-DpackageName=com.acme.autobrick \
+	-DinteractiveMode=false
+{% endhighlight %}
+
+This will create a directory with the artifact name (e.g. "autobrick" in the example above).
+Note that if run from a directory containing a pom, it will also modify that pom to add this as 
+a module!
+
+The project will contain an example Java entity. You can test this using the supplied unit tests,
+and also replace it with your own code.
+
+The `README.md` file within the project gives further guidance.
+
+
+#### Building
+
+To build, run the commands:
+
+{% highlight bash %}
+$ cd autobrick
+$ mvn clean install
+{% endhighlight %}
+
+
+#### Adding to the Catalog
+
+The build will produce an OSGi bundle in `target/autobrick-0.1.0-SNAPSHOT.jar`, suitable for 
+use in the [Brooklyn catalog]({{ site.path.guide }}/blueprints/catalog/) (using `brooklyn.libraries`).
+
+To use this in your Brooklyn catalog you will first have to copy the target jar to a suitable location. 
+For developing/testing purposes storing on the local filesystem is fine. 
+For production use, we recommend uploading to a remote maven repository or similar.
+
+Once your jar is in a suitable location the next step is to add a new catalog item to Brooklyn. 
+The project comes with a `catalog.bom` file, located in `src/main/resources`. 
+Modify this file by adding a 'brooklyn.libraries' statement to the bom pointing to the jar. 
+For example:
+
+{% highlight yaml %}
+brooklyn.catalog:
+    brooklyn.libraries:
+    - file:///path/to/jar/autobrick-0.1.0-SNAPSHOT.jar
+    version: "0.1.0-SNAPSHOT"
+    itemType: entity
+    items:
+    - id: com.acme.autobrick.MySample
+      item:
+        type: com.acme.autobrick.MySample
+{% endhighlight %}
+
+The command below will use the CLI to add this to the catalog of a running Brooklyn instance:
+
+{% highlight bash %}
+    br catalog add catalog.bom
+{% endhighlight %}
+
+After running that command, the OSGi bundle will have been added to the OSGi container, and the
+entity will have been added to your catalog. It can then be used in the same way as regular AMP 
+entities.
+
+For example, you can use the blueprint:
+
+{% highlight yaml %}
+services:
+- type: com.acme.autobrick.MySample
+{% endhighlight %}
+
+
+### Testing Entities
+
+The project comes with unit tests that demonstrate how to test entities, both within Java and
+also using YAML-based blueprints.
+
+A strongly recommended way is to write a YAML test blueprint using the test framework, and making  
+this available to anyone who will use your entity. This will allow users to easily run the test
+blueprint in their own environment (simply by deploying it to their own Brooklyn server) to confirm 
+that the entity is working as expected. An example is contained within the project at 
+`src/test/resources/sample-test.yaml`.

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/bundle-dependencies.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/bundle-dependencies.md b/guide/blueprints/java/bundle-dependencies.md
new file mode 100644
index 0000000..0f07fb6
--- /dev/null
+++ b/guide/blueprints/java/bundle-dependencies.md
@@ -0,0 +1,135 @@
+---
+title: Handling Bundle Dependencies
+layout: website-normal
+---
+
+Some Java blueprints will require third party libraries. These need to be made available to the
+Apache Brooklyn runtime. There are a number of ways this can be achieved.
+
+### Classic Mode: Dropins Folder
+
+In Brooklyn classic mode (i.e. when not using Karaf), jars can be added to `./lib/dropins/`.
+After restarting Brooklyn, these will be available on the classpath.
+
+In Brooklyn classic mode, there is an embedded OSGi container. This is used for installing 
+libraries referenced in catalog items.
+
+### OSGi Bundles
+
+#### Introduction to OSGi Bundles
+
+An [OSGi bundle](https://en.wikipedia.org/wiki/OSGi#Bundles) is a jar file with additional 
+metadata in its manifest file. The `MANIFEST.MF` file contains the symbolic name and version 
+of the bundle, along with details of its dependencies and of the packages it exports 
+(which are thus visible to other bundles).
+
+The [maven-bundle-plugin](http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html) 
+is a convenient way of building OSGi bundles.
+
+#### OSGi Bundles Declared in Catalog Items  
+
+Within a [catalog item]({{ site.path.guide}}/blueprints/catalog/), a list of URLs can be supplied under
+`brooklyn.libraries`. Each URL should point to an OSGi bundle. This list should include the OSGi 
+bundle that has the Java code for your blueprint, and also the OSGi bundles that it depends
+on (including all transitive dependencies).
+
+It is vital that these jars are built correctly as OSGi bundles, and that all transitive 
+dependencies are included. The bundles will be added to Karaf in the order given, so a bundle's
+dependencies should be listed before the bundle(s) that depend on them.
+
+In the [GistGenerator example]({{ site.path.guide}}/blueprints/java/defining-and-deploying.html), the 
+[catalog.bom file]({{ site.path.guide}}/blueprints/java/gist_generator/gist_generator.bom) included
+the URL of the dependency `org.eclipse.egit.github.core`. It also (before that line) included
+its transitive dependency, which is a specific version of `gson`.
+
+For Java blueprint developers, this is often the most convenient way to share a blueprint.
+
+Similarly for those wishing to use a new blueprint, this is often the simplest mechanism: the
+dependencies are fully described in the catalog item, which makes it convenient for deploying 
+to Apache Brooklyn instances where there is not direct access to Karaf or the file system.
+
+
+#### Adding Bundles and Features Directly to Karaf
+
+Bundles and features can be added manually, directly to Karaf.
+
+However, note this only affects the single Karaf instance. If running in HA mode or if provisioning
+a new instance of Apache Brooklyn, the bundles will also need to be added to these Karaf instances.
+
+
+##### Karaf Console
+
+Login to the [Karaf console](https://karaf.apache.org/manual/latest/#_shell_console_basics)
+using `./bin/client`, and add the bundles and features as desired.
+
+Examples of some useful commands are shown below:
+
+{% highlight bash %}
+karaf@amp> bundle:install -s http://repo1.maven.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.egit.github.core/2.1.5_1/org.apache.servicemix.bundles.egit.github.core-2.1.5_1.jar
+Bundle ID: 316
+
+karaf@amp> bundle:list -t 0 -s | grep github
+318 | Active   |  80 | 2.1.5.1                       | org.apache.servicemix.bundles.egit.github.core
+
+karaf@amp> bundle:headers org.apache.servicemix.bundles.egit.github.core
+...
+
+karaf@amp> bundle:uninstall org.apache.servicemix.bundles.egit.github.core
+{% endhighlight %}
+
+
+##### Karaf Deploy Folder
+
+Karaf support [hot deployment](https://karaf.apache.org/manual/latest/#_deployers). There are a 
+set of deployers, such as feature and KAR deployers, that handle deployment of artifacts added
+to the `deploy` folder.
+
+Note that the Karaf console can give finer control (including for uninstall).
+
+
+### Karaf KAR files
+
+[Karaf KAR](https://karaf.apache.org/manual/latest/kar) is an archive format (Karaf ARchive).
+A KAR is a jar file (so a zip file), which contains a set of feature descriptors and bundle jar files.
+
+This can be a useful way to bundle a more complex Java blueprint (along with its dependencies), to
+make it easier for others to install.
+
+A KAR file can be built using the 
+[maven plugin org.apache.karaf.tooling:features-maven-plugin](https://karaf.apache.org/manual/latest/#_maven).
+
+
+### Karaf Features
+
+A [karaf feature.xml](https://karaf.apache.org/manual/latest/#_create_a_features_xml_karaf_feature_archetype)
+defines a set of bundles that make up a feature. Once a feature is defined, one can add it to a Karaf instance:
+either directly (e.g. using the [Karaf console](https://karaf.apache.org/manual/latest/#_shell_console_basics)), or
+by referencing it in another feature.xml file. 
+
+
+### Embedded Dependencies
+
+An OSGi bundle can 
+[embed jar dependencies](http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html#embedding-dependencies)
+within it. This allows dependencies to be kept private within a bundle, and easily shipped with that bundle.
+
+To keep these private, it is vital that the OSGi bundle does not import or export the packages
+contained within those embedded jars, and does not rely on any of those packages in the public 
+signatures of any packages that are exported or imported.
+
+
+### Converting Non-OSGi Dependencies to Bundles
+
+If a dependencies is not available as an OSGi bundle (and you don't want to just [embed the jar](#embedded-dependencies)),
+there are a few options for getting an equivalent OSGi bundle:
+
+* Use a ServiceMix re-packaged jar, if available. ServiceMix have re-packed many common dependencies as
+  OSGi bundles, and published them on [Maven Central](https://search.maven.org).
+
+* Use the `wrap:` prefix. The [PAX URL Wrap protocol](https://ops4j1.jira.com/wiki/display/paxurl/Wrap+Protocol) 
+  is an OSGi URL handler that can process your legacy jar at runtime and transform it into an OSGi bundle.  
+  This can be used when declaring a dependency in your feature.xml, and when using the Karaf console's 
+  `bundle:install`. Note that it is not yet supported in Brooklyn's `brooklyn.libraries` catalog items.
+
+* Re-package the bundle yourself, offline, to produce a valid OSGi bundle.
+

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/common-usage.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/common-usage.md b/guide/blueprints/java/common-usage.md
new file mode 100644
index 0000000..ccafd9b
--- /dev/null
+++ b/guide/blueprints/java/common-usage.md
@@ -0,0 +1,205 @@
+---
+title: Common Classes and Entities
+layout: website-normal
+---
+
+<!-- TODO old, needs work (refactoring!) and use of java_link -->
+
+### Entity Class Hierarchy
+
+By convention in Brooklyn the following words have a particular meaning:
+
+* *Group* - a homogeneous grouping of entities (which need not all be managed by the same parent 
+  entity)
+* *Cluster* - a homogeneous collection of entities (all managed by the "cluster" entity)
+* *Fabric* - a multi-location collection of entities, with one per location; often used with a cluster per location
+* *Application* - a top-level entity, which can have one or more child entities.
+
+The following constructs are often used for Java entities:
+
+* *entity spec* defines an entity to be created; used to define a child entity, or often to 
+  define the type of entity in a cluster.
+* *traits* (mixins) providing certain capabilities, such as *Resizable* and *Startable*.
+* *Resizable* entities can re-sized dynamically, to increase/decrease the number of child entities.
+  For example, scaling up or down a cluster. It could similarly be used to vertically scale a VM,
+  or to resize a disk.
+* *Startable* indicates the effector to be executed on initial deployment (`start()`) and on 
+  tear down (`stop()`).
+
+
+### Configuration
+
+Configuration keys are typically defined as static named fields on the Entity interface. These
+define the configuration values that can be passed to the entity during construction. For
+example:
+
+{% highlight java %}
+public static final ConfigKey<String> ROOT_WAR = new ConfigKeys.newStringConfigKey(
+        "wars.root",
+        "WAR file to deploy as the ROOT, as URL (supporting file: and classpath: prefixes)");
+{% endhighlight %}
+
+One can optionally define a `@SetFromFlag("war")`. This defines a short-hand for configuring the
+entity. However, it should be used with caution - when using configuration set on a parent entity
+(and thus inherited), the `@SetFromFlag` short-form names are not checked. The long form defined 
+in the constructor should be meaningful and sufficient. The usage of `@SetFromFlag` is therefore
+discouraged.
+
+The type `AttributeSensorAndConfigKey<?>` can be used to indicate that a config key should be resolved,
+and its value set as a sensor on the entity (when `ConfigToAttributes.apply(entity)` is called).
+
+A special case of this is `PortAttributeSensorAndConfigKey`. This is resolved to find an available 
+port (by querying the target location). For example, the value `8081+` means that then next available
+port starting from 8081 will be used.
+
+
+### Declaring Sensors
+
+Sensors are typically defined as static named fields on the Entity interface. These define 
+the events published by the entity, which interested parties can subscribe to. For example:
+
+{% highlight java %}
+AttributeSensor<String> MANAGEMENT_URL = Sensors.newStringSensor(
+        "crate.managementUri",
+        "The address at which the Crate server listens");
+{% endhighlight %}
+
+
+### Declaring Effectors
+
+Effectors are the operations that an entity supports. There are multiple ways that an entity can 
+be defined. Examples of each are given below.
+
+#### Effector Annotation
+
+A method on the entity interface can be annotated to indicate it is an effector, and to provide
+metadata about the effector and its parameters.
+
+{% highlight java %}
+@org.apache.brooklyn.core.annotation.Effector(description="Retrieve a Gist")
+public String getGist(@EffectorParam(name="id", description="Gist id") String id);
+{% endhighlight %}
+
+
+#### Static Field Effector Declaration
+
+A static field can be defined on the entity to define an effector, giving metadata about that effector.
+
+{% highlight java %}
+public static final Effector<String> EXECUTE_SCRIPT = Effectors.effector(String.class, "executeScript")
+        .description("invokes a script")
+        .parameter(ExecuteScriptEffectorBody.SCRIPT)
+        .impl(new ExecuteScriptEffectorBody())
+        .build();
+{% endhighlight %}
+
+In this example, the implementation of the effector is an instance of `ExecuteScriptEffectorBody`. 
+This implements `EffectorBody`. It will be invoked whenever the effector is called.
+
+
+#### Dynamically Added Effectors
+
+An effector can be added to an entity dynamically - either as part of the entity's `init()`
+or as separate initialization code. This allows the implementation of the effector to be shared
+amongst multiple entities, without sub-classing. For example:
+
+{% highlight java %}
+Effector<Void> GET_GIST = Effectors.effector(Void.class, "createGist")
+        .description("Create a Gist")
+        .parameter(String.class, "id", "Gist id")
+        .buildAbstract();
+
+public static void CreateGistEffectorBody implements EffectorBody<Void>() {
+    @Override
+    public Void call(ConfigBag parameters) {
+        // impl
+        return null;
+    }
+}
+
+@Override
+public void init() {
+    getMutableEntityType().addEffector(CREATE_GIST, new CreateGistEffectorBody());
+}
+{% endhighlight %}
+
+
+### Effector Invocation
+
+There are several ways to invoke an effector programmatically:
+
+* Where there is an annotated method, simply call the method on the interface.
+
+* Call the `invoke` method on the entity, using the static effector declaration. For example:  
+  `entity.invoke(CREATE_GIST, ImmutableMap.of("id", id));`.
+
+* Call the utility method `org.apache.brooklyn.core.entity.Entities.invokeEffector`. For example:  
+  `Entities.invokeEffector(this, targetEntity, CREATE_GIST, ImmutableMap.of("id", id));`.
+
+When an effector is invoked, the call is intercepted to wrap it in a task. In this way, the 
+effector invocation is tracked - it is shown in the Activity view.
+
+When `invoke` or `invokeEffector` is used, the call returns a `Task` object (which extends 
+`Future`). This allows the caller to understand progress and errors on the task, as well as 
+calling `task.get()` to retrieve the return value. Be aware that `task.get()` is a blocking 
+function that will wait until a value is available before returning.
+
+
+### Tasks
+
+_Warning: the task API may be changed in a future release. However, backwards compatibility
+will be maintained where possible._
+
+When implementing entities and policies, all work done within Brooklyn is executed as Tasks.
+This makes it trackable and visible to administrators. For the activity list to show a break-down 
+of an effector's work (in real-time, and also after completion), tasks and sub-tasks must be 
+created.
+
+In common situations, tasks are implicitly created and executed. For example, when implementing
+an effector using the `@Effector` annotation on a method, the method invocation is automatically
+wrapped as a task. Similarly, when a subscription is passed an event (e.g. when using 
+`SensorEventListener.onEvent(SensorEvent<T> event)`, that call is done inside a task.
+
+Within a task, it is possible to create and execute sub-tasks. A common way to do this is to 
+use `DynamicTasks.queue`. If called from within a a "task queuing context" (e.g. from inside an
+effector implementation), it will add the task to be executed. By default, the outer task will not be
+marked as done until its queued sub-tasks are complete.
+
+When creating tasks, the `TaskBuilder` can be used to create simple tasks or to create compound tasks
+whose sub-tasks are to be executed either sequentially or in parallel. For example:
+
+{% highlight java %}
+TaskBuilder.<Integer>builder()
+        .displayName("stdout-example")
+        .body(new Callable<Integer>() { public Integer call() { System.out.println("example"; } })
+        .build();
+{% endhighlight %}
+
+There are also builder and factory utilities for common types of operation, such as executing SSH 
+commands using `SshTasks`.
+
+A lower level way to submit tasks within an entity is to call `getExecutionContext().submit(...)`.
+This automatically tags the task to indicate that its context is the given entity.
+
+An even lower level way to execute tasks (to be ignored except for power-users) is to go straight  
+to the `getManagementContext().getExecutionManager().submit(...)`. This is similar to the standard
+Java `Executor`, but also supports more metadata about tasks such as descriptions and tags.
+It also supports querying for tasks. There is also support for submitting `ScheduledTask` 
+instances which run periodically.
+
+The `Tasks` and `BrooklynTaskTags` classes supply a number of conveniences including builders to 
+make working with tasks easier.
+
+
+### Subscriptions and the Subscription Manager
+
+Entities, locations, policies and enrichers can subscribe to events. These events could be
+attribute-change events from other entities, or other events explicitly published by the entities.
+
+A subscription is created by calling `subscriptions().subscribe(entity, sensorType, sensorEventListener)`.
+The `sensorEventListener` will be called with the event whenever the given entity emits a sensor of
+the given type. If `null` is used for either the entity or sensor type, this is treated as a 
+wildcard.
+
+It is very common for a policy or enricher to subscribe to events, to kick off actions or to 
+publish other aggregated attributes or events. 

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/defining-and-deploying.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/defining-and-deploying.md b/guide/blueprints/java/defining-and-deploying.md
new file mode 100644
index 0000000..11a2889
--- /dev/null
+++ b/guide/blueprints/java/defining-and-deploying.md
@@ -0,0 +1,177 @@
+---
+title: Defining and Deploying
+layout: website-normal
+---
+
+## Intro
+
+This walkthrough will set up a simple entity, add it to the catalog, and provision it.
+
+For illustration purposes, we will write an integration with [Github Gist](https://gist.github.com/), 
+with an effector to create new gists.
+
+
+## Project Setup
+
+Follow the instructions to create a new Java project using the [archetype](archetype.html), and
+import it into your [favorite IDE]({{ site.path.guide }}/dev/env/ide/). This example assumes you 
+used the groupId `com.acme` and artifact id `autobrick`.
+
+First ensure you can build this project at the command line, using `mvn clean install`.
+
+
+## Java Entity Classes
+
+For this particular example, we will use a third party Gist library, so will need to add that as 
+a dependency. Add the following to your `pom.xml` inside the `<dependencies>` section 
+(see [Maven](https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html) 
+for more details):
+
+{% highlight xml %}
+<dependency>
+  <groupId>org.eclipse.mylyn.github</groupId>
+  <artifactId>org.eclipse.egit.github.core</artifactId>
+  <version>2.1.5</version>
+</dependency>
+{% endhighlight %}
+
+Create a new Java interface, `GistGenerator`, to describe the entity's interface (i.e. the 
+configuration options, sensors, and effectors). The code below assumes you have created this
+in the package `com.acme` for `src/main/java`.
+
+{% highlight java %}
+{% readj gist_generator/GistGenerator.java %}
+{% endhighlight %}
+
+To describe each part of this:
+
+* The `@ImplementedBy` indicates the implementation class for this entity type - i.e. the class 
+  to instantiate when an entity of this type is created.
+* By extending `Entity`, we indicate that this interface is an Entity type. We could alternatively
+  have extended one of the other sub-types of Entity.
+* The `OAUTH_KEY` is a configuration key - it is configuration that can be set on the entity when 
+  it is being instantiated.
+* The `@Effector` annotation indicates that the given method is an effector, so should be presented
+  and tracked as such. Execution of the effector is intercepted, to track it as a task and show its
+  execution in the Activity view.
+* The `@EffectorParam` annotations give metadata about the effector's parameters. This metadata,
+  such as the parameter description, is available to those using the client CLI, rest API and 
+  web-console.
+
+Note there is an alternative way of defining effectors - adding them to the entity dynamically, 
+discussed in the section [Dynamically Added Effectors](common-usage.html#dynamically-added-effectors).
+
+Next lets add the implementation. Create a new Java class named `GistGeneratorImpl`.
+
+{% highlight java %}
+{% readj gist_generator/GistGeneratorImpl.java %}
+{% endhighlight %}
+
+To describe each part of this:
+
+* Extends `AbstractEntity` - all entity implementations should extend this, or one of its 
+  sub-types.
+* Implements `GistGenerator`: this is the Entity type definition, so must be implemented.
+  Users of the entity will only refer to the interface; they will never be given an instance 
+  of the concrete class - instead a [dynamic proxy](https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html) 
+  is used (to allow remoting).
+* `org.slf4j.Logger` is the logger used throughout Apache Brooklyn.
+* Implements the `createGist` effector - we do not need to re-declare all the annotations.
+* If no `oath.key` parameter was passed in, then use the configuration set on the entity.
+* Use the third party library to create the gist.
+
+
+### Configuring GitHub
+
+First, create a github.com account, if you do not already have one.
+
+Before running the blueprint, we'll need to generate an access token that has permissions to
+create a gist programmatically.
+
+First [create a new access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/) 
+that our blueprint will use to create a gist:
+
+[![Create a new access key.](gist_generator/gist_create_token.png "Create a new access key")](gist_generator/gist_create_token.png)
+
+Next, grant the token rights to create gists:
+
+[![Grant access.](gist_generator/gist_grant_access.png "Grant access")](gist_generator/gist_grant_access.png)
+
+
+### Testing
+
+The archetype project comes with example unit tests that demonstrate how to test entities, 
+both within Java and also using YAML-based blueprints. 
+
+We will create a similar Java-based test for this blueprint. Create a new Java class named 
+`GistGeneratorTest` in the package `com.acme`, inside `src/test/java`.
+
+You will need to substitute the github access token you generated in the previous section for
+the placeholder text `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`.
+
+{% highlight java %}
+{% readj gist_generator/GistGeneratorTest.java %}
+{% endhighlight %}
+
+Similarly, we can write a test that uses the `GistGenerator` from a YAML blueprint. 
+Create a new Java class named `GistGeneratorYamlTest` in the package `com.acme`, 
+inside `src/test/java`.
+
+Again you will need to substitute the github access token you generated in the previous section for
+the placeholder text `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx`. See the section on 
+[externalised configuration]({{ site.path.guide }}/ops/externalized-configuration.html) 
+for how to store these credentials more securely. 
+
+{% highlight java %}
+{% readj gist_generator/GistGeneratorYamlTest.java %}
+{% endhighlight %}
+
+
+## Building the OSGi Bundle
+
+Next we will build this example as an [OSGi Bundle](https://www.osgi.org/developer/architecture/) 
+so that it can be added to the Apache Brooklyn server at runtime, and so multiple versions of the  
+blueprint can be managed.
+
+The `mvn clean install` will automatically do this, creating a jar inside the `target/` sub-directory
+of the project. This works by using the 
+[Maven Bundle Plugin](http://felix.apache.org/documentation/subprojects/apache-felix-maven-bundle-plugin-bnd.html)
+which we get automatically by declaring the `pom.xml`'s parent as `brooklyn-downstream-parent`.
+
+
+## Adding to the catalog
+
+Similar to the `sample.bom` entity that ships with the archetype, we will define a `.bom` file
+to add our `GistGenerator` to the catalog. Substitute the URL below for your own newly built 
+artifact (which will be in the `target` sub-directory after running `mvn clean install`).
+
+{% highlight yaml %}
+{% readj gist_generator/gist_generator.bom %}
+{% endhighlight %}
+
+See [Handling Bundle Dependencies]({{ site.path.guide}}/blueprints/java/bundle-dependencies.html)
+for a description of the `brooklyn.libraries` used above, and for other alternative approaches.
+
+The command below will use the `br` CLI to add this to the catalog of a running Brooklyn instance.
+Substitute the credentials, URL and port for those of your server.
+
+{% highlight bash %}
+$ br login https://127.0.0.1:8443 admin pa55w0rd
+$ br catalog add gist_generator.bom
+{% endhighlight %}
+
+
+## Using the blueprint
+
+The YAML blueprint below shows an example usage of this blueprint:
+
+    name: my sample
+    services:
+    - type: example.GistGenerator
+      brooklyn.config:
+        oauth.key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+
+Note the type name matches the id defined in the `.bom` file.
+
+You can now call the effector by any of the standard means - [web console]({{ site.path.guide }}/ops/gui/), 
+[REST api]({{ site.path.guide }}/ops/rest.html), or [Client CLI]({{ site.path.guide }}/ops/cli/).

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/entities.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/entities.md b/guide/blueprints/java/entities.md
new file mode 100644
index 0000000..1e2623d
--- /dev/null
+++ b/guide/blueprints/java/entities.md
@@ -0,0 +1,223 @@
+---
+title: Custom Entity Development
+layout: website-normal
+---
+
+This section details how to create new custom application components or groups as brooklyn entities.
+
+The Entity Lifecycle
+--------------------
+
+- Importance of serialization, ref to How mananagement works
+- Parents and Membership (groups)
+
+What to Extend -- Implementation Classes
+----------------------------------------
+
+- entity implementation class hierarchy
+
+  - `SoftwareProcess` as the main starting point for base entities (corresponding to software processes),
+    and subclasses such as `VanillaJavaApp`
+  - `DynamicCluster` (multiple instances of the same entity in a location) and 
+    `DynamicFabric` (clusters in multiple location) for automatically creating many instances,
+    supplied with an `EntityFactory` (e.g. `BaseEntityFactory`) in the `factory` flag
+  - `AbstractGroup` for collecting entities which are parented elsewhere in the hierachy
+  - `AbstractEntity` if nothing else fits
+  
+- traits (mixins, otherwise known as interfaces with statics) to define available config keys, sensors, and effectors;
+    and conveniences e.g. ``StartableMethods.{start,stop}`` is useful for entities which implement ``Startable``
+
+- the ``Entities`` class provides some generic convenience methods; worth looking at it for any work you do
+
+A common lifecycle pattern is that the ``start`` effector (see more on effectors below) is invoked, 
+often delegating either to a driver (for software processes) or children entities (for clusters etc).
+
+
+Configuration
+-------------
+<!---
+TODO: why to use config?
+-->
+
+- AttributeSensorAndConfigKey fields can be automatically converted for ``SoftwareProcess``. 
+  This is done in ``preStart()``. This must be done manually if required for other entities,
+  often with ``ConfigToAttributes.apply(this)``.
+
+- Setting ports is a special challenge, and one which the ``AttributeSensorAndConfigKey`` is particularly helpful for,
+  cf ``PortAttributeSensorAndConfigKey`` (a subclass),
+  causing ports automatically get assigned from a range and compared with the target ``PortSupplied`` location.
+  
+  Syntax is as described in the PortRange interface. For example, "8080-8099,8800+" will try port 8080, try sequentially through 8099, then try from 8800 until all ports are exhausted.
+  
+  This is particularly useful on a contended machine (localhost!). Like ordinary configuration, the config is done by the user, and the actual port used is reported back as a sensor on the entity.
+
+- Validation of config values can be applied by supplying a ``Predicate`` to the ``constraint`` of a ConfigKey builder.
+  Constraints are tested after an entity is initialised and before an entity managed.
+  Useful predicates include:
+  - ``StringPredicates.isNonBlank``: require that a String key is neither null nor empty.
+  - ``ResourcePredicates.urlExists``: require that a URL that is loadable by Brooklyn. Use this to
+    confirm that necessary resources are available to the entity.
+  - ``Predicates.in``: require one of a fixed set of values.
+  - ``Predicates.containsPattern``: require that a value match a regular expression pattern.
+
+  An important caveat is that only constraints on config keys that are on an entity's type hierarchy can be
+  tested automatically. Brooklyn has no knowledge of the true type of other keys until they are retrieved with a
+  ``config().get(key)``.
+
+
+Implementing Sensors
+--------------------
+
+- e.g. HTTP, JMX
+
+Sensors at base entities are often retrieved by feeds which poll the entity's corresponding instance in the real world.
+The ``SoftwareProcess`` provides a good example; by subclassing it and overriding the ``connectSensors()`` method
+you could wire some example sensors using the following: 
+
+{% highlight java %}
+public void connectSensors() {
+	super.connectSensors()
+	
+    httpFeed = HttpFeed.builder()
+            .entity(this)
+            .period(200)
+            .baseUri(mgmtUrl)
+            .poll(new HttpPollConfig<Boolean>(SERVICE_UP)
+                    .onSuccess(HttpValueFunctions.responseCodeEquals(200))
+                    .onError(Functions.constant(false)))
+            .poll(new HttpPollConfig<Integer>(REQUEST_COUNT)
+                    .onSuccess(HttpValueFunctions.jsonContents("requestCount", Integer.class)))
+            .build();
+}
+    
+@Override
+protected void disconnectSensors() {
+    super.disconnectSensors();
+    if (httpFeed != null) httpFeed.stop();
+}
+{% endhighlight %}
+
+In this example (a simplified version of ``JBoss7Server``), the url returns metrics in JSON. 
+We report the entity as up if we get back an http response code of 200, or down if any other response code or exception.
+We retrieve the request count from the response body, and convert it to an integer.
+
+Note the first line (``super.connectSensors()``); as one descends into specific convenience subclasses (such as for Java web-apps), the work done by the parent class's overridden methods may be relevant, and will want to be invoked or even added to a resulting list.
+
+For some sensors, and often at compound entities, the values are obtained by monitoring values of other sensors on the same (in the case of a rolling average) or different (in the case of the average of children nodes) entities. This is achieved by policies, described below.
+
+Implementing Effectors
+----------------------
+
+The ``Entity`` interface defines the sensors and effectors available. The entity class provides 
+wiring for the sensors, and the effector implementations. In simple cases it may be straightforward 
+to capture the behaviour of the effectors in a simple methods.
+For example deploying a WAR to a cluster can be done as follows:
+
+*This section is not complete. Feel free to [fork](https://github.com/apache/brooklyn-docs) the docs and lend a hand.*
+
+<!---
+TODO show an effector which recurses across children
+-->
+
+For some entities, specifically base entities, the implementation of effectors might need other tools (such as SSH), and may vary by location, so having a single implementation is not appropriate.
+
+The problem of multiple inheritance (e.g. SSH functionality and entity inheritance) and multiple implementations (e.g. SSH versus Windows) is handled in brooklyn using delegates called _drivers_. 
+
+In the implementations of ``JavaWebApp`` entities, the behaviour which the entity always does is captured in the entity class (for example, breaking deployment of multiple WARs into atomic actions), whereas implementations which is specific to a particular entity and driver (e.g. using scp to copy the WARs to the right place and install them, which of course is different among appservers, or using an HTTP or JMX management API, again where details vary between appservers) is captured in a driver class.
+
+Routines which are convenient for specific drivers can then be inherited in the driver class hierarchy. For example, when passing JMX environment variables to Java over SSH, ``JavaSoftwareProcessSshDriver`` extends ``AbstractSoftwareProcessSshDriver`` and parents ``JBoss7SshDriver``.
+
+<!---
+TODO more drivers such as jmx, etc are planned
+-->
+
+Testing
+-------
+
+* Unit tests can make use of `SimulatedLocation` and `TestEntity`, and can extend `BrooklynAppUnitTestSupport`.
+* Integration tests and use a `LocalhostMachineProvisioningLocation`, and can also extend `BrooklynAppUnitTestSupport`.
+
+
+<a name="SoftwareProcess-lifecycle"></a>
+
+SoftwareProcess Lifecycle
+-------------------------
+
+`SoftwareProcess` is the common super-type of most integration components (when implementing in Java).
+
+See ``JBoss7Server`` and ``MySqlNode`` for exemplars.
+
+The methods called in a `SoftwareProcess` entity's lifecycle are described below. The most important steps are shown in bold (when writing a new entity, these are the methods most often implemented).
+
+* Initial creation (via `EntitySpec` or YAML):
+  * **no-arg constructor**
+  * **init**
+  * add locations
+  * apply initializers
+  * add enrichers
+  * add policies
+  * add children
+  * manages entity (so is discoverable by other entities)
+
+* Start:
+  * provisions new machine, if the location is a `MachineProvisioningLocation`
+  * creates new driver
+    * **calls `getDriverInterface`**
+    * Infers the concrete driver class from the machine-type, 
+      e.g. by default it adds "Ssh" before the word "Driver" in "JBoss7Driver".
+    * instantiates the driver, **calling the constructor** to pass in the entity itself and the machine location
+  * sets attributes from config (e.g. for ports being used)
+  * calls `entity.preStart()`
+  * calls `driver.start()`, which:
+    * runs pre-install command (see config key `pre.install.command`)
+    * uploads install resources (see config keys `files.install` and `templates.install`)
+    * **calls `driver.install()`**
+    * runs post-install command (see config key `post.install.command`)
+    * **calls `driver.customize()`**
+    * uploads runtime resources (see config keys `files.runtime` and `templates.runtime`)
+    * runs pre-launch command (see config key `pre.launch.command`)
+    * **calls `driver.launch()`**
+    * runs post-launch command (see config key `post.launch.command`)
+    * calls `driver.postLaunch()`
+  * calls `entity.postDriverStart()`, which:
+    * calls `enity.waitForEntityStart()` - **waits for `driver.isRunning()` to report true**
+  * **calls `entity.connectSensors()`**
+  * calls `entity.waitForServicUp()`
+  * calls `entity.postStart()`
+
+* Restart:
+  * If restarting machine...
+    * calls `entity.stop()`, with `stopMachine` set to true.
+    * calls start
+    * restarts children (if configured to do so)
+  * Else (i.e. not restarting machine)...
+    * calls `entity.preRestart()`
+    * calls `driver.restart()`
+      * **calls `driver.stop()`**
+      * **calls `driver.launch()`**
+      * calls `driver.postLaunch()`
+    * restarts children (if configured to do so)
+    * calls `entity.postDriverStart()`, which:
+      * calls `enity.waitForEntityStart()` - **polls `driver.isRunning()`**, waiting for true
+    * calls `entity.waitForServicUp()`
+    * calls `entity.postStart()`
+
+* Stop:
+  * calls `entity.preStopConfirmCustom()` - aborts if exception.
+  * calls `entity.preStop()`
+  * stops the process:
+    * stops children (if configured to do so)
+    * **calls `driver.stop()`**
+  * stops the machine (if configured to do so)
+  * calls `entity.postStop()`
+
+* Rebind (i.e. when Brooklyn is restarted):
+  * **no-arg constructor**
+  * reconstitutes entity (e.g. setting config and attributes)
+  * If entity was running...
+    * calls `entity.rebind()`; if previously started then:
+      * creates the driver (same steps as for start)
+      * calls `driver.rebind()`
+      * **calls `entity.connectSensors()`**
+  * attaches policies, enrichers and persisted feeds
+  * manages the entity (so is discoverable by other entities)

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/entitlements.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/entitlements.md b/guide/blueprints/java/entitlements.md
new file mode 100644
index 0000000..59de4aa
--- /dev/null
+++ b/guide/blueprints/java/entitlements.md
@@ -0,0 +1,42 @@
+---
+title: Entitlements
+layout: website-normal
+---
+
+Brooklyn supports a plug-in system for defining "entitlements" -- 
+essentially permissions.
+
+Any entitlement scheme can be implemented by supplying a class which implements one method on one class:
+
+    public interface EntitlementManager {
+      public <T> boolean isEntitled(@Nullable EntitlementContext context, @Nonnull EntitlementClass<T> entitlementClass, @Nullable T entitlementClassArgument);
+    }
+
+This answers the question who is allowed do what to whom, looking at the following fields:
+
+* `context`: the user who is logged in and is attempting an action
+  (extensions can contain additional metadata)
+* `entitlementClass`: the type of action being queried, e.g. `DEPLOY_APPLICATION` or `SEE_SENSOR`
+  (declared in the class `Entitlements`)
+* `entitlementClassArgument`: details of the action being queried,
+  such as the blueprint in the case of `DEPLOY_APPLICATION` or the entity and sensor name in the case
+  of `SEE_SENSOR`
+
+To set a custom entitlements manager to apply across the board, simply use:
+
+    brooklyn.entitlements.global=org.apache.brooklyn.core.mgmt.entitlement.AcmeEntitlementManager
+
+The example above refers to a sample manager which is included in the test JARs of Brooklyn,
+which you can see [here]({{ site.brooklyn.url.git }}/core/src/test/java/org/apache/brooklyn/core/mgmt/entitlement/AcmeEntitlementManagerTest.java),
+and include in your project by adding the core tests JAR to your `dropins` folder.
+
+There are some entitlements schemes which exist out of the box, so for a simpler setup,
+see [Operations: Entitlements]({{ site.path.guide }}/ops/brooklyn_properties.html#entitlements). 
+
+There are also more complex schemes which some users have developed, including LDAP extensions 
+which re-use the LDAP authorization support in Brooklyn, 
+allowing permissions objects to be declared in LDAP leveraging regular expressions.
+For more information on this, ask on IRC or the mailing list,
+and see 
+{% include java_link.html class_name="EntitlementManager" package_path="org/apache/brooklyn/api/mgmt/entitlement" project_subpath="api" %}.
+

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/entity.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/entity.md b/guide/blueprints/java/entity.md
new file mode 100644
index 0000000..8b05d9c
--- /dev/null
+++ b/guide/blueprints/java/entity.md
@@ -0,0 +1,104 @@
+---
+layout: website-normal
+title: Writing an Entity
+---
+
+## Ways to write an entity
+
+There are several ways to write a new entity:
+
+* For Unix/Linux, write YAML blueprints, for example using a **`VanillaSoftwareProcess`** and 
+  configuring it with your scripts.
+* For Windows, write YAML blueprints using **`VanillaWindowsProcess`** and configure the PowerShell
+  scripts.
+* For composite entities, use YAML to compose exiting types of entities (potentially overwriting
+  parts of their configuration), and wire them together.
+* Use **[Chef recipes]({{site.path.guide}}/blueprints/chef)**.
+* Use **[Salt formulas]({{site.path.guide}}/blueprints/salt)**.
+* Use **[Ansible playbooks]({{site.path.guide}}/blueprints/ansible)**.
+* Write pure-java, extending existing base-classes. For example, the `GistGenerator` 
+  [example](defining-and-deploying.html). These can use utilities such as `HttpTool` and 
+  `BashCommands`.
+* Write pure-Java blueprints that extend `SoftwareProcess`. However, the YAML approach is strongly
+  recommended over this approach.
+* Write pure-Java blueprints that compose together existing entities, for example to manage
+  a cluster. Often this is possible in YAML and that approach is strongly recommended. However,
+  sometimes the management logic may be so complex that it is easier to use Java.
+
+The rest of this section covers writing an entity in pure-java (or other JVM languages).
+
+
+## Things To Know
+
+All entities have an interface and an implementation. The methods on the interface 
+are its effectors; the interface also defines its sensors.
+
+Entities are created through the management context (rather than calling the  
+constructor directly). This returns a proxy for the entity rather than the real 
+instance, which is important in a distributed management plane.
+
+All entity implementations inherit from `AbstractEntity`, often through one of the following:
+
+* **`SoftwareProcessImpl`**:  if it's a software process
+* **`VanillaJavaAppImpl`**:  if it's a plain-old-java app
+* **`JavaWebAppSoftwareProcessImpl`**:  if it's a JVM-based web-app
+* **`DynamicClusterImpl`**, **`DynamicGroupImpl`** or **`AbstractGroupImpl`**:  if it's a collection of other entities
+
+Software-based processes tend to use *drivers* to install and
+launch the remote processes onto *locations* which support that driver type.
+For example, `AbstractSoftwareProcessSshDriver` is a common driver superclass,
+targetting `SshMachineLocation` (a machine to which Brooklyn can ssh).
+The various `SoftwareProcess` entities above (and some of the exemplars 
+listed at the end of this page) have their own dedicated drivers.
+
+Finally, there are a collection of *traits*, such as `Resizable`, 
+in the package ``brooklyn.entity.trait``. These provide common
+sensors and effectors on entities, supplied as interfaces.
+Choose one (or more) as appropriate.
+
+
+
+## Key Steps
+
+*NOTE: Consider instead writing a YAML blueprint for your entity.*
+
+So to get started:
+
+1. Create your entity interface, extending the appropriate selection from above,
+   to define the effectors and sensors.
+2. Include an annotation like `@ImplementedBy(YourEntityImpl.class)` on your interface,
+   where `YourEntityImpl` will be the class name for your entity implementation.
+3. Create your entity class, implementing your entity interface and extending the 
+   classes for your chosen entity super-types. Naming convention is a suffix "Impl"
+   for the entity class, but this is not essential.
+4. Create a driver interface, again extending as appropriate (e.g. `SoftwareProcessDriver`).
+   The naming convention is to have a suffix "Driver". 
+5. Create the driver class, implementing your driver interface, and again extending as appropriate.
+   Naming convention is to have a suffix "SshDriver" for an ssh-based implementation.
+   The correct driver implementation is found using this naming convention, or via custom
+   namings provided by the `BasicEntityDriverFactory`.
+6. Wire the `public Class getDriverInterface()` method in the entity implementation, to specify
+   your driver interface.
+7. Provide the implementation of missing lifecycle methods in your driver class (details below)
+8. Connect the sensors from your entity (e.g. overriding `connectSensors()` of `SoftwareProcessImpl`)..
+   See the sensor feeds, such as `HttpFeed` and `JmxFeed`.
+
+Any JVM language can be used to write an entity. However use of pure Java is encouraged for
+entities in core brooklyn. 
+
+
+## Helpful References
+
+A few handy pointers will help make it easy to build your own entities.
+Check out some of the exemplar existing entities
+(note, some of the other entities use deprecated utilities and a deprecated class 
+hierarchy; it is suggested to avoid these, looking at the ones below instead):
+
+* `JBoss7Server`
+* `MySqlNode`
+
+You might also find the following helpful:
+
+* **[Entity Design Tips]({{site.path.guide}}/dev/tips/index.html#EntityDesign)**
+* The **[User Guide]({{site.path.guide}})**
+* The **[Mailing List](https://mail-archives.apache.org/mod_mbox/brooklyn-dev/)**

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/feeds.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/feeds.md b/guide/blueprints/java/feeds.md
new file mode 100644
index 0000000..4c151de
--- /dev/null
+++ b/guide/blueprints/java/feeds.md
@@ -0,0 +1,233 @@
+---
+title: Feeds
+layout: website-normal
+---
+
+<!-- TODO old, needs work (refactoring!) and use of java_link -->
+
+### Feeds
+
+`Feed`s within Apache Brooklyn are used to populate an entity's sensors. There are a variety of 
+feed types, which commonly poll to retrieve the raw metrics of the entity (for example polling an 
+HTTP management API, or over JMX).  
+
+
+#### Persistence
+
+There are two ways to associate a feed with an entity.
+
+The first way is (within the entity) to call `feeds().addFeed(...)`.
+This persists the feed: the feed will be automatically
+added to the entity when the Brooklyn server restarts. It is important that all configuration
+of the feed is persistable (e.g. not using any in-line anonymous inner classes to define
+functions).
+
+The feed builders can be passed a `uniqueTag(...)`, which will be used to ensure that on
+rebind there will not be multiple copied of the feed (e.g. if `rebind()` had already re-created
+the feed).
+
+The second way is to just pass to the feed's builder the entity. When using this mechanism, 
+the feed will be wired up to the entity but it will not be persisted. In this case, it is
+important that the entity's `rebind()` method recreates the feed.
+
+
+#### Types of Feed
+
+##### HTTP Feed
+
+An `HttpFeed` polls over http(s). An example is shown below:
+
+{% highlight java %}
+private HttpFeed feed;
+
+@Override
+protected void connectSensors() {
+  super.connectSensors();
+  
+  feed = feeds().addFeed(HttpFeed.builder()
+      .period(200)
+      .baseUri(String.format("http://%s:%s/management/subsystem/web/connector/http/read-resource", host, port))
+      .baseUriVars(ImmutableMap.of("include-runtime","true"))
+      .poll(new HttpPollConfig(SERVICE_UP)
+          .onSuccess(HttpValueFunctions.responseCodeEquals(200))
+          .onError(Functions.constant(false)))
+      .poll(new HttpPollConfig(REQUEST_COUNT)
+          .onSuccess(HttpValueFunctions.jsonContents("requestCount", Integer.class)))
+      .build());
+}
+
+@Override
+protected void disconnectSensors() {
+  super.disconnectSensors();
+  if (feed != null) feed.stop();
+}
+{% endhighlight %}
+
+
+##### SSH Feed
+
+An SSH feed executes a command over ssh periodically. An example is shown below:
+
+{% highlight java %}
+private AbstractCommandFeed feed;
+
+@Override
+protected void connectSensors() {
+  super.connectSensors();
+
+  feed = feeds.addFeed(SshFeed.builder()
+      .machine(mySshMachineLachine)
+      .poll(new CommandPollConfig(SERVICE_UP)
+          .command("rabbitmqctl -q status")
+          .onSuccess(new Function() {
+              public Boolean apply(SshPollValue input) {
+                return (input.getExitStatus() == 0);
+              }}))
+      .build());
+}
+
+@Override
+protected void disconnectSensors() {
+  super.disconnectSensors();
+  if (feed != null) feed.stop();
+}
+{% endhighlight %}
+
+##### WinRm CMD Feed
+
+A WinRM feed executes a windows command over winrm periodically. An example is shown below:
+
+{% highlight java %}
+private AbstractCommandFeed feed;
+
+//@Override
+protected void connectSensors() {
+  super.connectSensors();
+
+  feed = feeds.addFeed(CmdFeed.builder()
+                .entity(entity)
+                .machine(machine)
+                .poll(new CommandPollConfig<String>(SENSOR_STRING)
+                        .command("ipconfig")
+                        .onSuccess(SshValueFunctions.stdout()))
+                .build());
+}
+
+@Override
+protected void disconnectSensors() {
+  super.disconnectSensors();
+  if (feed != null) feed.stop();
+}
+{% endhighlight %}
+
+##### Windows Performance Counter Feed
+
+This type of feed retrieves performance counters from a Windows host, and posts the values to sensors.
+
+One must supply a collection of mappings between Windows performance counter names and Brooklyn 
+attribute sensors.
+
+This feed uses WinRM to invoke the windows utility <tt>typeperf</tt> to query for a specific set 
+of performance counters, by name. The values are extracted from the response, and published to the
+entity's sensors. An example is shown below:
+
+{% highlight java %}
+private WindowsPerformanceCounterFeed feed;
+
+@Override
+protected void connectSensors() {
+  feed = feeds.addFeed(WindowsPerformanceCounterFeed.builder()
+      .addSensor("\\Processor(_total)\\% Idle Time", CPU_IDLE_TIME)
+      .addSensor("\\Memory\\Available MBytes", AVAILABLE_MEMORY)
+      .build());
+}
+
+@Override
+protected void disconnectSensors() {
+  super.disconnectSensors();
+  if (feed != null) feed.stop();
+}
+{% endhighlight %}
+
+
+##### JMX Feed
+
+This type of feed queries over JMX to retrieve sensor values. This can query attribute
+values or call operations.
+
+The JMX connection details can be automatically inferred from the entity's standard attributes,
+or it can be explicitly supplied.
+
+An example is shown below:
+
+{% highlight java %}
+private JmxFeed feed;
+
+@Override
+protected void connectSensors() {
+  super.connectSensors();
+
+  feed = feeds().addFeed(JmxFeed.builder()
+      .period(5, TimeUnit.SECONDS)
+      .pollAttribute(new JmxAttributePollConfig<Integer>(ERROR_COUNT)
+          .objectName(requestProcessorMbeanName)
+          .attributeName("errorCount"))
+      .pollAttribute(new JmxAttributePollConfig<Boolean>(SERVICE_UP)
+          .objectName(serverMbeanName)
+          .attributeName("Started")
+          .onError(Functions.constant(false)))
+      .build());
+}
+
+Override
+protected void disconnectSensors() {
+  super.disconnectSensors();
+  if (feed != null) feed.stop();
+}
+{% endhighlight %}
+
+
+
+##### Function Feed
+
+This type of feed periodically executes something to compute the attribute values. This 
+can be a `Callable`, `Supplier` or Groovy `Closure`. It must be persistable (e.g. not use 
+an in-line anonymous inner classes).
+
+An example is shown below:
+
+{% highlight java %}
+public static class ErrorCountRetriever implements Callable<Integer> {
+  private final Entity entity;
+  
+  public ErrorCountRetriever(Entity entity) {
+    this.entity = entity;
+  }
+  
+  @Override
+  public Integer call() throws Exception {
+    // TODO your implementation...
+    return 0;
+  }
+}
+
+private FunctionFeed feed;
+
+@Override
+protected void connectSensors() {
+  super.connectSensors();
+
+  feed = feeds().addFeed(FunctionFeed.builder()
+    .poll(new FunctionPollConfig<Object, Integer>(ERROR_COUNT)
+        .period(500, TimeUnit.MILLISECONDS)
+        .callable(new ErrorCountRetriever(this))
+        .onExceptionOrFailure(Functions.<Integer>constant(null))
+    .build());
+}
+ 
+@Override
+protected void disconnectSensors() {
+  super.disconnectSensors();
+  if (feed != null) feed.stop();
+}
+{% endhighlight %}

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/GistGenerator.java
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/GistGenerator.java b/guide/blueprints/java/gist_generator/GistGenerator.java
new file mode 100644
index 0000000..678d1e0
--- /dev/null
+++ b/guide/blueprints/java/gist_generator/GistGenerator.java
@@ -0,0 +1,29 @@
+package com.acme;
+
+import java.io.IOException;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.ImplementedBy;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.annotation.Effector;
+import org.apache.brooklyn.core.annotation.EffectorParam;
+import org.apache.brooklyn.core.config.ConfigKeys;
+
+@ImplementedBy(GistGeneratorImpl.class)
+public interface GistGenerator extends Entity {
+
+    ConfigKey<String> OAUTH_KEY = ConfigKeys.newStringConfigKey("oauth.key", "OAuth key for creating a gist",
+            "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+
+    @Effector(description="Create a Gist")
+    String createGist(
+            @EffectorParam(name="gistName", description="Gist Name", defaultValue="Demo Gist") String gistName,
+            @EffectorParam(name="fileName", description="File Name", defaultValue="Hello.java") String fileName,
+            @EffectorParam(name="gistContents", description="Gist Contents", defaultValue="System.out.println(\"Hello World\");") String gistContents,
+            @EffectorParam(name="oauth.key", description="OAuth key for creating a gist", defaultValue="") String oauthKey) throws IOException;
+
+    @Effector(description="Retrieve a Gist")
+    public String getGist(
+            @EffectorParam(name="id", description="Gist id") String id,
+            @EffectorParam(name="oauth.key", description="OAuth key for creating a gist", defaultValue="") String oauthKey) throws IOException;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/GistGeneratorImpl.java
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/GistGeneratorImpl.java b/guide/blueprints/java/gist_generator/GistGeneratorImpl.java
new file mode 100644
index 0000000..db1ecdb
--- /dev/null
+++ b/guide/blueprints/java/gist_generator/GistGeneratorImpl.java
@@ -0,0 +1,47 @@
+package com.acme;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import org.apache.brooklyn.core.entity.AbstractEntity;
+import org.apache.brooklyn.util.text.Strings;
+import org.eclipse.egit.github.core.Gist;
+import org.eclipse.egit.github.core.GistFile;
+import org.eclipse.egit.github.core.service.GistService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Iterables;
+
+public class GistGeneratorImpl extends AbstractEntity implements GistGenerator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GistGeneratorImpl.class);
+
+    @Override
+    public String createGist(String gistName, String fileName, String gistContents, String oathToken) throws IOException {
+        if (Strings.isBlank(oathToken)) oathToken = config().get(OAUTH_KEY);
+
+        GistFile file = new GistFile();
+        file.setContent(gistContents);
+        Gist gist = new Gist();
+        gist.setDescription(gistName);
+        gist.setFiles(Collections.singletonMap(fileName, file));
+        gist.setPublic(true);
+        
+        GistService service = new GistService();
+        service.getClient().setOAuth2Token(oathToken);
+        LOG.info("Creating Gist: " +  gistName);
+        Gist result = service.createGist(gist);
+        return result.getId();
+    }
+    
+    @Override
+    public String getGist(String id, String oathToken) throws IOException {
+        if (Strings.isBlank(oathToken)) oathToken = config().get(OAUTH_KEY);
+
+        GistService service = new GistService();
+        service.getClient().setOAuth2Token(oathToken);
+        Gist gist = service.getGist(id);
+        return Iterables.getOnlyElement(gist.getFiles().values()).getContent();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/GistGeneratorTest.java
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/GistGeneratorTest.java b/guide/blueprints/java/gist_generator/GistGeneratorTest.java
new file mode 100644
index 0000000..9f5cc1a
--- /dev/null
+++ b/guide/blueprints/java/gist_generator/GistGeneratorTest.java
@@ -0,0 +1,20 @@
+package com.acme;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport;
+import org.testng.annotations.Test;
+
+public class GistGeneratorTest extends BrooklynAppUnitTestSupport {
+
+    @Test
+    public void testEntity() throws Exception {
+        String oathKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+        GistGenerator entity = app.createAndManageChild(EntitySpec.create(GistGenerator.class));
+        String id = entity.createGist("myGistName", "myFileName", "myGistContents", oathKey);
+        
+        String contents = entity.getGist(id, oathKey);
+        assertEquals(contents, "myGistContents");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/GistGeneratorYamlTest.java
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/GistGeneratorYamlTest.java b/guide/blueprints/java/gist_generator/GistGeneratorYamlTest.java
new file mode 100644
index 0000000..2051993
--- /dev/null
+++ b/guide/blueprints/java/gist_generator/GistGeneratorYamlTest.java
@@ -0,0 +1,39 @@
+package com.acme;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.core.entity.Entities;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+
+public class GistGeneratorYamlTest extends AbstractYamlTest {
+
+    private String contents;
+
+    @Test
+    public void testEntity() throws Exception {
+        String oathKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
+        
+        String yaml = Joiner.on("\n").join(
+            "name: my test",
+            "services:",
+            "- type: com.acme.GistGenerator",
+            "  brooklyn.config:",
+            "    oauth.key: "+oathKey);
+        
+        Entity app = createAndStartApplication(yaml);
+        waitForApplicationTasks(app);
+
+        Entities.dumpInfo(app);
+
+        GistGenerator entity = (GistGenerator) Iterables.getOnlyElement(app.getChildren());
+        String id = entity.createGist("myGistName", "myFileName", "myGistContents", null);
+        
+        contents = entity.getGist(id, null);
+        assertEquals(contents, "myGistContents");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/gist_create_token.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/gist_create_token.png b/guide/blueprints/java/gist_generator/gist_create_token.png
new file mode 100644
index 0000000..2a9f621
Binary files /dev/null and b/guide/blueprints/java/gist_generator/gist_create_token.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/gist_generator.bom
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/gist_generator.bom b/guide/blueprints/java/gist_generator/gist_generator.bom
new file mode 100644
index 0000000..e07ff65
--- /dev/null
+++ b/guide/blueprints/java/gist_generator/gist_generator.bom
@@ -0,0 +1,14 @@
+brooklyn.catalog:
+  libraries:
+  - http://search.maven.org/remotecontent?filepath=com/google/code/gson/gson/2.2.2/gson-2.2.2.jar
+  - http://repo1.maven.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.egit.github.core/2.1.5_1/org.apache.servicemix.bundles.egit.github.core-2.1.5_1.jar
+  - http://developers.cloudsoftcorp.com/brooklyn/guide/blueprints/java/gist_generator/autobrick-0.1.0-SNAPSHOT.jar
+  id: example.GistGenerator
+  version: "0.1.0-SNAPSHOT"
+  itemType: template
+  description: For programmatically generating GitHub Gists
+  displayName: Gist Generator
+  iconUrl: classpath:///sample-icon.png
+  item:
+    services:
+    - type: com.acme.GistGenerator

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/gist_generator/gist_grant_access.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/gist_generator/gist_grant_access.png b/guide/blueprints/java/gist_generator/gist_grant_access.png
new file mode 100644
index 0000000..48cc669
Binary files /dev/null and b/guide/blueprints/java/gist_generator/gist_grant_access.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/index.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/index.md b/guide/blueprints/java/index.md
new file mode 100644
index 0000000..1cd025e
--- /dev/null
+++ b/guide/blueprints/java/index.md
@@ -0,0 +1,36 @@
+---
+title: Java Entities
+title_in_menu: Java Entities
+layout: website-normal
+started-pdf-exclude: true
+children:
+- archetype.md
+- defining-and-deploying.md
+- bundle-dependencies.md
+- topology-dependencies.md
+- common-usage.md
+- feeds.md
+- entity.md
+- entities.md
+- service-state.md
+- entitlements.md
+---
+
+Java blueprints are powerful, but also rather more difficult to write than YAML.
+Advanced Java skills are required.
+
+{% include list-children.html %}
+
+The main uses of Java-based blueprints are:
+
+* Integration with a service's API (e.g. for an on-line DNS service). This could take advantage of
+  existing Java-based clients, or of Java's flexibility to chain together multiple calls.
+* Complex management logic, for example when the best practices for adding/removing nodes from a
+  cluster is fiddly and has many conditionals.
+* Where the developer has a strong preference for Java. Anything that can be done in YAML can be done in
+  the Java API. Once the blueprint is added to the catalog, the use of Java will be entirely hidden
+  from users of that blueprint.
+
+The Apache Brooklyn community is striving to make YAML-based blueprints as simple as possible -
+if you come across a use-case that is hard to do in YAML then please let the community know.
+

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/java_app/ExampleWebApp.java
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/java_app/ExampleWebApp.java b/guide/blueprints/java/java_app/ExampleWebApp.java
new file mode 100644
index 0000000..525a2bd
--- /dev/null
+++ b/guide/blueprints/java/java_app/ExampleWebApp.java
@@ -0,0 +1,62 @@
+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, 
+                                "http://search.maven.org/remotecontent?filepath=org/apache/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.8.0-incubating/brooklyn-example-hello-world-sql-webapp-0.8.0-incubating.war")
+                        .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));
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/service-state.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/service-state.md b/guide/blueprints/java/service-state.md
new file mode 100644
index 0000000..2abbf65
--- /dev/null
+++ b/guide/blueprints/java/service-state.md
@@ -0,0 +1,73 @@
+---
+title: Service State
+layout: website-normal
+toc: ../guide_toc.json
+categories: [use, guide, defining-applications]
+---
+
+Any entity can use the standard "service-up" and "service-state" 
+sensors to inform other entities and the GUI about its status.
+
+In normal operation, entities should publish at least one "service not-up indicator",
+using the `ServiceNotUpLogic.updateNotUpIndicator` method.  Each such indicator should have
+a unique name or input sensor.  `Attributes.SERVICE_UP` will then be updated automatically
+when there are no not-up indicators.
+
+When there are transient problems that can be detected, to trigger `ON_FIRE` status
+entity code can similarly set `ServiceProblemsLogic.updateProblemsIndicator` with a unique namespace,
+and subsequently clear it when the problem goes away.
+These problems are reflected at runtime in the `SERVICE_PROBLEMS` sensor,
+allowing multiple problems to be tracked independently.
+
+When an entity is changing the expected state, e.g. starting or stopping,
+the expected state can be set using `ServiceStateLogic.setExpectedState`;
+this expected lifecycle state is considered together with `SERVICE_UP` and `SERVICE_PROBLEMS`
+to compute the actual state.  By default the logic in `ComputeServiceState` is applied.
+
+For common entities, good out-of-the-box logic is applied, as follows:
+
+* For `SoftwareProcess` entities, lifecycle service state is updated by the framework
+  and a service not-up indicator is linked to the driver `isRunning()` check.
+  
+* For common parents, including `AbstractApplication` and `AbstractGroup` subclasses (including clusters, fabrics, etc),
+  the default enrichers analyse children and members to set a not-up indicator
+  (requiring at least one child or member who is up) and a problem indicator
+  (if any children or members are on-fire).
+  In some cases other quorum checks are preferable; this can be set e.g. by overriding 
+  the `UP_QUORUM_CHECK` or the `RUNNING_QUORUM_CHECK`, as follows:
+  
+      public static final ConfigKey<QuorumCheck> UP_QUORUM_CHECK = ConfigKeys.newConfigKeyWithDefault(AbstractGroup.UP_QUORUM_CHECK, 
+          "Require all children and members to be up for this node to be up",
+          QuorumChecks.all());
+
+  Alternatively the `initEnrichers()` method can be overridden to specify a custom-configured
+  enricher or set custom config key values (as done e.g. in `DynamicClusterImpl` so that
+  zero children is permitted provided when the initial size is configured to be 0).
+
+
+For sample code to set and more information on these methods' behaviours,
+see javadoc in `ServiceStateLogic`,
+overrides of `AbstractEntity.initEnrichers()`
+and tests in `ServiceStateLogicTests`.
+
+<!-- TODO include more documentation, sample code (ideally extracted on the fly from test cases so we know it works!) -->
+
+
+## Notes on Advanced Use
+
+The enricher to derive `SERVICE_UP` and `SERVICE_STATE_ACTUAL` from the maps and expected state values discussed above
+is added by the `AbstractEntity.initEnrichers()` method.
+This method can be overridden -- or excluded altogether by by overriding `init()` --
+and can add enrichers created using the `ServiceStateLogic.newEnricherFromChildren()` method
+suitably customized using methods on the returned spec object, for instance to look only at members
+or specify a quorum function (from `QuorumChecks`). 
+If different logic is required for computing `SERVICE_UP` and `SERVICE_STATE_ACTUAL`,
+use `ServiceStateLogic.newEnricherFromChildrenState()` and `ServiceStateLogic.newEnricherFromChildrenUp()`,
+noting that the first of these will replace the enricher added by the default `initEnrichers()`,
+whereas the second one runs with a different namespace (unique tag).
+For more information consult the javadoc on those classes.
+
+Entities can set `SERVICE_UP` and `SERVICE_STATE_ACTUAL` directly.
+Provided these entities never use the `SERVICE_NOT_UP_INDICATORS` and `SERVICE_PROBLEMS` map,
+the default enrichers will not override these values.
+

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/topology-dependencies.md
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/topology-dependencies.md b/guide/blueprints/java/topology-dependencies.md
new file mode 100644
index 0000000..93bbce3
--- /dev/null
+++ b/guide/blueprints/java/topology-dependencies.md
@@ -0,0 +1,53 @@
+---
+layout: website-normal
+title: Topology, Dependencies, and Management Policies
+title_in_menu: 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]({{ site.path.guide }}/start/policies.html), but also includes the MySQL database
+to demonstrate the use of dependent configuration.
+
+{% highlight java %}
+{% readj java_app/ExampleWebApp.java %}
+{% endhighlight %}
+
+To describe each part of this:
+
+* The application extends `AbstractApplication`.
+* It implements `init()`, to add its child entities. The `init` method is called only once, when
+  instantiating the entity instance.
+* The `addChild` method takes an `EntitySpec`. This describes the entity to be created, defining
+  its type and its configuration.
+* The `brooklyn.example.db.url` is a system property that will be passed to each `TomcatServer` 
+  instance. 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 `NginxController` is the load-balancer and reverse-proxy: by default, it round-robins to 
+  the ip:port of each member of the cluster configured as the `SERVER_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).

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/wt-deployed-application-700.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/wt-deployed-application-700.png b/guide/blueprints/java/wt-deployed-application-700.png
new file mode 100644
index 0000000..7ef90d9
Binary files /dev/null and b/guide/blueprints/java/wt-deployed-application-700.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/wt-deployed-application.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/wt-deployed-application.png b/guide/blueprints/java/wt-deployed-application.png
new file mode 100644
index 0000000..751402e
Binary files /dev/null and b/guide/blueprints/java/wt-deployed-application.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/wt-starting-700.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/wt-starting-700.png b/guide/blueprints/java/wt-starting-700.png
new file mode 100644
index 0000000..c87a539
Binary files /dev/null and b/guide/blueprints/java/wt-starting-700.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/wt-starting.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/wt-starting.png b/guide/blueprints/java/wt-starting.png
new file mode 100644
index 0000000..970805f
Binary files /dev/null and b/guide/blueprints/java/wt-starting.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/wt-tree-jboss-sensors-700.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/wt-tree-jboss-sensors-700.png b/guide/blueprints/java/wt-tree-jboss-sensors-700.png
new file mode 100644
index 0000000..3dfc7f2
Binary files /dev/null and b/guide/blueprints/java/wt-tree-jboss-sensors-700.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/java/wt-tree-jboss-sensors.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/java/wt-tree-jboss-sensors.png b/guide/blueprints/java/wt-tree-jboss-sensors.png
new file mode 100644
index 0000000..4c44ea9
Binary files /dev/null and b/guide/blueprints/java/wt-tree-jboss-sensors.png differ

http://git-wip-us.apache.org/repos/asf/brooklyn-docs/blob/1330dcd3/guide/blueprints/logstash-snapshot.png
----------------------------------------------------------------------
diff --git a/guide/blueprints/logstash-snapshot.png b/guide/blueprints/logstash-snapshot.png
new file mode 100644
index 0000000..07ad4bf
Binary files /dev/null and b/guide/blueprints/logstash-snapshot.png differ