You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by an...@apache.org on 2016/11/13 22:28:44 UTC

[4/4] incubator-tamaya git commit: TAMAYA-195: Added hazelcast support (small multi VM JavaFX Demo).

TAMAYA-195: Added hazelcast support (small multi VM JavaFX Demo).


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/57df9012
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/57df9012
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/57df9012

Branch: refs/heads/master
Commit: 57df9012d1ef6e736b925a41df2c2c60fe460110
Parents: fcf2730
Author: anatole <an...@apache.org>
Authored: Sun Nov 13 23:27:18 2016 +0100
Committer: anatole <an...@apache.org>
Committed: Sun Nov 13 23:27:18 2016 +0100

----------------------------------------------------------------------
 examples/11-distributed/pom.xml                 |  85 ++++++
 .../distributed/ContentManagerPanel.java        | 122 ++++++++
 .../tamaya/examples/distributed/Display.java    | 293 +++++++++++++++++++
 .../examples/distributed/DisplayContent.java    |  59 ++++
 .../examples/distributed/DisplayManager.java    | 276 +++++++++++++++++
 .../distributed/DisplayRegistration.java        | 123 ++++++++
 .../org.apache.tamaya.spi.PropertySource        |  19 ++
 .../src/main/resources/stylesheet.css           |  38 +++
 .../distributed/DisplayContentTest.java         |  48 +++
 .../distributed/DisplayRegistrationTest.java    |  70 +++++
 10 files changed, 1133 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/pom.xml
