You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tamaya.apache.org by pl...@apache.org on 2016/09/06 17:18:45 UTC

[49/50] [abbrv] incubator-tamaya-sandbox git commit: - Moved UI module into sandbox, including UI parts. - Decoupled accordingly existing modules from UI. - Fixed a few quality issues.

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/services/UserService.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/services/UserService.java b/ui/base/src/main/java/org/apache/tamaya/ui/services/UserService.java
new file mode 100644
index 0000000..71a8a43
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/services/UserService.java
@@ -0,0 +1,30 @@
+/*
+ * 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.ui.services;
+
+import org.apache.tamaya.ui.User;
+
+/**
+ * Created by atsticks on 29.03.16.
+ */
+public interface UserService {
+
+    User login(String userId, String credentials);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/ConfigView.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/ConfigView.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/ConfigView.java
new file mode 100644
index 0000000..fb0d41b
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/ConfigView.java
@@ -0,0 +1,229 @@
+/*
+ * 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.ui.views;
+
+import com.vaadin.data.Property;
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.Tree;
+import com.vaadin.ui.VerticalLayout;
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.UIConstants;
+import org.apache.tamaya.ui.ViewProvider;
+import org.apache.tamaya.ui.components.VerticalSpacedLayout;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import javax.annotation.Priority;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * View for evaluating the current convifugration tree.
+ */
+@Priority(10)
+public class ConfigView extends VerticalSpacedLayout implements View {
+
+    /**
+     * Provider to register this view.
+     */
+    @Priority(10)
+    public static final class Provider implements ViewProvider{
+
+        @Override
+        public ViewLifecycle getLifecycle() {
+            return ViewLifecycle.CREATE;
+        }
+
+        @Override
+        public String getName() {
+            return "view.config.name";
+        }
+
+        @Override
+        public String getUrlPattern() {
+            return "/config";
+        }
+
+        @Override
+        public String getDisplayName() {
+            return ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage("view.config.name");
+        }
+
+        @Override
+        public View createView(Object... params){
+            return new ConfigView();
+        }
+    }
+
+    private TextField keyFilter = new TextField("Key filter");
+    private TextField valueFilter = new TextField("Value filter");
+    private CheckBox showMetaEntries = new CheckBox("Show Metadata", false);
+    private Tree tree = new Tree("Current Configuration");
+
+    public ConfigView() {
+        Label caption = new Label("Raw Configuration");
+        Label description = new Label(
+                "This view shows the overall <b>raw</b> configuration tree. Dependening on your access rights you" +
+                        "may see partial or masked data. Similarly configuration can be <i>read-only</i> or <i>mutable</i>.",
+                ContentMode.HTML);
+
+        TabSheet tabPane = new TabSheet();
+        VerticalLayout configLayout = new VerticalLayout();
+
+        HorizontalLayout filters = new HorizontalLayout();
+
+        Button filterButton = new Button("Filter", new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                fillTree();
+            }
+        });
+        filters.setDefaultComponentAlignment(Alignment.BOTTOM_LEFT);
+        filters.addComponents(keyFilter, valueFilter, filterButton, showMetaEntries);
+        filters.setSpacing(true);
+
+        fillTree();
+        configLayout.addComponents(filters, tree);
+        tabPane.addTab(configLayout, "Configuration");
+        TextArea envProps = new TextArea();
+        StringBuilder b = new StringBuilder();
+        envProps.setHeight("100%");
+        envProps.setWidth("100%");
+        envProps.setSizeFull();
+        envProps.setRows(System.getenv().size());
+        for(Map.Entry<String,String> en:new TreeMap<>(System.getenv()).entrySet()){
+            b.append(en.getKey()).append("=").append(en.getValue()).append('\n');
+        }
+        envProps.setValue(b.toString());
+        envProps.setReadOnly(true);
+        tabPane.addTab(envProps, "Environment Properties");
+        TextArea sysProps = new TextArea();
+        sysProps.setSizeFull();
+        sysProps.setRows(System.getProperties().size());
+        b.setLength(0);
+        for(Map.Entry<Object,Object> en:new TreeMap<>(System.getProperties()).entrySet()){
+            b.append(en.getKey()).append("=").append(en.getValue()).append('\n');
+        }
+        sysProps.setValue(b.toString());
+        sysProps.setReadOnly(true);
+        tabPane.addTab(sysProps, "System Properties");
+        TextArea runtimeProps = new TextArea();
+        runtimeProps.setRows(5);
+        b.setLength(0);
+        b.append("Available Processors : ").append(Runtime.getRuntime().availableProcessors()).append('\n');
+        b.append("Free Memory          : ").append(Runtime.getRuntime().freeMemory()).append('\n');
+        b.append("Max Memory           : ").append(Runtime.getRuntime().maxMemory()).append('\n');
+        b.append("Total Memory         : ").append(Runtime.getRuntime().totalMemory()).append('\n');
+        b.append("Default Locale       : ").append(Locale.getDefault()).append('\n');
+        runtimeProps.setValue(b.toString());
+        runtimeProps.setReadOnly(true);
+        tabPane.addTab(runtimeProps, "Runtime Properties");
+        runtimeProps.setSizeFull();
+        addComponents(caption, description, tabPane);
+        caption.addStyleName(UIConstants.LABEL_HUGE);
+        description.addStyleName(UIConstants.LABEL_LARGE);
+        showMetaEntries.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
+                fillTree();
+            }
+        });
+    }
+
+    private void fillTree() {
+        String keyFilterExp = this.keyFilter.getValue();
+        if(keyFilterExp.isEmpty()){
+            keyFilterExp = null;
+        }
+        String valueFilterExp = this.valueFilter.getValue();
+        if(valueFilterExp.isEmpty()){
+            valueFilterExp = null;
+        }
+        tree.removeAllItems();
+        boolean showMetadata = showMetaEntries.getValue();
+        for(Map.Entry<String,String> entry: ConfigurationProvider.getConfiguration().getProperties().entrySet()){
+            String key = entry.getKey();
+            if(keyFilterExp!=null && !key.matches(keyFilterExp)){
+                continue;
+            }
+            if(valueFilterExp!=null && !entry.getValue().matches(valueFilterExp)){
+                continue;
+            }
+            if(!showMetadata && entry.getKey().startsWith("_")){
+                continue;
+            }
+            tree.addItem(key);
+            tree.setItemCaption(key, getCaption(key, entry.getValue()));
+            tree.setChildrenAllowed(key, false);
+            String parent = null;
+            int start = 0;
+            int index = key.indexOf('.', start);
+            while(index>0){
+                String subItem = key.substring(0,index);
+                String caption = key.substring(start, index);
+                tree.addItem(subItem);
+                tree.setItemCaption(subItem, caption);
+                if(parent!=null){
+                    tree.setParent(subItem, parent);
+                }
+                parent = subItem;
+                start = index+1;
+                index = key.indexOf('.', start);
+            }
+            String lastItem = key.substring(start);
+            if(!lastItem.equals(key)){
+                if(parent!=null){
+                    tree.setParent(key, parent);
+                }else{
+                    // should not happen
+                }
+            }else{ // singl root entry
+                if(parent!=null) {
+                    tree.setParent(key, parent);
+                }
+            }
+        }
+    }
+
+    private String getCaption(String key, String value) {
+        int index = key.lastIndexOf('.');
+        if(index<0){
+            return key + " = " + value;
+        }else{
+            return key.substring(index+1) + " = " + value;
+        }
+    }
+
+    @Override
+    public void enter(ViewChangeListener.ViewChangeEvent event) {
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/ErrorView.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/ErrorView.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/ErrorView.java
new file mode 100644
index 0000000..eef0db8
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/ErrorView.java
@@ -0,0 +1,43 @@
+/*
+ * 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.ui.views;
+
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.VerticalLayout;
+import org.apache.tamaya.ui.UIConstants;
+
+/**
+ * View used for shoiwing unexpected errors.
+ */
+public class ErrorView extends VerticalLayout implements View {
+
+    @Override
+    public void enter(ViewChangeListener.ViewChangeEvent event) {
+        setSizeFull();
+        setMargin(true);
+        Label label = new Label("Could not find a view with that name. You are most likely doing it wrong.");
+        label.addStyleName(UIConstants.LABEL_FAILURE);
+
+        addComponent(label);
+        setComponentAlignment(label, Alignment.MIDDLE_CENTER);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/HomeView.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/HomeView.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/HomeView.java
new file mode 100644
index 0000000..9d371d0
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/HomeView.java
@@ -0,0 +1,94 @@
+/*
+ * 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.ui.views;
+
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Label;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.CurrentUser;
+import org.apache.tamaya.ui.UIConstants;
+import org.apache.tamaya.ui.ViewProvider;
+import org.apache.tamaya.ui.components.VerticalSpacedLayout;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import javax.annotation.Priority;
+
+/**
+ * Home view containing a title and a description, used as default entry point of the UI after login.
+ */
+public class HomeView extends VerticalSpacedLayout implements View {
+
+    /**
+     * Provider to bew registered providing this view to the UI module.
+     */
+    @Priority(0)
+    public static final class Provider implements ViewProvider{
+
+        @Override
+        public ViewLifecycle getLifecycle() {
+            return ViewLifecycle.LAZY;
+        }
+
+        @Override
+        public String getName() {
+            return "view.home.name";
+        }
+
+        @Override
+        public String getUrlPattern() {
+            return "/home";
+        }
+
+        @Override
+        public String getDisplayName() {
+            return ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage(getName());
+        }
+
+        @Override
+        public View createView(Object... params) {
+            return new HomeView();
+        }
+
+    }
+
+    /**
+     * Constructor.
+     */
+    public HomeView() {
+        Label caption = new Label("Welcome, " + CurrentUser.get().getUserID());
+        Label description = new Label(
+                "<b>Apache Tamaya</b> is an API and extendable framework for accessing and managing configuration.<br/> \n" +
+                        "Please check the project's home page <a href='http://tamaya.incubator.apache.org'>http://tamaya.incubator.apache.org</a>.",
+                ContentMode.HTML);
+
+        addComponents(caption, description);
+
+        caption.addStyleName(UIConstants.LABEL_HUGE);
+        description.addStyleName(UIConstants.LABEL_LARGE);
+
+    }
+
+    @Override
+    public void enter(ViewChangeListener.ViewChangeEvent event) {
+        // nothing to do
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/SystemView.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/SystemView.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/SystemView.java
new file mode 100644
index 0000000..ea3421c
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/SystemView.java
@@ -0,0 +1,117 @@
+/*
+ * 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.ui.views;
+
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Tree;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.UIConstants;
+import org.apache.tamaya.ui.ViewProvider;
+import org.apache.tamaya.ui.components.VerticalSpacedLayout;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import javax.annotation.Priority;
+
+/**
+ * View showing the current loaded system components.
+ */
+@Priority(10000)
+public class SystemView extends VerticalSpacedLayout implements View {
+
+
+    /**
+     * Provider to register this view.
+     */
+    @Priority(20)
+    public static final class Provider implements ViewProvider{
+
+        @Override
+        public ViewLifecycle getLifecycle() {
+            return ViewLifecycle.CREATE;
+        }
+
+        @Override
+        public String getName() {
+            return "view.system.name";
+        }
+
+        @Override
+        public String getUrlPattern() {
+            return "/system";
+        }
+
+        @Override
+        public String getDisplayName() {
+            return ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage("view.system.name");
+        }
+
+        @Override
+        public View createView(Object... params){
+            return new SystemView();
+        }
+    }
+
+
+    private Tree configTree = new Tree(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("default.label.system"));
+
+
+    public SystemView() {
+        Label caption = new Label("Tamaya Runtime");
+        Label description = new Label(
+                "This view shows the system components currently active. This information may be useful when checking if an" +
+                        "configuration extension is loaded and for inspection of the configuration and property sources" +
+                        "invovlved.",
+                ContentMode.HTML);
+
+        fillComponentTree();
+
+        addComponents(caption, description, configTree);
+
+        caption.addStyleName(UIConstants.LABEL_HUGE);
+        description.addStyleName(UIConstants.LABEL_LARGE);
+
+    }
+
+    private void fillComponentTree() {
+        configTree.removeAllItems();
+        for(SystemInfoProvider infoProvider:ServiceContextManager.getServiceContext()
+                .getServices(SystemInfoProvider.class)){
+            infoProvider.provideSystemInfo(configTree);
+        }
+    }
+
+    private String getCaption(String key, String value) {
+        int index = key.lastIndexOf('.');
+        if(index<0){
+            return key + " = " + value;
+        }else{
+            return key.substring(index+1) + " = " + value;
+        }
+    }
+
+    @Override
+    public void enter(ViewChangeListener.ViewChangeEvent event) {
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/TamayaGeneralSystemInfoProvider.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/TamayaGeneralSystemInfoProvider.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/TamayaGeneralSystemInfoProvider.java
new file mode 100644
index 0000000..fd37136
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/TamayaGeneralSystemInfoProvider.java
@@ -0,0 +1,56 @@
+/*
+ * 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.ui.views;
+
+import com.vaadin.ui.Tree;
+import org.apache.tamaya.Configuration;
+import org.apache.tamaya.ConfigurationProvider;
+import org.apache.tamaya.spi.PropertyValueCombinationPolicy;
+
+import javax.annotation.Priority;
+
+/**
+ * Created by atsticks on 29.06.16.
+ */
+@Priority(0)
+public class TamayaGeneralSystemInfoProvider implements SystemInfoProvider{
+    @Override
+    public void provideSystemInfo(Tree tree) {
+        Configuration config = ConfigurationProvider.getConfiguration();
+        String currentParent = "General";
+        tree.addItem(currentParent);
+        tree.addItem("Configuration.class");
+        tree.setItemCaption("Configuration.class", "Configuration class = " + config.getClass().getName());
+        tree.setParent("Configuration.class", currentParent);
+        tree.setChildrenAllowed("Configuration.class", false);
+
+        tree.addItem("ConfigurationContext.class");
+        tree.setItemCaption("ConfigurationContext.class", "ConfigurationContext class = " +
+                config.getContext().getClass().getName());
+        tree.setParent("ConfigurationContext.class", currentParent);
+        tree.setChildrenAllowed("ConfigurationContext.class", false);
+
+        tree.addItem("PropertyValueCombinationPolicy.class");
+        tree.setItemCaption("PropertyValueCombinationPolicy.class",
+                PropertyValueCombinationPolicy.class.getSimpleName() + " class = " +
+                        config.getContext().getPropertyValueCombinationPolicy().getClass().getName());
+        tree.setParent("PropertyValueCombinationPolicy.class", currentParent);
+        tree.setChildrenAllowed("PropertyValueCombinationPolicy.class", false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginBox.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginBox.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginBox.java
new file mode 100644
index 0000000..73cf018
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginBox.java
@@ -0,0 +1,112 @@
+/*
+ * 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.ui.views.login;
+
+import com.vaadin.event.ShortcutAction;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.PasswordField;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.VerticalLayout;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.UIConstants;
+import org.apache.tamaya.ui.User;
+import org.apache.tamaya.ui.event.EventBus;
+import org.apache.tamaya.ui.services.MessageProvider;
+import org.apache.tamaya.ui.services.UserService;
+
+/**
+ * Login dialog centerd on the screen.
+ */
+public class LoginBox extends VerticalLayout {
+
+    private TextField username;
+    private PasswordField password;
+
+    public LoginBox() {
+        setWidth("400px");
+        addStyleName(UIConstants.LOGIN_BOX);
+        setSpacing(true);
+        setMargin(true);
+
+        addCaption();
+        addForm();
+        addButtons();
+    }
+
+    private void addCaption() {
+        Label caption = new Label("Login to system");
+        addComponent(caption);
+
+        caption.addStyleName(UIConstants.LABEL_H1);
+    }
+
+    private void addForm() {
+        FormLayout loginForm = new FormLayout();
+        MessageProvider mp = ServiceContextManager.getServiceContext().getService(MessageProvider.class);
+        username = new TextField(mp.getMessage("default.label.username"));
+        password = new PasswordField(mp.getMessage("default.label.password"));
+        loginForm.addComponents(username, password);
+        addComponent(loginForm);
+        loginForm.setSpacing(true);
+        for(Component component:loginForm){
+            component.setWidth("100%");
+        }
+        username.focus();
+    }
+
+    private void addButtons() {
+        HorizontalLayout buttonsLayout = new HorizontalLayout();
+        Button forgotButton = new Button("Forgot", new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                Notification.show("Sorry, this feature is not yet implemented.", Notification.Type.TRAY_NOTIFICATION);
+            }
+        });
+        Button loginButton = new Button("Login", new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                login();
+            }
+        });
+        buttonsLayout.addComponents(forgotButton, loginButton);
+        addComponent(buttonsLayout);
+        buttonsLayout.setSpacing(true);
+        forgotButton.addStyleName(UIConstants.BUTTON_LINK);
+        loginButton.addStyleName(UIConstants.BUTTON_PRIMARY);
+        loginButton.setClickShortcut(ShortcutAction.KeyCode.ENTER);
+        setComponentAlignment(buttonsLayout, Alignment.BOTTOM_RIGHT);
+    }
+
+    private void login() {
+        User user = ServiceContextManager.getServiceContext().getService(UserService.class)
+                .login(username.getValue(), password.getValue());
+        if(user!=null){
+            EventBus.post(new LoginEvent(user));
+        }else{
+            Notification.show("Login failed.", "Sorry the system could not log you in.", Notification.Type.WARNING_MESSAGE);
+            username.focus();
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginEvent.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginEvent.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginEvent.java
new file mode 100644
index 0000000..004c545
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginEvent.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ui.views.login;
+
+import org.apache.tamaya.ui.User;
+
+import java.util.Objects;
+
+/**
+ * Event sent when a user has been authenticated.
+ */
+public class LoginEvent {
+    /** The user, not null. */
+    private User user;
+
+    /**
+     * Creates a new event.
+     * @param user the user logged in, not null.
+     */
+    public LoginEvent(User user) {
+        this.user = Objects.requireNonNull(user);
+    }
+
+    /**
+     * Get the user logged in.
+     * @return the user logged in, never null.
+     */
+    public User getUser() {
+        return user;
+    }
+
+    @Override
+    public String toString() {
+        return "LoginEvent{" +
+                "user=" + user +
+                '}';
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginView.java
----------------------------------------------------------------------
diff --git a/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginView.java b/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginView.java
new file mode 100644
index 0000000..15730d3
--- /dev/null
+++ b/ui/base/src/main/java/org/apache/tamaya/ui/views/login/LoginView.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ui.views.login;
+
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.VerticalLayout;
+
+/**
+ * View used for login the users.
+ */
+public class LoginView extends VerticalLayout {
+
+    /**
+     * Creates a new view.
+     */
+    public LoginView() {
+        setSizeFull();
+        setDefaultComponentAlignment(Alignment.MIDDLE_CENTER);
+        addComponent(new LoginBox());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/resources/META-INF/javaconfiguration.properties
----------------------------------------------------------------------
diff --git a/ui/base/src/main/resources/META-INF/javaconfiguration.properties b/ui/base/src/main/resources/META-INF/javaconfiguration.properties
new file mode 100644
index 0000000..98d7155
--- /dev/null
+++ b/ui/base/src/main/resources/META-INF/javaconfiguration.properties
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+tamaya.users.admin.pwd=admin
+tamaya.users.admin.fullName=Administrator
+tamaya.users.admin.roles=admin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
----------------------------------------------------------------------
diff --git a/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider b/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
new file mode 100644
index 0000000..0ff3225
--- /dev/null
+++ b/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
@@ -0,0 +1,24 @@
+#
+# 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.ui.views.HomeView$Provider
+org.apache.tamaya.ui.views.ConfigView$Provider
+org.apache.tamaya.ui.views.SystemView$Provider
+
+# Events Module
+org.apache.tamaya.ui.events.EventView$Provider

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.MessageProvider
----------------------------------------------------------------------
diff --git a/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.MessageProvider b/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.MessageProvider
new file mode 100644
index 0000000..6ce4a9f
--- /dev/null
+++ b/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.MessageProvider
@@ -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.ui.internal.ConfigurationBasedMessageProvider
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.UserService
----------------------------------------------------------------------
diff --git a/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.UserService b/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.UserService
new file mode 100644
index 0000000..109865f
--- /dev/null
+++ b/ui/base/src/main/resources/META-INF/services/org.apache.tamaya.ui.services.UserService
@@ -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.ui.internal.ConfiguredUserService
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/resources/config/application.yml
----------------------------------------------------------------------
diff --git a/ui/base/src/main/resources/config/application.yml b/ui/base/src/main/resources/config/application.yml
new file mode 100644
index 0000000..a22ec36
--- /dev/null
+++ b/ui/base/src/main/resources/config/application.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+server:
+  type: default
+  maxThreads: 1024
+  applicationConnectors:
+      - type: http
+        port: 8090
+  adminConnectors:
+      - type: http
+        port: 8091
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/main/resources/ui/lang/tamaya.properties
----------------------------------------------------------------------
diff --git a/ui/base/src/main/resources/ui/lang/tamaya.properties b/ui/base/src/main/resources/ui/lang/tamaya.properties
new file mode 100644
index 0000000..ba458de
--- /dev/null
+++ b/ui/base/src/main/resources/ui/lang/tamaya.properties
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+project.name=Apache Tamaya
+default.label.logout=Log out
+default.label.unknown=<unknown>
+default.label.username=Username
+default.label.password=Password
+default.label.system=Runtime
+
+view.config.name=Configuration
+view.home.name=Home
+view.system.name=System Runtime

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/base/src/test/resources/config/application.yml
----------------------------------------------------------------------
diff --git a/ui/base/src/test/resources/config/application.yml b/ui/base/src/test/resources/config/application.yml
new file mode 100644
index 0000000..10ef339
--- /dev/null
+++ b/ui/base/src/test/resources/config/application.yml
@@ -0,0 +1,36 @@
+#
+# 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.
+#
+
+server:
+  type: default
+  maxThreads: 1024
+  applicationConnectors:
+      - type: http
+        port: 8090
+      - type: https
+        port: 8453
+  adminConnectors:
+      - type: http
+        port: 8091
+      - type: https
+        port: 8453
+
+ui:
+  disabled-views:
+    - "view.system.name"
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/events/src/main/java/org/apache/tamaya/ui/events/EventView.java
----------------------------------------------------------------------
diff --git a/ui/events/src/main/java/org/apache/tamaya/ui/events/EventView.java b/ui/events/src/main/java/org/apache/tamaya/ui/events/EventView.java
new file mode 100644
index 0000000..ffb59cf
--- /dev/null
+++ b/ui/events/src/main/java/org/apache/tamaya/ui/events/EventView.java
@@ -0,0 +1,181 @@
+/*
+ * 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.ui.events;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.TextField;
+import org.apache.tamaya.events.ConfigEvent;
+import org.apache.tamaya.events.ConfigEventListener;
+import org.apache.tamaya.events.ConfigEventManager;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.UIConstants;
+import org.apache.tamaya.ui.ViewProvider;
+import org.apache.tamaya.ui.components.VerticalSpacedLayout;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import javax.annotation.Priority;
+import java.util.Date;
+
+/**
+ * Tamaya View for observing the current event stream.
+ */
+public class EventView extends VerticalSpacedLayout implements View {
+
+    /**
+     * Provider used to register the view.
+     */
+    @Priority(20)
+    public static final class Provider implements ViewProvider{
+
+        @Override
+        public ViewLifecycle getLifecycle() {
+            return ViewLifecycle.EAGER;
+        }
+
+        @Override
+        public String getName() {
+            return "view.events.name";
+        }
+
+        @Override
+        public String getUrlPattern() {
+            return "/events";
+        }
+
+        @Override
+        public String getDisplayName() {
+            return getName();
+        }
+
+        @Override
+        public View createView(Object... params){
+            return new EventView();
+        }
+    }
+
+    private CheckBox changeMonitorEnabled = new CheckBox(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.events.button.enableMonitoring"));
+    private Button clearViewButton = new Button(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.events.button.clearView"));
+    private TextField pollingInterval = new TextField(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.events.field.pollingInterval"));
+    private Table eventsTable = new Table(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.events.table.name"));
+
+
+    public EventView() {
+        Label caption = new Label(ServiceContextManager.getServiceContext()
+                .getService(MessageProvider.class).getMessage("view.events.name"));
+        Label description = new Label(ServiceContextManager.getServiceContext()
+                .getService(MessageProvider.class).getMessage("view.events.description"),
+                ContentMode.HTML);
+
+        ConfigEventManager.addListener(new ConfigEventListener() {
+            @Override
+            public void onConfigEvent(ConfigEvent<?> event) {
+                addEvent(event);
+            }
+        });
+        changeMonitorEnabled.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
+                ConfigEventManager.enableChangeMonitoring(changeMonitorEnabled.getValue());
+                if(changeMonitorEnabled.getValue()) {
+                    Notification.show("Event Monitoring (Polling) active.");
+                }else{
+                    Notification.show("Event Monitoring (Polling) inactive.");
+                }
+            }
+        });
+        clearViewButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                eventsTable.removeAllItems();
+                Notification.show("Events cleared.");
+            }
+        });
+
+        HorizontalLayout eventSettings = new HorizontalLayout();
+        eventSettings.addComponents(changeMonitorEnabled, new Label(" Polling Interval"), pollingInterval, clearViewButton);
+        changeMonitorEnabled.setValue(ConfigEventManager.isChangeMonitoring());
+        pollingInterval.setValue(String.valueOf(ConfigEventManager.getChangeMonitoringPeriod()));
+        pollingInterval.setRequired(true);
+        pollingInterval.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
+                try{
+                    long millis = Long.parseLong((String)valueChangeEvent.getProperty().getValue());
+                    ConfigEventManager.setChangeMonitoringPeriod(millis);
+                    Notification.show("Updated Event Monitoring Poll Interval to " + millis + " milliseconds.");
+                }catch(Exception e){
+                    Notification.show("Cannot update Event Monitoring Poll Interval to "
+                            + valueChangeEvent.getProperty().getValue(), Notification.Type.ERROR_MESSAGE);
+                }
+            }
+        });
+        eventsTable.addContainerProperty("Timestamp", Date.class, null);
+        eventsTable.addContainerProperty("Type", String.class, "?");
+        eventsTable.addContainerProperty("Payload", String.class, "<empty>");
+        eventsTable.addContainerProperty("Version",  String.class, "?");
+        eventsTable.setPageLength(20);
+        eventsTable.setWidth("100%");
+        eventsTable.setResponsive(true);
+
+
+        caption.addStyleName(UIConstants.LABEL_HUGE);
+        description.addStyleName(UIConstants.LABEL_LARGE);
+        addComponents(caption, description, eventSettings, eventsTable);
+    }
+
+    private void addEvent(ConfigEvent<?> evt){
+        Object newItemId = eventsTable.addItem();
+        Item row = eventsTable.getItem(newItemId);
+        row.getItemProperty("Timestamp").setValue(new Date(evt.getTimestamp()));
+        row.getItemProperty("Type").setValue(evt.getResourceType().getSimpleName());
+        String value = String.valueOf(evt.getResource());
+        String valueShort = value.length()<150?value:value.substring(0,147)+"...";
+        row.getItemProperty("Payload").setValue(valueShort);
+        row.getItemProperty("Version").setValue(evt.getVersion());
+    }
+
+
+    private String getCaption(String key, String value) {
+        int index = key.lastIndexOf('.');
+        if(index<0){
+            return key + " = " + value;
+        }else{
+            return key.substring(index+1) + " = " + value;
+        }
+    }
+
+    @Override
+    public void enter(ViewChangeListener.ViewChangeEvent event) {
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/events/src/test/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
----------------------------------------------------------------------
diff --git a/ui/events/src/test/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider b/ui/events/src/test/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
new file mode 100644
index 0000000..d30ddaa
--- /dev/null
+++ b/ui/events/src/test/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
@@ -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.
+#
+events.EventView$Provider
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/mutableconfig/pom.xml
----------------------------------------------------------------------
diff --git a/ui/mutableconfig/pom.xml b/ui/mutableconfig/pom.xml
new file mode 100644
index 0000000..8a94150
--- /dev/null
+++ b/ui/mutableconfig/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<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">
+
+    <parent>
+        <groupId>org.apache.tamaya.ext</groupId>
+        <artifactId>tamaya-ui</artifactId>
+        <version>0.3-incubating-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <packaging>jar</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>tamaya-ui-mutableconfig</artifactId>
+    <name>Apache Tamaya Modules - UI (Mutable Config)</name>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigEditorWidget.java
----------------------------------------------------------------------
diff --git a/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigEditorWidget.java b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigEditorWidget.java
new file mode 100644
index 0000000..09b23a1
--- /dev/null
+++ b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigEditorWidget.java
@@ -0,0 +1,132 @@
+/*
+ * 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.ui.mutableconfig;
+
+import com.vaadin.ui.*;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import java.util.Objects;
+
+/**
+ * Tamaya UI view to change configuration.
+ */
+public class ConfigEditorWidget extends FormLayout {
+
+    private MutableConfiguration mutableConfig;
+
+    private ProtocolWidget logWriter;
+    private TransactionControlWidget taWidget;
+
+    private TextField configKey = new TextField(
+            ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage("view.edit.text.configKey"));
+    private TextField configValue = new TextField(
+            ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage("view.edit.text.configValue"));
+    private Button updateButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.updateKey"));
+    private Button removeButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.removeKey"));
+    private Button readButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.readKey"));
+
+    public ConfigEditorWidget(MutableConfiguration mutableConfig, ProtocolWidget logWriter, TransactionControlWidget taWidget) {
+        this.mutableConfig = Objects.requireNonNull(mutableConfig);
+        this.logWriter = Objects.requireNonNull(logWriter);
+        this.taWidget = Objects.requireNonNull(taWidget);
+        configKey.setWidth(50, Unit.PERCENTAGE);
+        configValue.setWidth(50, Unit.PERCENTAGE);
+        addComponents(configKey, configValue);
+        HorizontalLayout buttonLayout = new HorizontalLayout();
+        buttonLayout.addComponents(readButton, new Label("   "), updateButton, removeButton);
+        buttonLayout.setSpacing(true);
+        addComponents(buttonLayout);
+        initActions();
+    }
+
+    private void initActions() {
+        updateButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                if(mutableConfig.isWritable(configKey.getValue())){
+                    mutableConfig.put(configKey.getValue(), configValue.getValue());
+                    Notification.show("Added " + configKey.getValue() + " = " + configValue.getValue(),
+                            Notification.Type.TRAY_NOTIFICATION);
+                    logWriter.println(" - PUT " + configKey.getValue() + " = " + configValue.getValue());
+                    configKey.setValue("");
+                    configValue.setValue("");
+                }else{
+                    Notification.show("Could not add " + configKey.getValue() + " = " + configValue.getValue(),
+                            Notification.Type.ERROR_MESSAGE);
+                    logWriter.println(" - PUT " + configKey.getValue() + " rejected - not writable.");
+                }
+                taWidget.update();
+            }
+        });
+        removeButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                if(mutableConfig.isRemovable(configKey.getValue())){
+                    mutableConfig.remove(configKey.getValue());
+                    logWriter.println(" - DEL " + configKey.getValue());
+                    Notification.show("Removed " + configKey.getValue(),
+                            Notification.Type.TRAY_NOTIFICATION);
+                    configKey.setValue("");
+                    configValue.setValue("");
+                }else{
+                    Notification.show("Could not remove " + configKey.getValue(),
+                            Notification.Type.ERROR_MESSAGE);
+                    logWriter.println(" - DEL " + configKey.getValue() + " rejected - not removable.");
+                }
+                taWidget.update();
+            }
+        });
+        readButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                if(mutableConfig.isExisting(configKey.getValue())){
+                    String key = configKey.getValue();
+                    configValue.setValue(mutableConfig.get(key));
+                    Notification.show("Successfully read " + configKey.getValue(),
+                            Notification.Type.TRAY_NOTIFICATION);
+                    logWriter.println(" - GET " + key + " = " + configValue.getValue());
+                    logWriter.println("   - removable: " + mutableConfig.isRemovable(key));
+                    logWriter.println("   - writable : " + mutableConfig.isWritable(key));
+                }else{
+                    Notification.show("Could not read " + configKey.getValue(),
+                            Notification.Type.ERROR_MESSAGE);
+                    logWriter.println(" - GET " + configKey.getValue() + " rejected - not existing.");
+                }
+                taWidget.update();
+            }
+        });
+    }
+
+    private String getCaption(String key, String value) {
+        int index = key.lastIndexOf('.');
+        if(index<0){
+            return key + " = " + value;
+        }else{
+            return key.substring(index+1) + " = " + value;
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigUpdaterView.java
----------------------------------------------------------------------
diff --git a/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigUpdaterView.java b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigUpdaterView.java
new file mode 100644
index 0000000..7facaeb
--- /dev/null
+++ b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ConfigUpdaterView.java
@@ -0,0 +1,121 @@
+/*
+ * 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.ui.mutableconfig;
+
+import com.vaadin.navigator.View;
+import com.vaadin.navigator.ViewChangeListener;
+import com.vaadin.shared.ui.label.ContentMode;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.PopupView;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.MutableConfigurationProvider;
+import org.apache.tamaya.mutableconfig.spi.MutablePropertySource;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.UIConstants;
+import org.apache.tamaya.ui.ViewProvider;
+import org.apache.tamaya.ui.components.VerticalSpacedLayout;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import javax.annotation.Priority;
+
+/**
+ * Tamaya UI view to change configuration.
+ */
+public class ConfigUpdaterView extends VerticalSpacedLayout implements View {
+
+    /**
+     * Provider to register the view.
+     */
+    @Priority(50)
+    public static final class Provider implements ViewProvider{
+
+        @Override
+        public ViewLifecycle getLifecycle() {
+            return ViewLifecycle.LAZY;
+        }
+
+        @Override
+        public String getName() {
+            return "view.edit.name";
+        }
+
+        @Override
+        public String getUrlPattern() {
+            return "/edit";
+        }
+
+        @Override
+        public String getDisplayName() {
+            return ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage("view.edit.name");
+        }
+
+        @Override
+        public View createView(Object... params){
+            return new ConfigUpdaterView();
+        }
+    }
+
+    private ProtocolWidget logWidget = new ProtocolWidget();
+    private PopupView logPopup = new PopupView("Show log", logWidget);
+
+    private MutableConfiguration mutableConfig = MutableConfigurationProvider.getMutableConfiguration();
+
+    private TransactionControlWidget taControl = new TransactionControlWidget(mutableConfig,
+            logWidget);
+    private PopupView taDetails = new PopupView("Transaction Details", taControl);
+
+    private ConfigEditorWidget editorWidget = new ConfigEditorWidget(mutableConfig, logWidget, taControl);
+
+
+    public ConfigUpdaterView() {
+        Label caption = new Label(ServiceContextManager.getServiceContext()
+                .getService(MessageProvider.class).getMessage("view.edit.name"));
+        Label description = new Label(ServiceContextManager.getServiceContext()
+                .getService(MessageProvider.class).getMessage("view.edit.description"),
+                ContentMode.HTML);
+
+        caption.addStyleName(UIConstants.LABEL_HUGE);
+        description.addStyleName(UIConstants.LABEL_LARGE);
+        logWidget.print("INFO: Writable Property Sources: ");
+        for(MutablePropertySource ps:mutableConfig.getMutablePropertySources()){
+            logWidget.print(ps.getName(), ", ");
+        }
+        logWidget.println();
+        logWidget.setHeight(100, Unit.PERCENTAGE);
+        HorizontalLayout hl = new HorizontalLayout(taDetails, logPopup);
+        hl.setSpacing(true);
+        addComponents(caption, description, editorWidget, hl);
+    }
+
+    private String getCaption(String key, String value) {
+        int index = key.lastIndexOf('.');
+        if(index<0){
+            return key + " = " + value;
+        }else{
+            return key.substring(index+1) + " = " + value;
+        }
+    }
+
+    @Override
+    public void enter(ViewChangeListener.ViewChangeEvent event) {
+
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ProtocolWidget.java
----------------------------------------------------------------------
diff --git a/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ProtocolWidget.java b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ProtocolWidget.java
new file mode 100644
index 0000000..2d78aee
--- /dev/null
+++ b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/ProtocolWidget.java
@@ -0,0 +1,90 @@
+/*
+ * 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.ui.mutableconfig;
+
+import com.vaadin.ui.Button;
+import com.vaadin.ui.TextArea;
+import com.vaadin.ui.VerticalLayout;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * Widget showing a text protocol wioth a clear button to clear the widget space.
+ */
+public class ProtocolWidget extends VerticalLayout{
+
+    private TextArea textArea = new TextArea(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.edit.textArea.protocol"));
+    private Button clearButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.clearProtocol"));
+
+    private StringWriter protocol = new StringWriter();
+    private PrintWriter writer = new PrintWriter(protocol);
+
+    public ProtocolWidget(){
+        textArea.setWidth(600, Unit.PIXELS);
+        textArea.setHeight(400, Unit.PERCENTAGE);
+        textArea.setReadOnly(true);
+        clearButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                protocol.getBuffer().setLength(0);
+                flush();
+            }
+        });
+        textArea.setSizeFull();
+        addComponents(textArea, clearButton);
+        setWidth(700, Unit.PIXELS);
+        setHeight(500, Unit.PERCENTAGE);
+    }
+
+    public PrintWriter getWriter(){
+        return writer;
+    }
+
+    public void println(){
+        writer.println();
+    }
+
+    public void println(Object... items){
+        for(int i=0;i<items.length;i++){
+            writer.print(items[i]);
+        }
+        writer.println();
+        flush();
+    }
+
+    public void print(Object... items){
+        for(int i=0;i<items.length;i++){
+            writer.print(items[i]);
+        }
+        flush();
+    }
+
+    private void flush(){
+        writer.flush();
+        textArea.setReadOnly(false);
+        textArea.setValue(protocol.toString());
+        textArea.setReadOnly(true);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/TransactionControlWidget.java
----------------------------------------------------------------------
diff --git a/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/TransactionControlWidget.java b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/TransactionControlWidget.java
new file mode 100644
index 0000000..d22328a
--- /dev/null
+++ b/ui/mutableconfig/src/main/java/org/apache/tamaya/ui/mutableconfig/TransactionControlWidget.java
@@ -0,0 +1,229 @@
+/*
+ * 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.ui.mutableconfig;
+
+import com.vaadin.data.Property;
+import com.vaadin.ui.*;
+import org.apache.tamaya.mutableconfig.ChangePropagationPolicy;
+import org.apache.tamaya.mutableconfig.MutableConfiguration;
+import org.apache.tamaya.mutableconfig.MutableConfigurationProvider;
+import org.apache.tamaya.mutableconfig.propertysources.ConfigChangeContext;
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.apache.tamaya.ui.components.VerticalSpacedLayout;
+import org.apache.tamaya.ui.services.MessageProvider;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Tamaya UI view to change configuration.
+ */
+public class TransactionControlWidget extends TabSheet {
+
+    private Field taID = new TextField("Transaction ID");
+    private Field taContent = new TextArea("Transaction Context");
+    private VerticalLayout taLayout = new VerticalLayout(taID, taContent);
+
+    private CheckBox autoCommit = new CheckBox(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.edit.box.autoCommit"));
+
+    private ComboBox changePropagationPolicy = new ComboBox(ServiceContextManager.getServiceContext()
+            .getService(MessageProvider.class).getMessage("view.edit.select.propagationPolicy"),
+            Arrays.asList(new String[]{"ALL", "MOST_SIGNIFICANT_ONLY", "NONE", "CUSTOM"}));
+
+    private TextField changePropagationPolicyOther = new TextField(
+            ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+                    .getMessage("view.edit.text.propagationPolicyOther"),
+            MutableConfigurationProvider.getApplyAllChangePolicy().getClass().getName());
+
+    private MutableConfiguration mutableConfig;
+    private Button startTAButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.startTransaction"));
+    private Button rollbackTAButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.rollbackTransaction"));
+    private Button commitTAButton = new Button(ServiceContextManager.getServiceContext().getService(MessageProvider.class)
+            .getMessage("view.edit.button.commitTransaction"));
+    private ProtocolWidget logWriter;
+    private VerticalSpacedLayout leftLayout = new VerticalSpacedLayout();
+
+    public TransactionControlWidget(MutableConfiguration mutableConfig, ProtocolWidget logWriter) {
+        taContent.setReadOnly(true);
+        taContent.setWidth(600, Unit.PIXELS);
+        taContent.setHeight(250, Unit.PIXELS);
+        taLayout.setWidth(600, Unit.PIXELS);
+        taID.setReadOnly(true);
+        this.mutableConfig = Objects.requireNonNull(mutableConfig);
+        this.logWriter = Objects.requireNonNull(logWriter);
+        changePropagationPolicy.setWidth(500, Unit.PIXELS);
+        changePropagationPolicyOther.setWidth(500, Unit.PIXELS);
+        HorizontalLayout buttonLayout = new HorizontalLayout();
+        buttonLayout.addComponents(startTAButton, commitTAButton, rollbackTAButton);
+        leftLayout.addComponents(changePropagationPolicy, changePropagationPolicyOther, buttonLayout);
+        addTab(leftLayout, "Transaction Control");
+        addTab(taLayout, "Transaction Details");
+        setWidth(600, Unit.PIXELS);
+        initActions();
+        update();
+    }
+
+    private void initActions() {
+        autoCommit.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
+                mutableConfig.setAutoCommit(autoCommit.getValue());
+                if(mutableConfig.getAutoCommit()) {
+                    Notification.show("Autocommit is now ON.",
+                            Notification.Type.TRAY_NOTIFICATION);
+                }else{
+                    Notification.show("Autocommit is now OFF.",
+                            Notification.Type.TRAY_NOTIFICATION);
+                }
+                logWriter.println(" - Set Auto-Commit to " + autoCommit.getValue());
+            }
+        });
+        changePropagationPolicy.addValueChangeListener(new Property.ValueChangeListener() {
+            @Override
+            public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
+                changePropagationPolicyOther.setEnabled(false);
+                changePropagationPolicyOther.addValueChangeListener(new Property.ValueChangeListener() {
+                    @Override
+                    public void valueChange(Property.ValueChangeEvent valueChangeEvent) {
+                        String className = changePropagationPolicyOther.getValue();
+                        try {
+                            mutableConfig.setChangePropagationPolicy(
+                                    (ChangePropagationPolicy) Class.forName(className).newInstance());
+                            logWriter.println(" - Set ChangePropagationPolicy " + className);
+                            Notification.show("ChangePropagationPolicy is now CUSTOM: " + className);
+                        } catch (Exception e) {
+                            Notification.show("Failed to apply change policy: " + className + ": " + e,
+                                    Notification.Type.ERROR_MESSAGE);
+                        }
+                    }
+                });
+                switch ((String) changePropagationPolicy.getValue()) {
+                    case "MOST_SIGNIFICANT_ONLY":
+                        mutableConfig.setChangePropagationPolicy(
+                                MutableConfigurationProvider.getApplyMostSignificantOnlyChangePolicy());
+                        Notification.show("ChangePropagationPolicy is now MOST_SIGNIFICANT_ONLY.",
+                                Notification.Type.TRAY_NOTIFICATION);
+                        logWriter.println(" - Set ChangePropagationPolicy to MOST_SIGNIFICANT_ONLY.");
+                        break;
+                    case "NONE":
+                        Notification.show("Applying none equals being your config READ-ONLY.",
+                                Notification.Type.ASSISTIVE_NOTIFICATION);
+                        mutableConfig.setChangePropagationPolicy(
+                                MutableConfigurationProvider.getApplyNonePolicy());
+                        Notification.show("ChangePropagationPolicy is now NONE.", Notification.Type.TRAY_NOTIFICATION);
+                        logWriter.println(" - Set ChangePropagationPolicy to NONE.");
+                        break;
+                    case "CUSTOM":
+                        changePropagationPolicyOther.setEnabled(true);
+                        break;
+                    case "ALL":
+                    default:
+                        mutableConfig.setChangePropagationPolicy(
+                                MutableConfigurationProvider.getApplyAllChangePolicy());
+                        Notification.show("ChangePropagationPolicy is now ALL.", Notification.Type.TRAY_NOTIFICATION);
+                        logWriter.println(" - Set ChangePropagationPolicy to ALL.");
+                }
+            }
+        });
+        startTAButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                String taId = mutableConfig.startTransaction();
+                update();
+                Notification.show("Transaction started: " + taId, Notification.Type.TRAY_NOTIFICATION);
+                logWriter.println("Started Transaction: " + taId);
+            }
+        });
+        rollbackTAButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                String taId = mutableConfig.getTransactionId();
+                mutableConfig.rollbackTransaction();
+                update();
+                Notification.show("Transaction rolled back: " + taId, Notification.Type.TRAY_NOTIFICATION);
+                logWriter.println("Rolled back Transaction: " + taId);
+            }
+        });
+        commitTAButton.addClickListener(new Button.ClickListener() {
+            @Override
+            public void buttonClick(Button.ClickEvent clickEvent) {
+                String taId = mutableConfig.getTransactionId();
+                mutableConfig.commitTransaction();
+                update();
+                Notification.show("Transaction comitted: "  + taId, Notification.Type.TRAY_NOTIFICATION);
+                logWriter.println("Committed Transaction: " + taId);
+            }
+        });
+    }
+
+    public void update(){
+        taID.setReadOnly(false);
+        taContent.setReadOnly(false);
+        if(mutableConfig.getTransactionId()==null){
+            taID.setValue("N/A");
+        }else {
+            taID.setValue(mutableConfig.getTransactionId());
+        }
+        StringBuilder b = new StringBuilder();
+        ConfigChangeContext changes = mutableConfig.getConfigChangeContext();
+        if(mutableConfig.getTransactionId()==null){
+            startTAButton.setEnabled(true);
+            rollbackTAButton.setEnabled(false);
+            commitTAButton.setEnabled(false);
+            changePropagationPolicy.setEnabled(true);
+            changePropagationPolicyOther.setEnabled(true);
+            b.append("No Transaction Context available.");
+        }else{
+            b.append("TA ID      : ").append(changes.getTransactionID()).append('\n');
+            b.append("Started at : ").append(changes.getStartedAt()).append("\n\n");
+            b.append("PUT:\n");
+            b.append("====\n");
+            for(Map.Entry<String,String> en:changes.getAddedProperties().entrySet()){
+                b.append(en.getKey()).append(" = ").append(en.getValue()).append("\n\n");
+            }
+            b.append("DEL:\n");
+            b.append("====\n");
+            for(String key:changes.getRemovedProperties()){
+                b.append(key).append("\n\n");
+            }
+            startTAButton.setEnabled(false);
+            rollbackTAButton.setEnabled(true);
+            commitTAButton.setEnabled(true);
+            changePropagationPolicy.setEnabled(false);
+            changePropagationPolicyOther.setEnabled(false);
+        }
+        taContent.setValue(b.toString());
+        taID.setReadOnly(true);
+        taContent.setReadOnly(true);
+    }
+
+    private String getCaption(String key, String value) {
+        int index = key.lastIndexOf('.');
+        if (index < 0) {
+            return key + " = " + value;
+        } else {
+            return key.substring(index + 1) + " = " + value;
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tamaya-sandbox/blob/e4b68dfb/ui/mutableconfig/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
----------------------------------------------------------------------
diff --git a/ui/mutableconfig/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider b/ui/mutableconfig/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
new file mode 100644
index 0000000..6d2b914
--- /dev/null
+++ b/ui/mutableconfig/src/main/resources/META-INF/services/org.apache.tamaya.ui.ViewProvider
@@ -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.
+#
+mutableconfig.ConfigUpdaterView$Provider
\ No newline at end of file