----------------------------------------------------------------------
diff --git a/examples/11-distributed/pom.xml b/examples/11-distributed/pom.xml
new file mode 100644
index 0000000..5c5b8d3
--- /dev/null
+++ b/examples/11-distributed/pom.xml
@@ -0,0 +1,85 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing,
+  ~  software distributed under the License is distributed on an
+  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~  KIND, either express or implied.  See the License for the
+  ~  specific language governing permissions and limitations
+  ~  under the License.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.tamaya.ext</groupId>
+        <artifactId>tamaya-examples</artifactId>
+        <version>0.3-incubating-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <artifactId>tamaya-example-distributed</artifactId>
+    <groupId>org.apache.tamaya.examples</groupId>
+    <name>Apache Tamaya Example: Distributed Configuration</name>
+    <description>This project contains a simple example based on JavaFX and Vertx.</description>
+    <packaging>jar</packaging>
+
+    <properties>
+        <jdkVersion>1.8</jdkVersion>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.tamaya</groupId>
+            <artifactId>tamaya-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-injection-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-injection</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-core</artifactId>
+            <version>3.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-mutable-config</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.vertx</groupId>
+            <artifactId>vertx-hazelcast</artifactId>
+            <version>3.3.3</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.tamaya.ext</groupId>
+            <artifactId>tamaya-hazelcast</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.hamcrest</groupId>
+            <artifactId>java-hamcrest</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/ContentManagerPanel.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/ContentManagerPanel.java b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/ContentManagerPanel.java
new file mode 100644
index 0000000..9ac7aeb
--- /dev/null
+++ b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/ContentManagerPanel.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tamaya.examples.distributed;
+
+import com.sun.deploy.uitoolkit.impl.fx.ui.FXAppContext;
+import io.vertx.core.Vertx;
+import io.vertx.core.json.Json;
+import javafx.application.Platform;
+import javafx.embed.swing.SwingFXUtils;
+import javafx.geometry.Orientation;
+import javafx.scene.control.*;
+import javafx.scene.layout.VBox;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontWeight;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.functions.ConfigurationFunctions;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * Created by atsticks on 13.11.16.
+ */
+class ContentManagerPanel extends VBox{
+
+    private ChoiceBox selector = new ChoiceBox();
+    private TextField titleField = new TextField();
+    private TextArea contentField = new TextArea();
+    private TextField displayNameField = new TextField();
+    private Button sendButton = new Button("Update Content");
+    private Configuration config;
+    private Vertx vertx;
+
+    public ContentManagerPanel(Vertx vertx){
+        this.vertx = vertx;
+        displayNameField.setMinHeight(30.0);
+        displayNameField.setMinWidth(200.0);
+        displayNameField.setId("displayNameField");
+        titleField.setMinHeight(30.0);
+        titleField.setMinWidth(200.0);
+        titleField.setId("title");
+        titleField.setFont(Font.font("Arial", FontWeight.BOLD, 24));
+        titleField.setStyle("-fx-text-fill: #EFEFEF; -fx-background-color: black;");
+        contentField.setId("scene");
+        contentField.setFont(Font.font("Arial", FontWeight.LIGHT, 18));
+        getChildren().addAll(selector, new Label("Title"), titleField, new Label("content"), contentField,
+                new Label("Display Name"), displayNameField, new Separator(Orientation.VERTICAL), sendButton);
+        sendButton.setOnAction(h -> {
+            String selection = (String)selector.getSelectionModel().getSelectedItem();
+            if(selection!=null){
+                String uuid = selection.split("::")[1];
+                DisplayContent content = new DisplayContent();
+                content.content.put(Display.CONTENT_FIELD, contentField.getText());
+                content.title = titleField.getText();
+                content.displayId = uuid;
+                content.displayName = displayNameField.getText();
+                vertx.eventBus().publish(Display.DISPLAY_SHOW_TOPIC, Json.encode(content));
+            }
+        });
+        selector.setOnAction(h -> {
+            String selection = (String)selector.getSelectionModel().getSelectedItem();
+            if(selection!=null) {
+                displayNameField.setText(selection.split("::")[0]);
+            }
+        });
+        updateList();
+        vertx.periodicStream(5000).handler(h -> {
+            updateList();
+        });
+    }
+
+    public void updateList(){
+        config = ConfigurationProvider.getConfiguration()
+                .with(ConfigurationFunctions.section("displays.", true));
+        // resulting config:
+        // -----------------
+        // UUID.displayName
+        // UUID.content.title
+        // UUID.content.content
+        // UUID.timestamp
+        final Set<String> keys = new TreeSet<>();
+        for(Map.Entry<String,String> en:config.getProperties().entrySet()){
+            if(en.getKey().endsWith(".displayName")){
+                String uuid = en.getKey().substring(0,36);
+                keys.add(en.getValue()+"::"+uuid);
+            }
+        }
+        Platform.runLater(() -> {
+            final Set<String> exKeys = new HashSet<String>(selector.getItems());
+            for(Object item:exKeys){
+                if(!keys.contains(item)){
+                    selector.getItems().remove(item);
+                }
+            }
+            for(String item:keys){
+                if(!selector.getItems().contains(item)){
+                    selector.getItems().add(item);
+                }
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/Display.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/Display.java b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/Display.java
new file mode 100644
index 0000000..fb95a07
--- /dev/null
+++ b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/Display.java
@@ -0,0 +1,293 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.tamaya.examples.distributed;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.json.Json;
+import io.vertx.core.spi.cluster.ClusterManager;
+import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.scene.Group;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.scene.control.*;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.stage.Stage;
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.core.propertysource.EnvironmentPropertySource;
+import org.apache.tamaya.core.propertysource.SystemPropertySource;
+import org.apache.tamaya.functions.ConfigurationFunctions;
+import org.apache.tamaya.hazelcast.HazelcastPropertySource;
+import org.apache.tamaya.inject.ConfigurationInjection;
+import org.apache.tamaya.inject.api.Config;
+import org.apache.tamaya.spi.*;
+
+import java.time.LocalDateTime;
+import java.util.logging.Logger;
+
+/**
+ * Created by atsticks on 12.11.16.
+ */
+public class Display extends Application{
+
+    private static final Logger LOG = Logger.getLogger(Display.class.getSimpleName());
+
+    public static final String DISPLAY_SHOW_TOPIC = "Display::show";
+    public static final String DISPLAY_REGISTER_TOPIC = "Display::register";
+    public static final String CONTENT_FIELD = "content";
+
+    @Config(defaultValue="UNKNOWN DISPLAY")
+    private String displayName;
+
+    private Scene scene;
+
+    private Group root = new Group();
+
+    private Stage stage;
+
+    private TextField titleField = new TextField("title");
+
+    private TextField configFilterField = new TextField("");
+
+    private TextArea contentField = new TextArea("scene");
+
+    private TextArea monitorField = new TextArea("monitor");
+
+    private DisplayContent displayContent = new DisplayContent();
+
+    private DisplayRegistration registration;
+
+    private StringBuffer monitorBuffer = new StringBuffer();
+
+    private Vertx vertx;
+
+    private static HazelcastPropertySource hazelCastPropertySource;
+
+    public Display(){
+        LOG.info("\n-----------------------------------\n" +
+                "Starting Display...\n" +
+                "-----------------------------------");
+        LOG.info("--- Starting Vertx cluster...");
+        // Reusing the hazelcast instance already in place for vertx...
+        ClusterManager mgr = new HazelcastClusterManager(
+                hazelCastPropertySource.getHazelcastInstance());
+        VertxOptions vertxOptions = new VertxOptions().setClusterManager(mgr);
+        Vertx.clusteredVertx(vertxOptions, h -> {
+            vertx = h.result();
+        });
+        LOG.info("--- Waiting for Vertx cluster...");
+        while(vertx==null){
+            try {
+                Thread.sleep(100L);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        titleField.getStyleClass().add("title");
+        contentField.getStyleClass().add("content");
+        monitorField.getStyleClass().add("monitor");
+        titleField.setId("title");
+        titleField.setEditable(false);
+        contentField.setId("scene");
+        contentField.setEditable(false);
+    }
+
+    @Override
+    public void start(Stage stage) throws Exception {
+        this.stage = stage;
+        LOG.info("--- Configuring application...");
+        ConfigurationInjection.getConfigurationInjector()
+                .configure(this);
+        LOG.info("--- Registering display...");
+        registerDisplay();
+        LOG.info("--- Starting stage...");
+        initStage(stage);
+        registerListeners();
+        LOG.info("--- Showing stage...");
+        stage.show();
+        LOG.info("\n---------------\n" +
+                 "Display started\n" +
+                 "---------------");
+    }
+
+    private void registerDisplay() {
+        registration = new DisplayRegistration(displayName);
+        logToMonitor("Display started at " + LocalDateTime.now() +
+                "\n  id   = " + registration.getId() +
+                "\n  name = " + registration.getDisplayName());
+        // Register in the shared map every 10 seconds, with a TTL of 20 seconds...
+        vertx.eventBus().publish(DISPLAY_REGISTER_TOPIC, Json.encode(registration));
+        vertx.periodicStream(10000).handler(time -> {
+            registration = registration.update();
+            vertx.eventBus().publish(DISPLAY_REGISTER_TOPIC, Json.encode(registration));
+            vertx.sharedData().getClusterWideMap("displays", h -> {
+                h.result().put(registration.getId(), registration, 20000L, null);
+            });
+        });
+    }
+
+    private void registerListeners() {
+        // registering update hook
+        vertx.eventBus().consumer(DISPLAY_SHOW_TOPIC, h -> {
+            DisplayContent content = Json.decodeValue((String)h.body(), DisplayContent.class);
+            logToMonitor("NEW CONTENT: " + content.toString());
+            if(registration.getId().equals(content.displayId)) {
+                logToMonitor("Applying content: " + content + "...");
+                titleField.setText(content.title);
+                contentField.setText(content.content.get(CONTENT_FIELD));
+                if(content.displayName!=null) {
+                    this.registration.setDisplayName(
+                            content.displayName
+                    );
+                    Platform.runLater(() -> {
+                        this.stage.setTitle(content.displayName);
+                    });
+                }
+                logToMonitor("SUCCESS.");
+            }
+        });
+        vertx.eventBus().consumer(DISPLAY_REGISTER_TOPIC, h -> {
+            DisplayRegistration registration = Json.decodeValue((String)h.body(), DisplayRegistration.class);
+            logToMonitor("NEW DISPLAY: " + registration.toString());
+        });
+    }
+
+    private void initStage(Stage stage) {
+        stage.setTitle(registration.getDisplayName());
+        scene = new Scene(root, Color.WHITE);
+        scene.getStylesheets().add("/stylesheet.css");
+
+        BorderPane layout = new BorderPane();
+        layout.getStyleClass().add("main-layout");
+        layout.setPrefSize(600, 400);
+//        layout.setTop(createWinTitle());
+
+        Node displayPanel = createDisplayNode();
+        Node monitorPanel = createMonitorNode();
+
+        TabPane tabPane = new TabPane();
+        tabPane.getStylesheets().add("main-tabs");
+        Tab tab0 = new Tab("Display", displayPanel);
+        tab0.setClosable(false);
+        Tab tab1 = new Tab("Monitor", monitorPanel);
+        tab1.setClosable(false);
+        tabPane.getTabs().add(0, tab0);
+        tabPane.getTabs().add(1, tab1);
+        layout.setCenter(tabPane);
+        layout.setBottom(createStatusPane());
+        scene.setRoot(layout);
+        stage.setScene(scene);
+    }
+
+    private Node createStatusPane() {
+        return new Label();
+    }
+
+    private Node createMonitorNode() {
+        VBox vbox = new VBox();
+        ScrollPane monitorPane = new ScrollPane(monitorField);
+        monitorPane.setFitToHeight(true);
+        monitorPane.setFitToWidth(true);
+        monitorField.setPrefSize(2000,2000);
+        vbox.getChildren().addAll(monitorPane);
+        return vbox;
+    }
+
+    private Node createDisplayNode() {
+        VBox vbox = new VBox();
+        ScrollPane contentPane = new ScrollPane(contentField);
+        contentPane.setFitToHeight(true);
+        contentPane.setFitToWidth(true);
+        titleField.setText("- Nothing to show -");
+        contentField.setText("- Nothing to show -");
+        vbox.getChildren().addAll(titleField, contentPane, createButtonPane());
+        return vbox;
+    }
+
+    private Pane createButtonPane() {
+        HBox buttonLayout = new HBox();
+        buttonLayout.getStyleClass().add("button-pane");
+        Button showConfig = new Button("Show Config");
+        showConfig.setId("showConfig-button");
+        showConfig.onActionProperty().set(h -> {
+            if("Hide Config".equals(showConfig.getText())){
+                monitorField.setText(monitorBuffer.toString());
+                showConfig.setText("Show Config");
+            }else {
+                showConfig();
+                showConfig.setText("Hide Config");
+            }
+        });
+        configFilterField.onActionProperty().set(h -> {
+            showConfig();
+        });
+        configFilterField.setId("configFilter-field");
+        buttonLayout.getChildren().addAll(showConfig, configFilterField);
+        return buttonLayout;
+    }
+
+    private void showConfig() {
+        String filter = configFilterField.getText();
+        String configAsText = null;
+        if(filter!=null && !filter.trim().isEmpty()){
+            configAsText = ConfigurationProvider.getConfiguration()
+                    .with(ConfigurationFunctions.section(filter))
+                    .query(ConfigurationFunctions.textInfo());
+        }else{
+            configAsText = ConfigurationProvider.getConfiguration()
+                    .query(ConfigurationFunctions.textInfo());
+        }
+        monitorField.setText(configAsText);
+    }
+
+    public static void main(String[] args) {
+        // Programmatically setup our configuration
+        hazelCastPropertySource = new HazelcastPropertySource();
+        ConfigurationContext ctx = ConfigurationProvider.getConfigurationContextBuilder()
+                .addPropertySources(
+                        new EnvironmentPropertySource(),
+                        new SystemPropertySource(),
+                        hazelCastPropertySource
+                        )
+                .addDefaultPropertyConverters()
+                .build();
+        ConfigurationProvider.setConfiguration(
+                ConfigurationProvider.createConfiguration(ctx));
+        // Launch the app
+        Application.launch(Display.class);
+    }
+
+
+    public void logToMonitor(String message){
+        if(!message.endsWith("\n")){
+            monitorBuffer.append(message + '\n');
+        }else{
+            monitorBuffer.append(message);
+        }
+        synchronized (monitorField) {
+            monitorField.setText(monitorBuffer.toString());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayContent.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayContent.java b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayContent.java
new file mode 100644
index 0000000..18ba302
--- /dev/null
+++ b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayContent.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tamaya.examples.distributed;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Created by atsticks on 13.11.16.
+ */
+public class DisplayContent {
+    public String displayId;
+    public String title = "UNKNOWN";
+    public Map<String,String> content = new HashMap<>();
+    public long timestamp = System.currentTimeMillis();
+    public String displayName;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof DisplayContent)) return false;
+        DisplayContent that = (DisplayContent) o;
+        return timestamp == that.timestamp &&
+                Objects.equals(displayId, that.displayId) &&
+                Objects.equals(title, that.title);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(displayId, title, timestamp);
+    }
+
+    @Override
+    public String toString() {
+        return "DisplayContent{" +
+                "displayId='" + displayId + '\'' +
+                ", title='" + title + '\'' +
+                ", content=" + content +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayManager.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayManager.java b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayManager.java
new file mode 100644
index 0000000..efd200b
--- /dev/null
+++ b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayManager.java
@@ -0,0 +1,276 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.tamaya.examples.distributed;
+
+import io.vertx.core.Vertx;
+import io.vertx.core.VertxOptions;
+import io.vertx.core.json.Json;
+import io.vertx.core.spi.cluster.ClusterManager;
+import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;
+import javafx.application.Application;
+import javafx.scene.Group;
+import javafx.scene.Node;
+import javafx.scene.Scene;
+import javafx.scene.control.*;
+import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.HBox;
+import javafx.scene.layout.Pane;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.scene.text.Font;
+import javafx.scene.text.FontWeight;
+import javafx.stage.Stage;
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.core.propertysource.EnvironmentPropertySource;
+import org.apache.tamaya.core.propertysource.SystemPropertySource;
+import org.apache.tamaya.functions.ConfigurationFunctions;
+import org.apache.tamaya.hazelcast.HazelcastPropertySource;
+import org.apache.tamaya.inject.ConfigurationInjection;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.MutableConfigurationProvider;
+import org.apache.tamaya.spi.ConfigurationContext;
+
+import java.util.logging.Logger;
+
+/**
+ * Created by atsticks on 12.11.16.
+ */
+public class DisplayManager extends Application{
+
+    private static final Logger LOG = Logger.getLogger(DisplayManager.class.getSimpleName());
+
+    public static final String DISPLAY_SHOW_TOPIC = "Display::show";
+    public static final String DISPLAY_REGISTER_TOPIC = "Display::register";
+    public static final String CONTENT_FIELD = "content";
+
+    private Scene scene;
+
+    private Group root = new Group();
+
+    private TextField configFilterField = new TextField("");
+
+    private TextArea configField = new TextArea();
+
+    private TextArea monitorField = new TextArea("Nothing to monitor yet.");
+
+    private StringBuffer monitorBuffer = new StringBuffer();
+
+    private Vertx vertx;
+
+    private static HazelcastPropertySource hazelCastPropertySource;
+
+    public DisplayManager(){
+        LOG.info("\n-----------------------------------\n" +
+                "Starting DisplayDisplayManager...\n" +
+                "-----------------------------------");
+        LOG.info("--- Starting Vertx cluster...");
+        // Reusing the hazelcast instance already in place for vertx...
+        ClusterManager mgr = new HazelcastClusterManager(
+                hazelCastPropertySource.getHazelcastInstance());
+        VertxOptions vertxOptions = new VertxOptions().setClusterManager(mgr);
+        Vertx.clusteredVertx(vertxOptions, h -> {
+            vertx = h.result();
+        });
+        LOG.info("--- Waiting for Vertx cluster...");
+        while(vertx==null){
+            try {
+                Thread.sleep(100L);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        }
+        monitorField.getStyleClass().add("monitor");
+        configField.getStyleClass().add("config");
+    }
+
+    @Override
+    public void start(Stage stage) throws Exception {
+        LOG.info("--- Configuring application...");
+        ConfigurationInjection.getConfigurationInjector()
+                .configure(this);
+        LOG.info("--- Starting stage...");
+        initStage(stage);
+        registerListeners();
+        LOG.info("--- Showing stage...");
+        stage.show();
+        LOG.info("\n----------------------\n" +
+                 "DisplayManager started\n" +
+                 "----------------------");
+    }
+
+    private void registerListeners() {
+        // registering update hook
+        vertx.eventBus().consumer(DISPLAY_SHOW_TOPIC, h -> {
+            DisplayContent content = Json.decodeValue((String)h.body(), DisplayContent.class);
+            logToMonitor("NEW CONTENT: " + content.toString());
+            logToMonitor("Updating config for content: " + content + "...");
+            MutableConfiguration config = MutableConfigurationProvider.createMutableConfiguration();
+            String id = content.displayId;
+            config.put("displays."+id+".title", content.title);
+            config.put("displays."+id+".timestamp", String.valueOf(content.timestamp));
+            config.put("displays."+id+".content.content", content.content.get(CONTENT_FIELD));
+            config.store();
+            logToMonitor("UPDATED.");
+        });
+        vertx.eventBus().consumer(DISPLAY_REGISTER_TOPIC, h -> {
+            DisplayRegistration registration = Json.decodeValue((String)h.body(), DisplayRegistration.class);
+            if(registration.isUpdate()){
+                logToMonitor("UDT DISPLAY: " + registration.getId());
+            }else{
+                logToMonitor("NEW DISPLAY: " + registration.toString());
+            }
+            MutableConfiguration config = MutableConfigurationProvider.createMutableConfiguration();
+            String id = registration.getId();
+            config.put("displays."+id+".displayName", registration.getDisplayName());
+            config.put("_displays."+id+".displayName.ttl", "10000");
+            if(registration.getHost()!=null) {
+                config.put("displays." + id + ".host", registration.getHost());
+                config.put("_displays." + id + ".host.ttl", "10000");
+            }
+            config.put("displays."+id+".displayModel", registration.getDisplayModel());
+            config.put("_displays."+id+".displayModel.ttl", "10000");
+            config.store();
+            logToMonitor("UPDATED.");
+        });
+    }
+
+    private void initStage(Stage stage) {
+        stage.setTitle("Display Manager");
+        scene = new Scene(root, Color.RED);
+        scene.getStylesheets().add("/stylesheet.css");
+
+        BorderPane layout = new BorderPane();
+        layout.getStyleClass().add("main-layout");
+//        layout.setPrefSize(600, 400);
+//        layout.setTop(createWinTitle());
+
+        Node configPanel = createConfigNode();
+        Node monitorPanel = createMonitorNode();
+
+        TabPane tabPane = new TabPane();
+        tabPane.getStylesheets().add("main-tabs");
+        Tab tab0 = new Tab("Monitor", monitorPanel);
+        tab0.setClosable(false);
+        Tab tab1 = new Tab("Configuration", configPanel);
+        tab1.setClosable(false);
+        Tab tab2 = new Tab("Content Manager", new ContentManagerPanel(vertx));
+        tab2.setClosable(false);
+        tabPane.getTabs().add(0, tab0);
+        tabPane.getTabs().add(1, tab1);
+        tabPane.getTabs().add(2, tab2);
+        layout.setCenter(tabPane);
+        layout.setBottom(createStatusPane());
+        scene.setRoot(layout);
+        stage.setScene(scene);
+    }
+
+    private Node createStatusPane() {
+        return new Label();
+    }
+
+    private Node createMonitorNode() {
+        VBox vbox = new VBox();
+        ScrollPane monitorPane = new ScrollPane(monitorField);
+        monitorPane.setFitToHeight(true);
+        monitorPane.setFitToWidth(true);
+        monitorField.setPrefSize(2000,2000);
+        vbox.getChildren().addAll(monitorPane);
+        return vbox;
+    }
+
+    private Node createConfigNode() {
+        VBox vbox = new VBox();
+        ScrollPane contentPane = new ScrollPane(configField);
+        contentPane.setFitToHeight(true);
+        contentPane.setFitToWidth(true);
+        configField.setPrefSize(2000,2000);
+        vbox.getChildren().addAll(contentPane, createButtonPane());
+        return vbox;
+    }
+
+    private Node createWinTitle() {
+        Label winTitle = new Label();
+        winTitle.setMinHeight(30.0);
+        winTitle.setMinWidth(200.0);
+        winTitle.setId("wintitle");
+        winTitle.setText("Tamaya Config Demo - DisplayManager");
+        return winTitle;
+    }
+
+    private Pane createButtonPane() {
+        HBox buttonLayout = new HBox();
+        buttonLayout.getStyleClass().add("button-pane");
+        Button refreshConfig = new Button("Refresh Config");
+        refreshConfig.setId("refreshConfig-button");
+        refreshConfig.onActionProperty().set(h -> {
+                showConfig();
+            });
+        configFilterField.onActionProperty().set(h -> {
+            showConfig();
+        });
+        configFilterField.setId("configFilter-field");
+        buttonLayout.getChildren().addAll(refreshConfig, configFilterField);
+        return buttonLayout;
+    }
+
+    private void showConfig() {
+        String filter = configFilterField.getText();
+        String configAsText = null;
+        if(filter!=null && !filter.trim().isEmpty()){
+            configAsText = ConfigurationProvider.getConfiguration()
+                    .with(ConfigurationFunctions.section(filter))
+                    .query(ConfigurationFunctions.textInfo());
+        }else{
+            configAsText = ConfigurationProvider.getConfiguration()
+                    .query(ConfigurationFunctions.textInfo());
+        }
+        configField.setText(configAsText);
+    }
+
+    public void logToMonitor(String message){
+        if(!message.endsWith("\n")){
+            monitorBuffer.append(message + '\n');
+        }else{
+            monitorBuffer.append(message);
+        }
+        synchronized (monitorField) {
+            monitorField.setText(monitorBuffer.toString());
+        }
+    }
+
+    public static void main(String[] args) {
+        // Programmatically setup our configuration
+        hazelCastPropertySource = new HazelcastPropertySource();
+        ConfigurationContext ctx = ConfigurationProvider.getConfigurationContextBuilder()
+                .addPropertySources(
+                        new EnvironmentPropertySource(),
+                        new SystemPropertySource(),
+                        hazelCastPropertySource
+                        )
+                .addDefaultPropertyConverters()
+                .build();
+        ConfigurationProvider.setConfiguration(
+                ConfigurationProvider.createConfiguration(ctx));
+        // Launch the app
+        Application.launch(DisplayManager.class);
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayRegistration.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayRegistration.java b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayRegistration.java
new file mode 100644
index 0000000..a2a181e
--- /dev/null
+++ b/examples/11-distributed/src/main/java/org/apache/tamaya/examples/distributed/DisplayRegistration.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tamaya.examples.distributed;
+
+import java.io.Serializable;
+import java.net.InetAddress;
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Created by atsticks on 13.11.16.
+ */
+public class DisplayRegistration implements Serializable{
+
+    private static final long serialVersionUID = 1L;
+
+    private String id;
+    private String displayName;
+    private String host;
+    private String displayModel;
+    private boolean update;
+    private long timestamp = System.currentTimeMillis();
+
+    private DisplayRegistration(){}
+
+    public DisplayRegistration(String displayName) {
+        this.displayName = Objects.requireNonNull(displayName);
+        this.displayModel = "fxDemo";
+
+        this.id = UUID.randomUUID().toString();
+    }
+
+    public DisplayRegistration(String displayName, String displayModel) {
+        this.displayModel = Objects.requireNonNull(displayModel);
+        this.displayName = Objects.requireNonNull(displayName);
+        this.id = UUID.randomUUID().toString();
+        InetAddress adr = null;
+        try{
+            adr = InetAddress.getLocalHost();
+            this.host = adr.getCanonicalHostName();
+        }
+        catch(Exception e){
+            this.host = adr.getHostName();
+        }
+    }
+
+    public boolean isUpdate(){
+        return this.update;
+    }
+
+    public String getDisplayModel() {
+        return displayModel;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {return true;}
+        if (!(o instanceof DisplayRegistration)) {return false;}
+        DisplayRegistration that = (DisplayRegistration) o;
+        return Objects.equals(getId(), that.getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getId());
+    }
+
+    @Override
+    public String toString() {
+        return "DisplayRegistration{" +
+                "\n  id='" + id + '\'' +
+                "\n  displayName='" + displayName + '\'' +
+                "\n  host='" + host + '\'' +
+                "\n  displayModel='" + displayModel + '\'' +
+                "\n  timestamp='" + timestamp + '\'' +
+                "\n  update='" + update + '\'' +
+                "\n}";
+    }
+
+    public DisplayRegistration update() {
+        DisplayRegistration reg = new DisplayRegistration();
+        reg.displayModel = this.displayModel;
+        reg.displayName = this.displayName;
+        reg.host = this.host;
+        reg.id = this.id;
+        reg.update = true;
+        reg.timestamp = System.currentTimeMillis();
+        return reg;
+    }
+
+    public void setDisplayName(String displayName) {
+        this.displayName = Objects.requireNonNull(displayName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertySource
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertySource b/examples/11-distributed/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertySource
new file mode 100644
index 0000000..a2a4042
--- /dev/null
+++ b/examples/11-distributed/src/main/resources/META-INF/services/org.apache.tamaya.spi.PropertySource
@@ -0,0 +1,19 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy current the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#org.apache.tamaya.examples.remote.client.RemotePropertySource
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/main/resources/stylesheet.css
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/main/resources/stylesheet.css b/examples/11-distributed/src/main/resources/stylesheet.css
new file mode 100644
index 0000000..2eb6c4f
--- /dev/null
+++ b/examples/11-distributed/src/main/resources/stylesheet.css
@@ -0,0 +1,38 @@
+.text{
+   -fx-font: bold 12pt "Arial";
+   -fx-background-color: light-grey;
+}
+.button{
+    -fx-font: bold 12pt "Arial";
+    -fx-text-fill: rgb(49, 89, 23);
+    -fx-border-color: rgb(49, 89, 23);
+    -fx-border-radius: 5;
+    -fx-padding: 3 6 6 6;
+}
+#wintitle{
+  -fx-font: bold 36pt "Arial";
+  -fx-text-fill: #FFBDBD;
+  -fx-background-color: black;
+}
+.main-layout{
+    -fx-width: 100%;
+    -fx-height: 100%;
+}
+.title{
+    -fx-font: bold 24pt "Arial";
+    -fx-text-fill: #EFEFEF;
+    -fx-background-color: light-grey;
+    -fx-text-fill: rgb(49, 89, 23);
+    -fx-border-color: rgb(49, 89, 23);
+    -fx-border-size: 0;
+    -fx-border-radius: 3;
+    -fx-padding: 3 6 6 6;
+    -fx-min-height: 40;
+    -fx-min-width: 200;
+}
+.content{
+    -fx-font: bold 18pt "Arial";
+}
+.monitor{
+    -fx-font: bold 16pt "Courier New";
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayContentTest.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayContentTest.java b/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayContentTest.java
new file mode 100644
index 0000000..bf92e88
--- /dev/null
+++ b/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayContentTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tamaya.examples.distributed;
+
+import io.vertx.core.json.Json;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by atsticks on 13.11.16.
+ */
+public class DisplayContentTest {
+
+    @org.junit.Test
+    public void testToString() throws Exception {
+
+    }
+
+    @org.junit.Test
+    public void testJson() throws Exception {
+        DisplayContent content = new DisplayContent();
+        content.displayId = "1234";
+        content.title = "myTitle";
+        content.content.put("content", "myContent");
+        String val = Json.encode(content);
+        DisplayContent decoded = Json.decodeValue(val, DisplayContent.class);
+        assertNotNull(decoded);
+        assertEquals(content, decoded);
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/57df9012/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayRegistrationTest.java
----------------------------------------------------------------------
diff --git a/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayRegistrationTest.java b/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayRegistrationTest.java
new file mode 100644
index 0000000..c23728d
--- /dev/null
+++ b/examples/11-distributed/src/test/java/org/apache/tamaya/examples/distributed/DisplayRegistrationTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.tamaya.examples.distributed;
+
+import io.vertx.core.json.Json;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by atsticks on 13.11.16.
+ */
+public class DisplayRegistrationTest {
+    @Test
+    public void getDisplayModel() throws Exception {
+
+    }
+
+    @Test
+    public void getDisplayName() throws Exception {
+
+    }
+
+    @Test
+    public void getHost() throws Exception {
+
+    }
+
+    @Test
+    public void getId() throws Exception {
+
+    }
+
+    @Test
+    public void testEquals() throws Exception {
+
+    }
+
+    @Test
+    public void testToString() throws Exception {
+
+    }
+
+    @org.junit.Test
+    public void testJson() throws Exception {
+        DisplayRegistration reg = new DisplayRegistration("myDisplay", "VT100");
+        String val = Json.encode(reg);
+        DisplayRegistration decoded = Json.decodeValue(val, DisplayRegistration.class);
+        assertNotNull(decoded);
+        assertEquals(reg, decoded);
+    }
+
+}
\ No newline at end of file