Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b377fd1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+.git
+.idea/**/*.xml
+.settings
+.classpath
+target
+/.idea/compiler.xml
+/.idea/*.xml
+/.idea/modules.xml
+/.idea/vcs.xml
+/bin/
+*.iml
+.project
+.classpath
+.idea
+/dependency-reduced-pom.xml
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..c9ab737
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,21 @@
+FROM myserver:withproxy
+#linux 16.04
+MAINTAINER Dimitris
+
+WORKDIR microservices
+
+RUN git clone  http://172.18.22.160:8880/gitblit-1.8.0/r/Dropwizard/Microservices/mics-central-service.git && cd mics-central-service && git checkout DEVELOP_BE
+
+WORKDIR mics-central-service
+
+RUN mvn install -DskipTests
+
+WORKDIR /
+
+COPY my_wrapper_script.sh my_wrapper_script.sh
+RUN sed -i -e 's/\r$//' my_wrapper_script.sh
+CMD ./my_wrapper_script.sh
+
+EXPOSE 9010 9011
+
+
diff --git a/How_to_dockerize_documentation.docx b/How_to_dockerize_documentation.docx
new file mode 100644
index 0000000..84b581e
--- /dev/null
+++ b/How_to_dockerize_documentation.docx
Binary files differ
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..0db6dd9
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,18 @@
+node {
+
+    stage('Clone repository') {
+        /* Let's make sure we have the repository cloned to our workspace */
+
+        checkout scm
+    }
+
+    stage('Build image') {
+        /* This builds the actual image; synonymous to
+         * docker build on the command line */
+		sh 'docker build --rm --no-cache -t myserver_central:jenkinsversion .'
+    }
+	
+	stage('Refresh containers') {
+		bat 'start cmd.exe /c C:\\Jenkinshelper\\refresh_docker.bat'
+	}
+}
\ No newline at end of file
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..11ecb79
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,198 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+   distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+    i) changes to the Program, and
+   ii) additions to the Program;
+
+   where such changes and/or additions to the Program originate from and are
+   distributed by that particular Contributor. A Contribution 'originates' from
+   a Contributor if it was added to the Program by such Contributor itself or
+   anyone acting on such Contributor's behalf. Contributions do not include
+   additions to the Program which: (i) are separate modules of software
+   distributed in conjunction with the Program under their own license
+   agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+  a) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free copyright license to
+     reproduce, prepare derivative works of, publicly display, publicly perform,
+     distribute and sublicense the Contribution of such Contributor, if any, and
+     such derivative works, in source code and object code form.
+  b) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free patent license under
+     Licensed Patents to make, use, sell, offer to sell, import and otherwise
+     transfer the Contribution of such Contributor, if any, in source code and
+     object code form. This patent license shall apply to the combination of the
+     Contribution and the Program if, at the time the Contribution is added by
+     the Contributor, such addition of the Contribution causes such combination
+     to be covered by the Licensed Patents. The patent license shall not apply
+     to any other combinations which include the Contribution. No hardware per
+     se is licensed hereunder.
+  c) Recipient understands that although each Contributor grants the licenses to
+     its Contributions set forth herein, no assurances are provided by any
+     Contributor that the Program does not infringe the patent or other
+     intellectual property rights of any other entity. Each Contributor
+     disclaims any liability to Recipient for claims brought by any other entity
+     based on infringement of intellectual property rights or otherwise. As a
+     condition to exercising the rights and licenses granted hereunder, each
+     Recipient hereby assumes sole responsibility to secure any other
+     intellectual property rights needed, if any. For example, if a third party
+     patent license is required to allow Recipient to distribute the Program, it
+     is Recipient's responsibility to acquire that license before distributing
+     the Program.
+  d) Each Contributor represents that to its knowledge it has sufficient
+     copyright rights in its Contribution, if any, to grant the copyright
+     license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its
+own license agreement, provided that:
+
+  a) it complies with the terms and conditions of this Agreement; and
+  b) its license agreement:
+      i) effectively disclaims on behalf of all Contributors all warranties and
+         conditions, express and implied, including warranties or conditions of
+         title and non-infringement, and implied warranties or conditions of
+         merchantability and fitness for a particular purpose;
+     ii) effectively excludes on behalf of all Contributors all liability for
+         damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits;
+    iii) states that any provisions which differ from this Agreement are offered
+         by that Contributor alone and not by any other party; and
+     iv) states that source code for the Program is available from such
+         Contributor, and informs licensees how to obtain it in a reasonable
+         manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+  a) it must be made available under this Agreement; and
+  b) a copy of this Agreement must be included with each copy of the Program.
+     Contributors may not remove or alter any copyright notices contained within
+     the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor to
+control, and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may participate in
+any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its exercise of
+rights under this Agreement , including but not limited to the risks and costs
+of program errors, compliance with applicable laws, damage to or loss of data,
+programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted under
+Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue and
+survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation
+may assign the responsibility to serve as the Agreement Steward to a suitable
+separate entity. Each new version of the Agreement will be given a
+distinguishing version number. The Program (including Contributions) may always
+be distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to distribute the Program (including its Contributions)
+under the new version. Except as expressly stated in Sections 2(a) and 2(b)
+above, Recipient receives no rights or licenses to the intellectual property of
+any Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted under
+this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..fc24ab4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# micsCentral
+
+How to start the micsCentral application
+---
+
+1. Run `mvn clean install` to build your application
+1. Start application with `java -jar target/mics-central-service-0.1.1-SNAPSHOT.jar server config.yml`
+1. To check that your application is running enter url `http://localhost:8080`
+
+Health Check
+---
+
+To see your applications health enter url `http://localhost:8081/healthcheck`
diff --git a/my_wrapper_script.sh b/my_wrapper_script.sh
new file mode 100644
index 0000000..b332df0
--- /dev/null
+++ b/my_wrapper_script.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+cd microservices/mics-central-service/
+java -jar target/mics-central-service.jar server serviceConfigDocker.yml
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..e3768dd
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,288 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <prerequisites>
+        <maven>3.0.0</maven>
+    </prerequisites>
+
+    <groupId>org.eclipse.openk</groupId>
+    <artifactId>mics-central-service</artifactId>
+    <version>0.1.3-SNAPSHOT</version>
+    <packaging>jar</packaging>
+
+    <name>mics-central-service</name>
+
+    <properties>
+        <java-source-target-version>1.8</java-source-target-version>
+        <maven.test.skip>false</maven.test.skip>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <mainClass>org.eclipse.openk.MicsCentralApplication</mainClass>
+
+        <dropwizard.version>1.3.1</dropwizard.version>
+        <easymock.version>3.4</easymock.version>
+        <powermock-api-easymock.version>1.6.6</powermock-api-easymock.version>
+        <jacoco-maven-plugin.version>0.7.9</jacoco-maven-plugin.version>
+        <sonar-maven-plugin.version>3.2</sonar-maven-plugin.version>
+        <commons-io.version>2.5</commons-io.version>
+        <gson.version>2.8.5</gson.version>
+        <httpclient.version>4.5.3</httpclient.version>
+        <swagger-maven-plugin-version>3.1.6</swagger-maven-plugin-version>
+        <swagger-jersey2-jaxrs>1.5.12</swagger-jersey2-jaxrs>
+        <maven-shade-plugin.version>2.4.1</maven-shade-plugin.version>
+        <maven-jar-plugin-version>2.6</maven-jar-plugin-version>
+        <maven-compiler-plugin-version>3.6.1</maven-compiler-plugin-version>
+        <maven-source-plugin-version>2.4</maven-source-plugin-version>
+        <maven-javadoc-plugin-version>2.10.3</maven-javadoc-plugin-version>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.dropwizard</groupId>
+                <artifactId>dropwizard-bom</artifactId>
+                <version>${dropwizard.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.dropwizard</groupId>
+            <artifactId>dropwizard-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <version>${easymock.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-module-junit4</artifactId>
+            <version>${powermock-api-easymock.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-easymock</artifactId>
+            <version>${powermock-api-easymock.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacoco</groupId>
+            <artifactId>jacoco-maven-plugin</artifactId>
+            <version>${jacoco-maven-plugin.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-jersey2-jaxrs</artifactId>
+            <version>${swagger-jersey2-jaxrs}</version>
+            <scope>compile</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.code.findbugs</groupId>
+                    <artifactId>annotations</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>${maven-shade-plugin.version}</version>
+                <configuration>
+                    <createDependencyReducedPom>true</createDependencyReducedPom>
+                    <transformers>
+                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
+                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                            <mainClass>${mainClass}</mainClass>
+                        </transformer>
+                    </transformers>
+                    <!-- exclude signed Manifests -->
+                    <filters>
+                        <filter>
+                            <artifact>*:*</artifact>
+                            <excludes>
+                                <exclude>META-INF/*.SF</exclude>
+                                <exclude>META-INF/*.DSA</exclude>
+                                <exclude>META-INF/*.RSA</exclude>
+                            </excludes>
+                        </filter>
+                    </filters>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>${maven-jar-plugin-version}</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addClasspath>true</addClasspath>
+                            <mainClass>${mainClass}</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin-version}</version>
+                <configuration>
+                    <source>${java-source-target-version}</source>
+                    <target>${java-source-target-version}</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-source-plugin</artifactId>
+                <version>${maven-source-plugin-version}</version>
+                <executions>
+                    <execution>
+                        <id>attach-sources</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <version>${maven-javadoc-plugin-version}</version>
+                <executions>
+                    <execution>
+                        <id>attach-javadocs</id>
+                        <goals>
+                            <goal>jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>sonar-maven-plugin</artifactId>
+                <version>${sonar-maven-plugin.version}</version>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>${jacoco-maven-plugin.version}</version>
+                <configuration>
+                    <skip>${maven.test.skip}</skip>
+                    <output>file</output>
+                    <append>true</append>
+                    <excludes>
+                        <exclude>**/Globals.*</exclude>
+                    </excludes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>jacoco-initialize</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>jacoco-site</id>
+                        <phase>verify</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>com.github.kongchen</groupId>
+                <artifactId>swagger-maven-plugin</artifactId>
+                <version>${swagger-maven-plugin-version}</version>
+                <configuration>
+                    <skipSwaggerGeneration>false</skipSwaggerGeneration>
+                    <apiSources>
+                        <apiSource>
+                            <springmvc>false</springmvc>
+                            <locations>
+                                <location>org.eclipse.openk</location>
+                            </locations>
+                            <schemes>
+                                <shema>http</shema>
+                            </schemes>
+                            <host>localhost:9010</host>
+                            <basePath>/mics/central</basePath>
+                            <info>
+                                <title>micsCentralService@openK - Backend REST-Service documentation</title>
+                                <version>v1</version>
+                                <description>This documentation contains the description of all used REST services.</description>
+                                <termsOfService>
+                                    .
+                                </termsOfService>
+                                <contact>
+                                    <email>nn@pta.de</email>
+                                    <name></name>
+                                </contact>
+                                <license>
+                                    <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
+                                    <name>Apache 2.0</name>
+                                </license>
+                            </info>
+                            <outputFormats>yaml</outputFormats>
+                            <templatePath>${basedir}/templates/strapdown.html.hbs</templatePath>
+                            <outputPath>target/generated-docs/swaggerInterfaceDocumentation.html</outputPath>
+                            <swaggerDirectory>target/generated-docs</swaggerDirectory>
+                            <securityDefinitions>
+                                <securityDefinition>
+                                    <json>/securityDefinitions.json</json>
+                                </securityDefinition>
+                            </securityDefinitions>
+                        </apiSource>
+                    </apiSources>
+                </configuration>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>
diff --git a/serviceConfigDevLocal.yml b/serviceConfigDevLocal.yml
new file mode 100644
index 0000000..eec7e02
--- /dev/null
+++ b/serviceConfigDevLocal.yml
@@ -0,0 +1,26 @@
+servicesDistributionFileName: servicesDistributionDevLocal.json
+proxyHost: webproxy3.pta.de
+proxyPort: 8080
+
+logging:
+  level: INFO
+  appenders:
+    - type: file
+      currentLogFilename: /log/mics-central-service.log
+      threshold: ALL
+      archive: true
+      archivedLogFilenamePattern: /log/mics-central-service-%d.log
+      archivedFileCount: 5
+      timeZone: UTC
+  loggers:
+    org.eclipse.openk: DEBUG
+    org.eclipse.jetty.servlets: DEBUG
+
+server:
+  applicationConnectors:
+  - type: http
+    port: 9010
+  adminConnectors:
+  - type: http
+    port: 9011
+
diff --git a/serviceConfigDevLocal_MASTER.yml b/serviceConfigDevLocal_MASTER.yml
new file mode 100644
index 0000000..0a83714
--- /dev/null
+++ b/serviceConfigDevLocal_MASTER.yml
@@ -0,0 +1,26 @@
+servicesDistributionFileName: servicesDistributionDevServer.json
+proxyHost:
+proxyPort:
+
+logging:
+  level: INFO
+  appenders:
+    - type: file
+      currentLogFilename: /log/mics-central-service.log
+      threshold: ALL
+      archive: true
+      archivedLogFilenamePattern: /log/mics-central-service-%d.log
+      archivedFileCount: 5
+      timeZone: UTC
+  loggers:
+    org.eclipse.openk: INFO
+    org.eclipse.jetty.servlets: DEBUG
+
+server:
+  applicationConnectors:
+  - type: http
+    port: 9010
+  adminConnectors:
+  - type: http
+    port: 9011
+
diff --git a/serviceConfigDocker.yml b/serviceConfigDocker.yml
new file mode 100644
index 0000000..38ea5bb
--- /dev/null
+++ b/serviceConfigDocker.yml
@@ -0,0 +1,25 @@
+servicesDistributionFileName: servicesDistributionDocker.json
+
+
+logging:
+  level: INFO
+  appenders:
+    - type: file
+      currentLogFilename: /log/mics-central-service.log
+      threshold: ALL
+      archive: true
+      archivedLogFilenamePattern: /log/mics-central-service-%d.log
+      archivedFileCount: 5
+      timeZone: UTC
+  loggers:
+    org.eclipse.openk: DEBUG
+    org.eclipse.jetty.servlets: DEBUG
+
+server:
+  applicationConnectors:
+  - type: http
+    port: 9010
+  adminConnectors:
+  - type: http
+    port: 9011
+
diff --git a/serviceConfig_QA.yml b/serviceConfig_QA.yml
new file mode 100644
index 0000000..e49270f
--- /dev/null
+++ b/serviceConfig_QA.yml
@@ -0,0 +1,26 @@
+servicesDistributionFileName: servicesDistributionQAServer.json
+proxyHost:
+proxyPort:
+
+logging:
+  level: INFO
+  appenders:
+    - type: file
+      currentLogFilename: /opt/mics/logs/mics-central-service.log
+      threshold: ALL
+      archive: true
+      archivedLogFilenamePattern: /opt/mics/logs/mics-central-service-%d.log
+      archivedFileCount: 5
+      timeZone: UTC
+  loggers:
+    org.eclipse.openk: DEBUG
+    org.eclipse.jetty.servlets: DEBUG
+
+server:
+  applicationConnectors:
+  - type: http
+    port: 9010
+  adminConnectors:
+  - type: http
+    port: 9011
+
diff --git a/servicesDistributionDevLocal.json b/servicesDistributionDevLocal.json
new file mode 100644
index 0000000..ec1db9b
--- /dev/null
+++ b/servicesDistributionDevLocal.json
@@ -0,0 +1,77 @@
+[
+  {
+    "active": "true",
+    "clustername": "elogbook.openK",
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "planned-grid-measures.openK",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/gridmeasures",
+        "portApp": "9050",
+        "portHealth": "9051",
+        "description": "Planned Grid Measures Backend"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      }
+    ]
+  },
+  {
+    "active": "true",
+    "clustername": "openK",
+    "description": "service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "planned-grid-measures.openK",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/gridmeasures",
+        "portApp": "9050",
+        "portHealth": "9051",
+        "description": "Planned Grid Measures Backend"
+      },
+      {
+        "active": "true",
+        "name": "authNauth.openK",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/portal/rest/beservice",
+        "healthUrlPath": "/portal/rest/beservice",
+        "portApp": "8080",
+        "portHealth": "8080",
+        "description": "Auth&Auth-Modul"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      },
+      {
+        "active": "true",
+        "name": "cim-cache",
+        "protocol": "https",
+        "host": "169.50.13.154",
+        "urlPath": "/domain",
+        "portApp": "443",
+        "portHealth": "",
+        "description": "CIM-Cache Domain API"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/servicesDistributionDevServer.json b/servicesDistributionDevServer.json
new file mode 100644
index 0000000..af6b818
--- /dev/null
+++ b/servicesDistributionDevServer.json
@@ -0,0 +1,77 @@
+[
+  {
+    "active": "true",
+    "clustername": "elogbook.openK",
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/authNAuth",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      }
+    ]
+  },
+  {
+    "active": "true",
+    "clustername": "openK",
+    "description": "service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "planned-grid-measures.openK",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/mics/gridmeasures",
+        "portApp": "9050",
+        "portHealth": "9051",
+        "description": "Planned Grid Measures Backend"
+      },
+      {
+        "active": "true",
+        "name": "authNauth.openK",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/portal/rest/beservice",
+        "healthUrlPath": "/portal/rest/beservice",
+        "portApp": "8880",
+        "portHealth": "8880",
+        "description": "Auth&Auth-Modul"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      },
+      {
+        "active": "true",
+        "name": "cim-cache",
+        "protocol": "https",
+        "host": "169.50.13.154",
+        "urlPath": "/domain",
+        "portApp": "443",
+        "portHealth": "",
+        "description": "CIM-Cache Domain API"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/servicesDistributionDocker.json b/servicesDistributionDocker.json
new file mode 100644
index 0000000..b2afaa4
--- /dev/null
+++ b/servicesDistributionDocker.json
@@ -0,0 +1,66 @@
+[
+  {
+    "active": "true",
+    "clustername": "elogbook.openK",
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "planned-grid-measures.openK",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/gridmeasures",
+        "portApp": "9050",
+        "portHealth": "9051",
+        "description": "Planned Grid Measures Backend"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      }
+    ]
+  },
+  {
+    "active": "true",
+    "clustername": "openK",
+    "description": "service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "planned-grid-measures.openK",
+        "protocol": "http",
+        "host": "172.25.0.88",
+        "urlPath": "/mics/gridmeasures",
+        "portApp": "9050",
+        "portHealth": "9051",
+        "description": "Planned Grid Measures Backend"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      },
+      {
+        "active": "true",
+        "name": "cim-cache",
+        "protocol": "https",
+        "host": "169.50.13.154",
+        "urlPath": "/domain",
+        "portApp": "443",
+        "portHealth": "",
+        "description": "CIM-Cache Domain API"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/servicesDistributionQAServer.json b/servicesDistributionQAServer.json
new file mode 100644
index 0000000..eb650f0
--- /dev/null
+++ b/servicesDistributionQAServer.json
@@ -0,0 +1,77 @@
+[
+  {
+    "active": "true",
+    "clustername": "elogbook.openK",
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "169.50.13.154",
+        "urlPath": "/authNAuth",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "169.50.13.154",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      }
+    ]
+  },
+  {
+    "active": "true",
+    "clustername": "openK",
+    "description": "service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "planned-grid-measures.openK",
+        "protocol": "http",
+        "host": "169.50.13.154",
+        "urlPath": "/mics/gridmeasures",
+        "portApp": "9050",
+        "portHealth": "9051",
+        "description": "Planned Grid Measures Backend"
+      },
+      {
+        "active": "true",
+        "name": "authNauth.openK",
+        "protocol": "http",
+        "host": "169.50.13.154",
+        "urlPath": "/portal/rest/beservice",
+        "healthUrlPath": "/portal/rest/beservice",
+        "portApp": "8080",
+        "portHealth": "8080",
+        "description": "Auth&Auth-Modul"
+      },
+      {
+        "active": "true",
+        "name": "mics-central-service",
+        "protocol": "http",
+        "host": "169.50.13.154",
+        "urlPath": "/mics/central",
+        "portApp": "9010",
+        "portHealth": "9011",
+        "description": "Mics Central Service-Configures and dispatches different service clusters for different modules"
+      },
+      {
+        "active": "true",
+        "name": "cim-cache",
+        "protocol": "https",
+        "host": "169.50.13.154",
+        "urlPath": "/domain",
+        "portApp": "443",
+        "portHealth": "",
+        "description": "CIM-Cache Domain API"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/sonar-project.properties b/sonar-project.properties
new file mode 100644
index 0000000..09164a6
--- /dev/null
+++ b/sonar-project.properties
@@ -0,0 +1,16 @@
+# must be unique in a given SonarQube instance
+sonar.projectKey=openk.pta.de:plannedGridMeasures-mics-central-service-BE
+# this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1.
+sonar.projectName=plannedGridMeasures-mics-central-service-BE
+sonar.projectVersion=0.0.1_Snapshot
+ 
+sonar.sourceEncoding=UTF-8
+sonar.sources=src/main
+sonar.language=java
+sonar.exclusions=**/common/Globals.java,**/rest/*.java,**/LoggerUtil.java,**/dao/*.java,**/dao/interfaces/*.java,**/controller/BackendController*.java,**/auth2/**/*.java,**/communication/RestServiceWrapper.java,**/controller/BackendController.java
+sonar.binaries=target/classes
+sonar.cpd.exclusions=**/model/*.java,**/api/*.java
+sonar.tests=src/test
+sonar.java.coveragePlugin=jacoco
+sonar.junit.reportPaths=target/surefire-reports
+sonar.jacoco.reportPath=target/jacoco.exec
diff --git a/src/main/java/org/eclipse/openk/MicsCentralApplication.java b/src/main/java/org/eclipse/openk/MicsCentralApplication.java
new file mode 100644
index 0000000..e0479a0
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/MicsCentralApplication.java
@@ -0,0 +1,85 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk;
+
+import com.codahale.metrics.health.HealthCheck;
+import io.dropwizard.Application;
+import io.dropwizard.setup.Bootstrap;
+import io.dropwizard.setup.Environment;
+import org.eclipse.jetty.servlets.CrossOriginFilter;
+import org.eclipse.openk.core.controller.BackendConfig;
+import org.eclipse.openk.core.controller.InitServicesConfigCacheJob;
+import org.eclipse.openk.health.ConfigFilePresentHealthCheck;
+import org.eclipse.openk.resources.MicsCentralResource;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.FilterRegistration;
+import java.util.EnumSet;
+
+public class MicsCentralApplication extends Application<MicsCentralConfiguration> {
+
+    public static void main(final String[] args) throws Exception {
+        new MicsCentralApplication().run(args);
+    }
+
+    @Override
+    public String getName() {
+        return "micsCentral";
+    }
+
+    @Override
+    public void initialize(final Bootstrap<MicsCentralConfiguration> bootstrap) {
+        // nothing to do here for now
+    }
+
+    @Override
+    public void run(final MicsCentralConfiguration configuration,
+                    final Environment environment) {
+
+        initAppEnvironment( configuration );
+
+        final MicsCentralResource micsCentralResource = new MicsCentralResource();
+        final HealthCheck configFilePresentHC = new ConfigFilePresentHealthCheck();
+
+        environment.healthChecks().register("configFilePresent", configFilePresentHC );
+        environment.jersey().register(micsCentralResource);
+
+        configureCors(environment);
+    }
+
+    private void initAppEnvironment( MicsCentralConfiguration conf ) {
+        InitServicesConfigCacheJob.init(conf.getServicesDistributionFileName());
+        BackendConfig.getInstance().setProxyHost(conf.getProxyHost());
+        BackendConfig.getInstance().setProxyPort(
+                Integer.parseInt(null != conf.getProxyPort() ? conf.getProxyPort() : "-1"));
+    }
+
+    private void configureCors(Environment environment) {
+        final FilterRegistration.Dynamic cors =
+                environment.servlets().addFilter("CORS", CrossOriginFilter.class);
+
+        // Configure CORS parameters
+        cors.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
+        cors.setInitParameter(CrossOriginFilter.TIMING_ALLOW_ORIGIN_HEADER, "*");
+        cors.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin,Authorization,X-XSRF-TOKEN");
+        cors.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "OPTIONS,GET,PUT,POST,DELETE,HEAD");
+        cors.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "true");
+
+        // Add URL mapping
+        cors.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
+        // DO NOT pass a preflight request to down-stream auth filters
+        // unauthenticated preflight requests should be permitted by spec
+        cors.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, Boolean.FALSE.toString());
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/MicsCentralConfiguration.java b/src/main/java/org/eclipse/openk/MicsCentralConfiguration.java
new file mode 100644
index 0000000..df7c7b0
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/MicsCentralConfiguration.java
@@ -0,0 +1,54 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk;
+
+import io.dropwizard.Configuration;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.hibernate.validator.constraints.*;
+
+public class MicsCentralConfiguration extends Configuration {
+    @NotEmpty
+    private String servicesDistributionFileName;
+
+    @JsonProperty
+    private String proxyHost;
+
+    @JsonProperty
+    private String proxyPort;
+
+    @JsonProperty
+    public String getServicesDistributionFileName() {
+        return servicesDistributionFileName;
+    }
+
+    @JsonProperty
+    public void setServicesDistributionFileName(String servicesDistributionFileName) {
+        this.servicesDistributionFileName = servicesDistributionFileName;
+    }
+
+    public String getProxyHost() {
+        return proxyHost;
+    }
+
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public String getProxyPort() {
+        return proxyPort;
+    }
+
+    public void setProxyPort(String proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/api/ServiceDistributionCluster.java b/src/main/java/org/eclipse/openk/api/ServiceDistributionCluster.java
new file mode 100644
index 0000000..5c5bc8b
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/api/ServiceDistributionCluster.java
@@ -0,0 +1,185 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.api;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.hibernate.validator.constraints.NotEmpty;
+
+
+public class ServiceDistributionCluster {
+
+    public static class ServiceDistribution {
+
+        private boolean active;
+
+        @NotEmpty
+        private String name;
+
+        @NotEmpty
+        private String host;
+
+        @NotEmpty
+        private String urlPath;
+
+        private String healthUrlPath;
+
+        @NotEmpty
+        private String protocol;
+
+        @NotEmpty
+        private Integer portApp;
+
+        private Integer portHealth;
+
+        private String description;
+
+        public ServiceDistribution() {
+            // public default construction
+        }
+
+        @JsonProperty
+        public boolean isActive() {
+            return active;
+        }
+
+        @JsonProperty
+        public void setActive(boolean active) {
+            this.active = active;
+        }
+
+        @JsonProperty
+        public String getName() {
+            return name;
+        }
+
+        @JsonProperty
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        @JsonProperty
+        public String getHost() {
+            return host;
+        }
+
+        @JsonProperty
+        public void setHost(String host) {
+            this.host = host;
+        }
+
+        @JsonProperty
+        public String getUrlPath() {
+            return urlPath;
+        }
+
+        @JsonProperty
+        public void setUrlPath(String urlPath) {
+            this.urlPath = urlPath;
+        }
+
+        public String getHealthUrlPath() {
+            return healthUrlPath;
+        }
+
+        public void setHealthUrlPath(String healthUrlPath) {
+            this.healthUrlPath = healthUrlPath;
+        }
+
+        @JsonProperty
+        public String getProtocol() {
+            return protocol;
+        }
+
+        @JsonProperty
+        public void setProtocol(String protocol) {
+            this.protocol = protocol;
+        }
+
+        @JsonProperty
+        public int getPortApp() {
+            return portApp;
+        }
+
+        @JsonProperty
+        public void setPortApp(int portApp) {
+            this.portApp = portApp;
+        }
+
+        @JsonProperty
+        public String getDescription() {
+            return description;
+        }
+
+        @JsonProperty
+        public void setDescription(String description) {
+            this.description = description;
+        }
+
+        @JsonProperty
+        public Integer getPortHealth() {
+            return portHealth;
+        }
+
+        @JsonProperty
+        public void setPortHealth(Integer portHealth) {
+            this.portHealth = portHealth;
+        }
+    }
+
+    private boolean active;
+
+    @NotEmpty
+    private String clustername;
+
+    private String description;
+
+    private ServiceDistribution[] distributions;
+
+    @JsonProperty
+    public boolean isActive() {
+        return active;
+    }
+
+    @JsonProperty
+    public void setActive(boolean active) {
+        this.active = active;
+    }
+
+    @JsonProperty
+    public String getClustername() {
+        return clustername;
+    }
+
+    @JsonProperty
+    public void setClustername(String clustername) {
+        this.clustername = clustername;
+    }
+
+    @JsonProperty
+    public String getDescription() {
+        return description;
+    }
+
+    @JsonProperty
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public ServiceDistribution[] getDistributions() {
+        return distributions;
+    }
+
+    public void setDistributions(ServiceDistribution[] distributions) {
+        this.distributions = distributions;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/api/ServiceRequestEnvelope.java b/src/main/java/org/eclipse/openk/api/ServiceRequestEnvelope.java
new file mode 100644
index 0000000..61abca8
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/api/ServiceRequestEnvelope.java
@@ -0,0 +1,118 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.api;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.log4j.Logger;
+import org.glassfish.jersey.internal.util.Base64;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+public class ServiceRequestEnvelope {
+    private static final Logger logger = Logger.getLogger(ServiceRequestEnvelope.class);
+    public static class HttpHeader {
+        private String attribute;
+        private String value;
+
+        public String getAttribute() {
+            return attribute;
+        }
+
+        public void setAttribute(String attribute) {
+            this.attribute = attribute;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+
+    private String serviceName;
+    private String method;
+    private String uriFragment;
+    private String payload;
+    private HttpHeader[] headers;
+
+    @JsonProperty
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    @JsonProperty
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    @JsonProperty
+    public String getMethod() {
+        return method;
+    }
+
+    @JsonProperty
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    @JsonProperty
+    public String getUriFragment() {
+        return uriFragment;
+    }
+
+    @JsonProperty
+    public void setUriFragment(String uriFragment) {
+        this.uriFragment = uriFragment;
+    }
+
+    @JsonProperty
+    public String getPayload() {
+        return payload;
+    }
+
+    @JsonProperty
+    public void setPayload(String payload) {
+        this.payload = payload;
+    }
+
+    @JsonProperty
+    public HttpHeader[] getHeaders() {
+        return headers;
+    }
+
+    @JsonProperty
+    public void setHeaders(HttpHeader[] headers) {
+        this.headers = headers;
+    }
+
+    public String getPayloadDecode() {
+        if( payload != null && !payload.isEmpty()) {
+            try {
+                return URLDecoder.decode(Base64.decodeAsString(payload), "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                logger.error("Unsupported Encoding", e);
+                return "";
+            }
+        }
+        else {
+            return "";
+        }
+    }
+
+    public void setPayloadEncode(String payload) {
+        this.payload = Base64.encodeAsString(payload);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/api/VersionInfo.java b/src/main/java/org/eclipse/openk/api/VersionInfo.java
new file mode 100644
index 0000000..a5bc079
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/api/VersionInfo.java
@@ -0,0 +1,27 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.api;
+
+public class VersionInfo {
+    private String backendVersion;
+
+    public String getBackendVersion() {
+        return backendVersion;
+    }
+
+    public void setBackendVersion(String backendVersion) {
+        this.backendVersion = backendVersion;
+    }
+
+
+}
diff --git a/src/main/java/org/eclipse/openk/core/common/Globals.java b/src/main/java/org/eclipse/openk/core/common/Globals.java
new file mode 100644
index 0000000..0331396
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/common/Globals.java
@@ -0,0 +1,22 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.common;
+
+
+public final class Globals {
+    public static final String HEADER_JSON_UTF8 = "application/json; charset=utf-8";
+    public static final String HEALTH_CHECK_ADD_PATH = "healthcheck?pretty=true";
+
+    private Globals() {
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/core/common/GsonUTCDateAdapter.java b/src/main/java/org/eclipse/openk/core/common/GsonUTCDateAdapter.java
new file mode 100644
index 0000000..e284869
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/common/GsonUTCDateAdapter.java
@@ -0,0 +1,47 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.common;
+
+import com.google.gson.*;
+
+import java.lang.reflect.Type;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class GsonUTCDateAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
+
+    private final DateFormat dateFormat;
+
+    public GsonUTCDateAdapter() {
+        dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);      //This is the format I need
+        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));                               //This is the key line which converts the date to UTC which cannot be accessed with the default serializer
+    }
+
+    @Override
+    public synchronized JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
+        return new JsonPrimitive(dateFormat.format(date));
+    }
+
+    @Override
+    public synchronized Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) {
+        try {
+            return dateFormat.parse(jsonElement.getAsString());
+        } catch (ParseException e) {
+            throw new JsonParseException(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/core/common/JsonGeneratorBase.java b/src/main/java/org/eclipse/openk/core/common/JsonGeneratorBase.java
new file mode 100644
index 0000000..5f1a734
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/common/JsonGeneratorBase.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.common;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.util.Date;
+
+public class JsonGeneratorBase {
+    private JsonGeneratorBase() {}
+    public static Gson getGson() {
+        return new GsonBuilder()
+                .registerTypeAdapter(Date.class, new GsonUTCDateAdapter())
+                .disableHtmlEscaping()
+                .create();
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/core/common/util/ResourceLoaderBase.java b/src/main/java/org/eclipse/openk/core/common/util/ResourceLoaderBase.java
new file mode 100644
index 0000000..0619003
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/common/util/ResourceLoaderBase.java
@@ -0,0 +1,38 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.common.util;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.InputStream;
+import java.io.StringWriter;
+
+public class ResourceLoaderBase {
+    private String stream2String(InputStream is) {
+        StringWriter writer = new StringWriter();
+        try {
+            IOUtils.copy(is, writer, "UTF-8");
+        } catch (Exception e) { // NOSONAR
+            return "";
+        }
+        return writer.toString();
+
+
+    }
+
+    public String loadStringFromResource(String filename) {
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        InputStream jsonstream = classLoader.getResourceAsStream(filename);
+        return stream2String(jsonstream);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/core/communication/RestServiceWrapper.java b/src/main/java/org/eclipse/openk/core/communication/RestServiceWrapper.java
new file mode 100644
index 0000000..1a16b9a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/communication/RestServiceWrapper.java
@@ -0,0 +1,221 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.communication;
+
+
+import org.apache.commons.httpclient.HostConfiguration;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.*;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.util.EntityUtils;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.core.common.Globals;
+import org.eclipse.openk.core.controller.BackendConfig;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+
+public class RestServiceWrapper {
+    public static class HttpHeader {
+        private String attribute;
+        private String value;
+
+        public HttpHeader(String attribute, String value) {
+            this.attribute = attribute;
+            this.value = value;
+        }
+
+        public String getAttribute() {
+            return attribute;
+        }
+
+        public void setAttribute(String attribute) {
+            this.attribute = attribute;
+        }
+
+        public String getValue() {
+            return value;
+        }
+
+        public void setValue(String value) {
+            this.value = value;
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(RestServiceWrapper.class.getName());
+    private boolean useHttps;
+
+    public enum HttpMethod {GET, POST, PUT, DELETE}
+
+    public RestServiceWrapper(boolean https) {
+        this.useHttps = https;
+    }
+
+    public static HttpHeader createHeader(String attribute, String value) {
+        return new HttpHeader(attribute, value);
+    }
+
+    public String performGetRequest(String restFunctionWithParams) throws HttpStatusException {
+        LOGGER.debug("CompleteUrl: " + restFunctionWithParams);
+        // create HTTP Client
+        CloseableHttpClient httpClient = createHttpsClient();
+
+        // create new Request with given URL
+        HttpGet getRequest = new HttpGet(restFunctionWithParams);
+        getRequest.addHeader("accept", Globals.HEADER_JSON_UTF8);
+
+        HttpResponse response;
+        // Execute request an catch response
+        try {
+            response = httpClient.execute(getRequest);
+
+        } catch (IOException e) {
+            String errtext = "Get communication to <" + restFunctionWithParams + "> failed.";
+            LOGGER.warn(errtext, e);
+            throw new HttpStatusException(HttpStatus.SC_SERVICE_UNAVAILABLE);
+        }
+
+        return createJson(response);
+    }
+
+    public String performPostRequest(String restFunctionWithParams, String data) throws HttpStatusException {
+
+        // create HTTP Client
+        CloseableHttpClient httpClient = createHttpsClient();
+
+        // create new Post Request with given URL
+        HttpPost postRequest = new HttpPost(restFunctionWithParams);
+
+        // add additional header to getRequest which accepts application/JSON data
+        postRequest.addHeader("accept", Globals.HEADER_JSON_UTF8);
+        postRequest.addHeader("Content-Type", Globals.HEADER_JSON_UTF8);
+
+        postRequest.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
+
+        HttpResponse response;
+        // Execute request an catch response
+        try {
+            response = httpClient.execute(postRequest);
+        } catch (IOException e) {
+            String errtext = "Post communication to <" + restFunctionWithParams + "> failed!";
+            LOGGER.warn(errtext, e);
+            throw new HttpStatusException(HttpStatus.SC_SERVICE_UNAVAILABLE);
+        }
+        return createJson(response);
+    }
+
+    public Response performHttpRequest(HttpMethod method, String restFunctionWithParams,
+                                       List<HttpHeader> headerList, String data) throws HttpStatusException {
+
+        // create HTTP Client
+        try (CloseableHttpClient httpClient = createHttpsClient() ) {
+
+            HttpRequestBase request = createRequest(method, restFunctionWithParams, data);
+            for (HttpHeader header : headerList) {
+                request.addHeader(header.attribute, header.value);
+            }
+
+            HttpResponse response;
+            // Execute request an catch response
+            response = httpClient.execute(request);
+
+
+            String ent = createJson(response);
+
+            Response.ResponseBuilder rb = Response.status(response.getStatusLine().getStatusCode());
+            if (ent != null) {
+                rb.entity(ent);
+            }
+            return rb.build();
+        } catch (IOException e) {
+            String errtext = "Communication to <" + restFunctionWithParams + "> failed...";
+            LOGGER.warn(errtext, e);
+            throw new HttpStatusException(HttpStatus.SC_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    private HttpRequestBase createRequest(HttpMethod method, String restFunctionWithParams, String data) throws HttpStatusException {
+        HttpRequestBase ret;
+        switch (method) {
+            case GET:
+                ret = new HttpGet(restFunctionWithParams);
+                break;
+            case POST:
+                ret = setPayload(new HttpPost(restFunctionWithParams), data);
+                break;
+            case PUT:
+                ret = setPayload(new HttpPut(restFunctionWithParams), data);
+                break;
+            case DELETE:
+                ret = new HttpDelete(restFunctionWithParams);
+                break;
+            default:
+                throw new HttpStatusException(HttpStatus.SC_METHOD_NOT_ALLOWED);
+        }
+        return ret;
+    }
+
+    private HttpRequestBase setPayload(HttpEntityEnclosingRequestBase req, String data) {
+        req.setEntity(new StringEntity(data, StandardCharsets.UTF_8));
+        return req;
+    }
+
+
+    private CloseableHttpClient createHttpsClient() throws HttpStatusException {
+        if (useHttps) {
+            try {
+                SSLContextBuilder builder = new SSLContextBuilder();
+                builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
+                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier());
+
+                String proxyHost = BackendConfig.getInstance().getProxyHost();
+                int proxyPort = BackendConfig.getInstance().getProxyPort();
+                if (proxyHost != null && !proxyHost.isEmpty()){
+                    return HttpClients.custom().setSSLSocketFactory(sslsf).setProxy(new HttpHost(proxyHost, proxyPort)).build();
+                }
+
+                return HttpClients.custom().setSSLSocketFactory(sslsf).build();
+            } catch (Exception e) {
+                LOGGER.error(e);
+                throw new HttpStatusException(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+            }
+        } else {
+            return HttpClientBuilder.create().build();
+        }
+    }
+
+    private String createJson(HttpResponse response) throws HttpStatusException {
+        String retJson;
+        try {
+            retJson = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            LOGGER.error(e);
+            throw new HttpStatusException(HttpStatus.SC_INTERNAL_SERVER_ERROR);
+        }
+
+        return retJson;
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/BackendConfig.java b/src/main/java/org/eclipse/openk/core/controller/BackendConfig.java
new file mode 100644
index 0000000..1af2080
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/BackendConfig.java
@@ -0,0 +1,31 @@
+package org.eclipse.openk.core.controller;
+
+public class BackendConfig {
+
+  static final private BackendConfig instance = new BackendConfig();
+
+  private String proxyHost;
+  private int proxyPort;
+
+  private BackendConfig(){}
+
+  public static BackendConfig getInstance(){
+    return instance;
+  }
+
+  public String getProxyHost() {
+    return proxyHost;
+  }
+
+  public void setProxyHost(String proxyHost) {
+    this.proxyHost = proxyHost;
+  }
+
+  public int getProxyPort() {
+    return proxyPort;
+  }
+
+  public void setProxyPort(int proxyPort) {
+    this.proxyPort = proxyPort;
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/BaseWebService.java b/src/main/java/org/eclipse/openk/core/controller/BaseWebService.java
new file mode 100644
index 0000000..1d321f7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/BaseWebService.java
@@ -0,0 +1,70 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.util.Properties;
+
+public class BaseWebService {
+    @FunctionalInterface
+    public interface Invokable <T> {
+        public T invoke() throws Exception; // NOSONAR
+    }
+    private final Logger logger;
+
+    protected BaseWebService(Logger logger) {
+        this.logger = logger;
+    }
+
+    protected Response invokeRunnable(Invokable runnable)
+    {
+        try  { // NOSONAR
+            Object o =  runnable.invoke();
+            return Response.ok(o).build();
+        } catch (HttpStatusException hse) {
+            logger.error(hse);
+            return Response.status(hse.getHttpStatus()).build();
+        }
+        catch (Exception e) {
+            logger.error("Caught unexpected Exception:", e);
+            return Response.status(HttpStatus.INTERNAL_SERVER_ERROR_500).build();
+        }
+    }
+
+
+    protected String getVersionString() {
+        try {
+            // determine static VersionInfo
+            final Properties properties = new Properties();
+
+            properties.load(BaseWebService.class.getClassLoader().getResourceAsStream("project.properties"));
+
+            String beversion = properties.getProperty("backend.version");
+            if( beversion.contains("$")) {
+                beversion = "LOCAL-DEV";
+            }
+            return beversion;
+        } catch (IOException e) {
+            logger.error("Exception reading the properties file", e);
+            throw new RuntimeException("Exception during start up"); // NOSONAR
+        }
+    }
+
+
+
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/CentralController.java b/src/main/java/org/eclipse/openk/core/controller/CentralController.java
new file mode 100644
index 0000000..7a48009
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/CentralController.java
@@ -0,0 +1,109 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.api.VersionInfo;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.core.common.Globals;
+import org.eclipse.openk.core.communication.RestServiceWrapper;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+public class CentralController {
+    private static final Logger logger = Logger.getLogger(CentralController.class);
+
+    public ServiceDistributionCluster readServerDistribution(String cluster) throws HttpStatusException {
+        ServiceDistributionCluster[] dcs = ServicesConfigCache.getInstance().getCache();
+
+        for (ServiceDistributionCluster item : dcs) {
+            if (item.getClustername().equalsIgnoreCase(cluster) && item.isActive()) {
+                return removeInactiveItems(item);
+            }
+        }
+        logger.error("There is no cluster name equals with " + cluster + " or the cluster is not active.");
+        throw new HttpStatusException(HttpStatus.NOT_FOUND_404);
+    }
+
+    public VersionInfo getVersionInfo(String version ) {
+        VersionInfo vi = new VersionInfo();
+        vi.setBackendVersion( version );
+        return vi;
+    }
+
+
+    protected RestServiceWrapper createRestServiceWrapper( boolean isHttps ) {
+        return new RestServiceWrapper(isHttps);
+    }
+
+    public String getServiceHealthState(String clustername, String servicename) throws HttpStatusException {
+
+        ServiceDistributionCluster.ServiceDistribution dist = findDistribution(clustername, servicename);
+        RestServiceWrapper w = createRestServiceWrapper(false );
+        StringBuilder url = new StringBuilder();
+        url.append(dist.getProtocol() + "://" + dist.getHost() + ":"
+                + dist.getPortHealth());
+
+        if( dist.getHealthUrlPath() != null ) {
+            url.append(dist.getUrlPath());
+        }
+        url.append("/" + Globals.HEALTH_CHECK_ADD_PATH );
+
+        return w.performGetRequest(url.toString());
+    }
+
+    private ServiceDistributionCluster.ServiceDistribution findDistribution(String clustername,
+                                                                            String servicename) throws HttpStatusException {
+        ServiceDistributionCluster cluster = getCluster(ServicesConfigCache.getInstance().getCache(), clustername);
+
+        Optional<ServiceDistributionCluster.ServiceDistribution> dist = Arrays.stream(cluster.getDistributions())
+                .filter(e -> e.isActive() && e.getName().equals(servicename))
+                .findFirst();
+
+        if(dist.isPresent()) {
+            return dist.get();
+        }
+        else {
+            throw new HttpStatusException(HttpStatus.NOT_FOUND_404);
+        }
+    }
+
+    private ServiceDistributionCluster getCluster(ServiceDistributionCluster[] clusterArray, String clustername) throws HttpStatusException {
+        List<ServiceDistributionCluster> clusterList = Arrays.asList(clusterArray);
+        Optional<ServiceDistributionCluster> ret = clusterList.stream()
+                .filter(c -> c.getClustername().equals(clustername)).findFirst();
+
+        if (ret.isPresent()) {
+            return ret.get();
+        } else {
+            logger.info("Could not find a cluster with the name: " + clustername);
+            throw new HttpStatusException(HttpStatus.NOT_FOUND_404);
+        }
+    }
+
+    private ServiceDistributionCluster removeInactiveItems( ServiceDistributionCluster cluster ) {
+        List<ServiceDistributionCluster.ServiceDistribution> dlist = Arrays.asList(cluster.getDistributions());
+        dlist = dlist.stream().filter(ServiceDistributionCluster.ServiceDistribution::isActive).collect(Collectors.toList());
+        ServiceDistributionCluster.ServiceDistribution[] distArr
+                = new ServiceDistributionCluster.ServiceDistribution[dlist.size()];
+        cluster.setDistributions(dlist.toArray(distArr));
+        return cluster;
+    }
+
+
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/DispatchController.java b/src/main/java/org/eclipse/openk/core/controller/DispatchController.java
new file mode 100644
index 0000000..68125bb
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/DispatchController.java
@@ -0,0 +1,77 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import com.google.common.collect.Lists;
+import org.apache.log4j.Logger;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.api.ServiceDistributionCluster.ServiceDistribution;
+import org.eclipse.openk.api.ServiceRequestEnvelope;
+import org.eclipse.openk.core.communication.RestServiceWrapper;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.ws.rs.core.Response;
+import java.util.List;
+
+import static java.util.stream.Collectors.toList;
+
+public class DispatchController {
+    private static Logger logger = Logger.getLogger(DispatchController.class);
+
+    public Response dispatch(String clustername, ServiceRequestEnvelope envelope) throws HttpStatusException {
+
+        List<RestServiceWrapper.HttpHeader> transformedList = Lists.newArrayList(envelope.getHeaders()).stream()
+                .map(header ->
+                        RestServiceWrapper.createHeader(header.getAttribute(), header.getValue())).collect(toList());
+
+        String url = locateBaseUrl(ServicesConfigCache.getInstance().getCache(),
+                clustername, envelope.getServiceName())
+                + envelope.getUriFragment();
+
+        RestServiceWrapper rsWrap = createRestServiceWrapper(url.toUpperCase().startsWith("HTTPS"));
+        return rsWrap.performHttpRequest(resolveMethod(envelope.getMethod()),
+                url, transformedList, envelope.getPayloadDecode());
+    }
+
+    protected RestServiceWrapper createRestServiceWrapper(boolean useHttps) {
+        return new RestServiceWrapper(useHttps);
+    }
+
+    private String locateBaseUrl(ServiceDistributionCluster[] cluster, String clustername, String servicename) throws HttpStatusException {
+        ServiceDistribution dist = new ServiceResolver(cluster)
+                .resolve(clustername, servicename);
+        if (dist == null) {
+            logger.error("Service [" + clustername + "]/[" + servicename + "] is not resolvable!");
+            throw new HttpStatusException(HttpStatus.NOT_FOUND_404);
+        }
+        return dist.getProtocol() + "://" + dist.getHost() + ":" + dist.getPortApp() + dist.getUrlPath();
+    }
+
+    private RestServiceWrapper.HttpMethod resolveMethod(String method) throws HttpStatusException {
+        switch (method.toUpperCase()) {
+            case "GET":
+                return RestServiceWrapper.HttpMethod.GET;
+            case "POST":
+                return RestServiceWrapper.HttpMethod.POST;
+            case "PUT":
+                return RestServiceWrapper.HttpMethod.PUT;
+            case "DELETE":
+                return RestServiceWrapper.HttpMethod.DELETE;
+            default:
+                logger.error("Invalid Method: " + method);
+                throw new HttpStatusException(HttpStatus.METHOD_NOT_ALLOWED_405);
+        }
+
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/InitServicesConfigCacheJob.java b/src/main/java/org/eclipse/openk/core/controller/InitServicesConfigCacheJob.java
new file mode 100644
index 0000000..41642d0
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/InitServicesConfigCacheJob.java
@@ -0,0 +1,33 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.apache.log4j.Logger;
+
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class InitServicesConfigCacheJob {
+
+    private static final Logger LOGGER = Logger.getLogger(InitServicesConfigCacheJob.class.getName());
+
+    private InitServicesConfigCacheJob() {
+    }
+
+    public static void init( String configFileName ) {
+        LOGGER.info("InitServicesConfigCacheJob called");
+        TimerTask timerTask = new ServicesConfigCacheTimerTask(configFileName);
+        Timer timer = new Timer();
+        timer.scheduleAtFixedRate(timerTask, 100, 5000L);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/ServiceResolver.java b/src/main/java/org/eclipse/openk/core/controller/ServiceResolver.java
new file mode 100644
index 0000000..fe6e12c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/ServiceResolver.java
@@ -0,0 +1,43 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.api.ServiceDistributionCluster.ServiceDistribution;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+public class ServiceResolver {
+    private final ServiceDistributionCluster[] clusters;
+
+    public ServiceResolver(ServiceDistributionCluster[] clusters) {
+        this.clusters = clusters;
+    }
+
+    public ServiceDistribution resolve(String clustername, String servicename) {
+        Optional<ServiceDistributionCluster> cluster
+                = Arrays.stream(clusters).filter(
+                x -> x.getClustername().equalsIgnoreCase(clustername)).findFirst();
+        if (cluster.isPresent()) {
+            Optional<ServiceDistributionCluster.ServiceDistribution> dist =
+                    Arrays.stream(cluster.get().getDistributions())
+                            .filter(x -> x.getName().equalsIgnoreCase(servicename))
+                            .findFirst();
+            if (dist.isPresent()) {
+                return dist.get();
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/ServicesConfigCache.java b/src/main/java/org/eclipse/openk/core/controller/ServicesConfigCache.java
new file mode 100644
index 0000000..ea276d7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/ServicesConfigCache.java
@@ -0,0 +1,89 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.log4j.Logger;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validation;
+import javax.validation.Validator;
+import javax.validation.ValidatorFactory;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Set;
+
+public class ServicesConfigCache {
+  private static final Logger logger = Logger.getLogger(ServicesConfigCache.class.getName());
+    private static ServicesConfigCache instance = new ServicesConfigCache();
+  private static final Object lock = new Object();
+
+  private ServiceDistributionCluster[] cache;
+
+  private ServicesConfigCache(){
+  }
+
+  public static ServicesConfigCache getInstance() {
+      return instance;
+  }
+
+
+  public void readServerDistribution(String configFileName) throws HttpStatusException {
+    try {
+      ServiceDistributionCluster[] dcs = readServerDistributionFromText(new String(Files.readAllBytes(Paths.get(configFileName)), Charset.forName("UTF-8")));
+      synchronized( lock ) {
+        cache = dcs;
+      }
+
+    } catch (IOException e) {
+      logger.error("Could not read file "+configFileName+"!", e);
+      throw new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR_500);
+    }
+  }
+
+  private ServiceDistributionCluster[] readServerDistributionFromText(String jsonText) throws HttpStatusException {
+    ServiceDistributionCluster[] dcs;
+
+    try {
+      final ObjectMapper mapper = new ObjectMapper();
+      dcs = mapper.readValue(jsonText, ServiceDistributionCluster[].class);
+    } catch (IOException e) {
+      logger.error("Could not parse file!", e);
+      throw new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR_500);
+    }
+
+    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
+    Validator validator = factory.getValidator();
+
+    for (ServiceDistributionCluster item : dcs) {
+      Set<ConstraintViolation<ServiceDistributionCluster>> violations
+              = validator.validate(item);
+        if (!violations.isEmpty()) {
+        logger.error("Error in configfile!: ");
+        throw new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR_500);
+      }
+    }
+    return dcs;
+  }
+
+  public ServiceDistributionCluster[] getCache() {
+    synchronized( lock ) {
+      return cache;
+    }
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/core/controller/ServicesConfigCacheTimerTask.java b/src/main/java/org/eclipse/openk/core/controller/ServicesConfigCacheTimerTask.java
new file mode 100644
index 0000000..136a26f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/controller/ServicesConfigCacheTimerTask.java
@@ -0,0 +1,37 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import java.util.TimerTask;
+
+public class ServicesConfigCacheTimerTask extends TimerTask {
+  private static final Logger logger = Logger.getLogger(ServicesConfigCacheTimerTask.class.getName());
+  private String configFileName;
+
+  public ServicesConfigCacheTimerTask( String configFileName ) {
+    this.configFileName = configFileName;
+  }
+
+
+  @Override
+  public void run() {
+    try {
+      ServicesConfigCache.getInstance().readServerDistribution(this.configFileName);
+    } catch (HttpStatusException e) {
+      logger.error("Error reading ServerDistributionFile", e);
+    }
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/core/exceptions/HttpStatusException.java b/src/main/java/org/eclipse/openk/core/exceptions/HttpStatusException.java
new file mode 100644
index 0000000..f9348b7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/core/exceptions/HttpStatusException.java
@@ -0,0 +1,25 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.exceptions;
+
+public class HttpStatusException extends Exception {
+    private final int httpStatus;
+
+    public HttpStatusException(int httpStatus ) {
+        this.httpStatus = httpStatus;
+    }
+
+    public int getHttpStatus() {
+        return httpStatus;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/health/ConfigFilePresentHealthCheck.java b/src/main/java/org/eclipse/openk/health/ConfigFilePresentHealthCheck.java
new file mode 100644
index 0000000..924d1e7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/health/ConfigFilePresentHealthCheck.java
@@ -0,0 +1,31 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.health;
+
+import com.codahale.metrics.health.HealthCheck;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.core.controller.ServicesConfigCache;
+
+public class ConfigFilePresentHealthCheck extends HealthCheck {
+    @Override
+    protected Result check() throws Exception {
+        ServiceDistributionCluster[] sdc = ServicesConfigCache.getInstance().getCache(); // Throws Exception if it fails
+
+        if (sdc != null && sdc.length > 0) {
+            return Result.healthy();
+        }
+        else {
+            return Result.unhealthy("No ServiceDistributionCluster available!");
+        }
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java b/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java
new file mode 100644
index 0000000..61e62a1
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java
@@ -0,0 +1,96 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.resources;
+
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.api.VersionInfo;
+import org.eclipse.openk.core.common.JsonGeneratorBase;
+import org.eclipse.openk.core.controller.DispatchController;
+import org.hibernate.validator.constraints.NotEmpty;
+import org.eclipse.openk.api.ServiceRequestEnvelope;
+import org.eclipse.openk.core.controller.CentralController;
+import org.eclipse.openk.core.controller.BaseWebService;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Api(value = "/mics/gridmeasures")
+@ApiResponses( value ={
+        @ApiResponse(code = 200, message = "OK",response = VersionInfo.class,reference = "#/definitions/VersionInfo"),
+        @ApiResponse(code = 400, message = "Bad Request"),
+        @ApiResponse(code = 401, message = "Unauthorized"),
+        @ApiResponse(code = 404, message = "Not found"),
+        @ApiResponse(code = 423, message = "Locked"),
+        @ApiResponse(code = 500, message = "Internal Server Error") } )
+@Path("/mics/central")
+@Produces(MediaType.APPLICATION_JSON)
+public class MicsCentralResource extends BaseWebService{
+    private static Logger logger = Logger.getLogger(MicsCentralResource.class.getName());
+
+    public MicsCentralResource() {
+        super(logger);
+    }
+
+    @ApiOperation(value = "Service Distribution", notes = "This service returns the available distributions for a given cluster")
+    @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK") } )
+    @GET
+    @Path("/serviceDistribution/{clustername}")
+    public Response getServiceDistribution(@ApiParam(name = "clustername", value = "The name of the cluster")
+                                           @PathParam("clustername") @NotEmpty String clustername) {
+        return invokeRunnable(() -> new CentralController().readServerDistribution(clustername));
+    }
+
+    @ApiOperation(value = "Health state check", notes = "This service checks if the components of a service are healthy")
+    @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK") } )
+    @GET
+    @Path("/serviceHealthState/{clustername}/{servicename}")
+    public Response getClusterHealthState(@ApiParam(name = "clustername", value = "The name of the cluster")
+                                          @PathParam("clustername") @NotEmpty String clustername,
+                                          @ApiParam(name = "servicename", value = "The name of the service")
+                                          @PathParam("servicename") @NotEmpty String servicename) {
+        return invokeRunnable(() -> new CentralController().getServiceHealthState(clustername, servicename));
+    }
+
+    @ApiOperation(value = "Dispatcher", notes = "")
+    @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK") } )
+    @POST
+    @Path("/dispatch/{clustername}")
+    public Response dispatch(String envelope,
+                             @ApiParam(name = "clustername", value = "The name of the cluster")
+                             @PathParam("clustername") @NotEmpty String clustername) {
+        ServiceRequestEnvelope envObj = JsonGeneratorBase.getGson().fromJson(envelope, ServiceRequestEnvelope.class);
+
+        try {
+            return new DispatchController().dispatch(clustername, envObj);
+        } catch (HttpStatusException hse) {
+            logger.error(hse);
+            return Response.status(hse.getHttpStatus()).build();
+        }
+    }
+
+    @ApiOperation(value = "Version Information", notes = "This services displays the version infos of this backend and the connected database.")
+    @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK", response = VersionInfo.class,reference = "#/definitions/VersionInfo") } )
+    @GET
+    @Path("/versionInfo")
+    public Response getVersionInfo() {
+        return invokeRunnable(() -> new CentralController().getVersionInfo(getVersionString()));
+    }
+}
diff --git a/src/main/resources/banner.txt b/src/main/resources/banner.txt
new file mode 100644
index 0000000..561b172
--- /dev/null
+++ b/src/main/resources/banner.txt
@@ -0,0 +1,6 @@
+================================================================================
+
+                              micsCentral
+
+================================================================================
+
diff --git a/src/main/resources/project.properties b/src/main/resources/project.properties
new file mode 100644
index 0000000..25e06ec
--- /dev/null
+++ b/src/main/resources/project.properties
@@ -0,0 +1 @@
+backend.version =${project.version}
\ No newline at end of file
diff --git a/src/main/resources/securityDefinitions.json b/src/main/resources/securityDefinitions.json
new file mode 100644
index 0000000..7183dfd
--- /dev/null
+++ b/src/main/resources/securityDefinitions.json
@@ -0,0 +1,16 @@
+{
+  "api_key": {
+    "type": "apiKey",
+    "name": "api_key",
+    "in": "header"
+  },
+  "Existing JWT token": {
+    "type": "oauth2",
+    "authorizationUrl": "http://swagger.io/api/oauth/dialog",
+    "flow": "implicit",
+    "scopes": {
+      "scope1": "scope description 1",
+      "scope2": "scope description 2"
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/org/eclipse/openk/MicsCentralApplicationTest.java b/src/test/java/org/eclipse/openk/MicsCentralApplicationTest.java
new file mode 100644
index 0000000..a8acd29
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/MicsCentralApplicationTest.java
@@ -0,0 +1,92 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk;
+
+import com.codahale.metrics.health.HealthCheckRegistry;
+import io.dropwizard.jersey.setup.JerseyEnvironment;
+import io.dropwizard.jetty.setup.ServletEnvironment;
+import io.dropwizard.setup.Environment;
+import org.easymock.EasyMock;
+import org.eclipse.jetty.servlets.CrossOriginFilter;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import javax.servlet.FilterRegistration;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replay;
+
+public class MicsCentralApplicationTest {
+
+    @Test
+    public void testGetName() {
+        assertEquals( "micsCentral", new MicsCentralApplication().getName());
+    }
+
+    @Test
+    public void testRun() {
+
+        MicsCentralConfiguration conf = createConfiguration();
+        MicsCentralApplication mca = new MicsCentralApplication();
+        mca.run(conf, createMockedEnvironment());
+
+    }
+
+    @Test
+    public void testRun2() throws Exception {
+        MicsCentralApplication mca = new MicsCentralApplication();
+        Whitebox.invokeMethod(mca, "configureCors", createMockedEnvironment() );
+    }
+
+    @Test
+    public void testInitialize() {
+        new MicsCentralApplication().initialize(null);
+    }
+
+    private MicsCentralConfiguration createConfiguration() {
+        MicsCentralConfiguration c = new MicsCentralConfiguration();
+        c.setServicesDistributionFileName("src/test/resources/testServiceDistributions.json");
+        c.setProxyHost(null);
+        c.setProxyPort(null);
+        return c;
+    }
+
+    private Environment createMockedEnvironment() {
+        FilterRegistration.Dynamic cors = EasyMock.createMock(FilterRegistration.Dynamic.class);
+        expect(cors.setInitParameter(anyString(), anyString())).andReturn( Boolean.TRUE ).anyTimes();
+        cors.addMappingForUrlPatterns(anyObject(), anyBoolean(), anyString());
+        expectLastCall();
+        replay( cors );
+
+        ServletEnvironment se = EasyMock.createMock(ServletEnvironment.class);
+        expect(se.addFilter(eq("CORS"), eq(CrossOriginFilter.class))).andReturn(cors).anyTimes();
+        replay(se);
+
+        JerseyEnvironment je = EasyMock.createMock(JerseyEnvironment.class);
+        je.register(anyObject());
+        expectLastCall();
+
+        HealthCheckRegistry hcr = EasyMock.createMock(HealthCheckRegistry.class);
+        hcr.register(anyString(), anyObject());
+        expectLastCall();
+
+        Environment environment = EasyMock.createMock( Environment.class );
+        expect( environment.servlets() ).andReturn(se).anyTimes();
+        expect( environment.jersey() ).andReturn(je).anyTimes();
+        expect( environment.healthChecks() ).andReturn(hcr).anyTimes();
+        replay( environment );
+        verify( environment );
+        return environment;
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/api/ServiceDistributionClusterTest.java b/src/test/java/org/eclipse/openk/api/ServiceDistributionClusterTest.java
new file mode 100644
index 0000000..21341a1
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/api/ServiceDistributionClusterTest.java
@@ -0,0 +1,82 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.api;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class ServiceDistributionClusterTest {
+
+    private ServiceDistributionCluster.ServiceDistribution createDistribution(
+            boolean active, String name, String host, String urlPath, String healthUrlPath, String protocol,
+            Integer portApp, Integer portHealth, String description) {
+
+        ServiceDistributionCluster.ServiceDistribution sd = new ServiceDistributionCluster.ServiceDistribution();
+        sd.setActive(true);
+        sd.setName(name);
+        sd.setHost(host);
+        sd.setUrlPath(urlPath);
+        if( healthUrlPath != null) {
+            sd.setHealthUrlPath(healthUrlPath);
+        }
+        sd.setProtocol(protocol);
+        sd.setPortApp(portApp);
+        sd.setPortHealth(portHealth);
+        sd.setDescription(description);
+
+        return sd;
+    }
+
+    @Test
+    public void testPojo() throws IOException {
+        List<ServiceDistributionCluster.ServiceDistribution> distList = new ArrayList<>();
+        distList.add(createDistribution(true, "Hugo", "1.2.3.4", "19/eleven",
+                "healthy","httpx",
+                1000, 2000, "Hugo ist toll"));
+        distList.add(createDistribution(false, "Bruno Haferkamp", "2.3.4.5", "seven/of/nine", "httpxy",
+                null,10, null, "Bruno ist noch toller"));
+        ServiceDistributionCluster.ServiceDistribution[] arr
+                = new ServiceDistributionCluster.ServiceDistribution[distList.size()];
+        ServiceDistributionCluster cluster = new ServiceDistributionCluster();
+
+        cluster.setDistributions(distList.toArray(arr));
+        cluster.setClustername("Kleister");
+        cluster.setActive(true);
+        cluster.setDescription("The cluster of kleister!");
+
+        ObjectMapper om = new ObjectMapper();
+        String json = om.writeValueAsString(cluster);
+
+        ServiceDistributionCluster inCluster = om.readValue(json, ServiceDistributionCluster.class);
+
+        assertEquals(cluster.getClustername(), inCluster.getClustername());
+        assertEquals(cluster.isActive(), inCluster.isActive());
+        assertEquals(cluster.getDescription(), inCluster.getDescription());
+        for (int i = 0; i < cluster.getDistributions().length; i++) {
+            assertEquals(cluster.getDistributions()[i].getName(), inCluster.getDistributions()[i].getName());
+            assertEquals(cluster.getDistributions()[i].getHost(), inCluster.getDistributions()[i].getHost());
+            assertEquals(cluster.getDistributions()[i].getUrlPath(), inCluster.getDistributions()[i].getUrlPath());
+            assertEquals(cluster.getDistributions()[i].isActive(), inCluster.getDistributions()[i].isActive());
+            assertEquals(cluster.getDistributions()[i].getPortApp(), inCluster.getDistributions()[i].getPortApp());
+            assertEquals(cluster.getDistributions()[i].getPortHealth(), inCluster.getDistributions()[i].getPortHealth());
+            assertEquals(cluster.getDistributions()[i].getDescription(), inCluster.getDistributions()[i].getDescription());
+            assertEquals(cluster.getDistributions()[i].getProtocol(), inCluster.getDistributions()[i].getProtocol());
+        }
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/api/ServiceRequestEnvelopeTest.java b/src/test/java/org/eclipse/openk/api/ServiceRequestEnvelopeTest.java
new file mode 100644
index 0000000..8e8258f
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/api/ServiceRequestEnvelopeTest.java
@@ -0,0 +1,58 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.api;
+
+import org.glassfish.jersey.internal.util.Base64;
+import org.junit.Test;
+
+import static junit.framework.TestCase.assertEquals;
+
+public class ServiceRequestEnvelopeTest {
+
+    @Test
+    public void testPojo() {
+       final String payload = "Testme Accurate";
+        final String payloadEncoded = Base64.encodeAsString(payload);
+        ServiceRequestEnvelope env = new ServiceRequestEnvelope();
+        env.setMethod("POST");
+        env.setPayloadEncode(payload);
+        env.setUriFragment("Fraggel");
+        env.setServiceName("Salve");
+
+        ServiceRequestEnvelope.HttpHeader[] headers = new ServiceRequestEnvelope.HttpHeader[2];
+        headers[0] = new ServiceRequestEnvelope.HttpHeader();
+        headers[0].setAttribute("1stAttr");
+        headers[0].setValue("1stValue");
+        headers[1] = new ServiceRequestEnvelope.HttpHeader();
+        headers[1].setAttribute("2ndAttr");
+        headers[1].setValue("2ndValue");
+        env.setHeaders(headers);
+
+        assertEquals("POST", env.getMethod());
+        assertEquals(payload, env.getPayloadDecode());
+        assertEquals(payloadEncoded, env.getPayload());
+        env.setPayload(payload);
+        assertEquals(payload, env.getPayload());
+        assertEquals("Fraggel", env.getUriFragment());
+        assertEquals("Salve", env.getServiceName());
+        assertEquals(2, env.getHeaders().length);
+        assertEquals("2ndAttr", env.getHeaders()[1].getAttribute());
+        assertEquals("1stValue", env.getHeaders()[0].getValue());
+
+        env.setPayload(null);
+        assertEquals("", env.getPayloadDecode());
+
+        env.setPayload("");
+        assertEquals("", env.getPayloadDecode());
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/api/VersionInfoTest.java b/src/test/java/org/eclipse/openk/api/VersionInfoTest.java
new file mode 100644
index 0000000..fa9b197
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/api/VersionInfoTest.java
@@ -0,0 +1,36 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.api;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+
+public class VersionInfoTest {
+
+    @Test
+    public void testGetVersionInfo() throws IOException {
+        VersionInfo vi = new VersionInfo();
+        vi.setBackendVersion("123");
+
+        ObjectMapper om = new ObjectMapper();
+        String jsonString = om.writeValueAsString(vi);
+
+        VersionInfo vi2 = om.readValue(jsonString, VersionInfo.class);
+
+        assertEquals(vi.getBackendVersion(), vi2.getBackendVersion());
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/core/common/GsonUTCDateAdapterTest.java b/src/test/java/org/eclipse/openk/core/common/GsonUTCDateAdapterTest.java
new file mode 100644
index 0000000..06c574c
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/common/GsonUTCDateAdapterTest.java
@@ -0,0 +1,66 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.common;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonSerializationContext;
+import org.junit.Test;
+
+import java.lang.reflect.Type;
+import java.util.Calendar;
+
+public class GsonUTCDateAdapterTest {
+
+    @Test
+    public void serializeTest() {
+        GsonUTCDateAdapter gsonUTCDateAdapter = new GsonUTCDateAdapter();
+        Calendar calendar = Calendar.getInstance();
+        java.util.Date date = calendar.getTime();
+        Type type = new Type() {
+            @Override
+            public String getTypeName() {
+                return null;
+            }
+        };
+        JsonSerializationContext jsonSerializationContext = new JsonSerializationContext() {
+            @Override
+            public JsonElement serialize(Object o) {
+                return null;
+            }
+
+            @Override
+            public JsonElement serialize(Object o, Type type) {
+                return null;
+            }
+        };
+
+        JsonElement je = gsonUTCDateAdapter.serialize(date, type, jsonSerializationContext);
+
+        // run through generator code base
+        JsonGeneratorBase.getGson();
+
+
+        JsonDeserializationContext jsonDeserializationContext = new JsonDeserializationContext() {
+            @Override
+            public <T> T deserialize(JsonElement jsonElement, Type type) throws JsonParseException {
+                return null;
+            }
+        };
+
+
+        gsonUTCDateAdapter.deserialize(je, type, jsonDeserializationContext);
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/core/common/util/ResourceLoaderBaseTest.java b/src/test/java/org/eclipse/openk/core/common/util/ResourceLoaderBaseTest.java
new file mode 100644
index 0000000..9247f87
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/common/util/ResourceLoaderBaseTest.java
@@ -0,0 +1,27 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.common.util;
+
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class ResourceLoaderBaseTest {
+    @Test
+    public void testloadStringFromResourceError() {
+        ResourceLoaderBase rlb = new ResourceLoaderBase();
+        String str = rlb.loadStringFromResource("UNKNOWN_FILE");
+        assertEquals("", str);
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/core/controller/BaseWebServiceTest.java b/src/test/java/org/eclipse/openk/core/controller/BaseWebServiceTest.java
new file mode 100644
index 0000000..2b5ac28
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/controller/BaseWebServiceTest.java
@@ -0,0 +1,75 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.core.common.util.ResourceLoaderBase;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.ws.rs.core.Response;
+
+import static org.junit.Assert.*;
+
+public class BaseWebServiceTest extends ResourceLoaderBase {
+	private static final org.apache.log4j.Logger EMPTYLOGGER = org.apache.log4j.Logger
+			.getLogger(BaseWebServiceTest.class.getName());
+
+	private BaseWebService createBaseWebService() {
+		return new BaseWebService(EMPTYLOGGER);
+	}
+
+	private BaseWebService.Invokable createInvokable( Object o, Exception e2Return ) {
+		return () -> {
+            if( e2Return == null ) {
+                return o;
+            }
+            else {
+                throw e2Return;
+            }
+        };
+	}
+
+	@Test
+	public void testInvokeRunnableOK() {
+		Response r = createBaseWebService().invokeRunnable(createInvokable("Test Ok", null));
+		assertEquals(HttpStatus.OK_200, r.getStatus());
+	}
+
+	@Test
+	public void testInvokeRunnable_HttpStatusException() {
+		Response r = createBaseWebService().invokeRunnable(createInvokable(null,
+				new HttpStatusException(HttpStatus.BAD_REQUEST_400)));
+		assertEquals(HttpStatus.BAD_REQUEST_400, r.getStatus());
+	}
+
+	@Test
+	public void testInvokeRunnable_GeneralException() {
+		Response r = createBaseWebService().invokeRunnable(createInvokable( null,
+				new Exception("hallodri")));
+		assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, r.getStatus());
+	}
+
+	@Test
+	public void testGetVersionString() throws Exception {
+		BaseWebService bws = createBaseWebService();
+		String version = (String) Whitebox.invokeMethod(bws, "getVersionString");
+		assertNotNull(version);
+		assertNotEquals(version, "");
+	}
+
+
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/core/controller/CentralControllerTest.java b/src/test/java/org/eclipse/openk/core/controller/CentralControllerTest.java
new file mode 100644
index 0000000..cfd8e84
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/controller/CentralControllerTest.java
@@ -0,0 +1,154 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.easymock.EasyMock;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.api.VersionInfo;
+import org.eclipse.openk.core.common.util.ResourceLoaderBase;
+import org.eclipse.openk.core.communication.RestServiceWrapper;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class CentralControllerTest {
+
+    private ServiceDistributionCluster baseTestReadServerDistribution(String clustername, String jsonFile) throws Exception {
+        ResourceLoaderBase resourceLoaderBase = new ResourceLoaderBase();
+        String json = resourceLoaderBase.loadStringFromResource(jsonFile);
+
+        ServicesConfigCache scc = ServicesConfigCache.getInstance();
+        ServiceDistributionCluster[] sdc = (ServiceDistributionCluster[])
+                Whitebox.invokeMethod(scc,"readServerDistributionFromText", json);
+
+        Whitebox.setInternalState(scc, "cache", sdc);
+
+        CentralController be = new CentralController();
+
+        ServiceDistributionCluster ret = be.readServerDistribution(clustername);
+
+        return ret;
+    }
+
+    @Test
+    public void testReadServerDistribution() throws Exception {
+
+        ServiceDistributionCluster sdc = baseTestReadServerDistribution("elogbook.openK", "testServiceDistributions.json");
+
+        assertEquals("elogbook.openK", sdc.getClustername());
+        assertEquals(2, sdc.getDistributions().length);
+        assertEquals("172.18.22.160", sdc.getDistributions()[0].getHost());
+    }
+
+    @Test
+    public void testFailReadServerDistribution() throws Exception {
+        try {
+            baseTestReadServerDistribution("doesntMatter", "testServiceDist_False.json");
+        } catch( HttpStatusException e ) {
+            assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, e.getHttpStatus());
+        }
+    }
+
+    @Test
+    public void testReadServerDistribution_notfound() throws Exception {
+        try {
+            ServiceDistributionCluster sdc = baseTestReadServerDistribution("invalidCluster", "testServiceDistributions.json");
+        } catch( HttpStatusException e ) {
+            assertEquals(HttpStatus.NOT_FOUND_404, e.getHttpStatus());
+        }
+    }
+
+    @Test
+    public void testReadServerDistribution_activeInactive() throws Exception {
+        ServiceDistributionCluster sdc = baseTestReadServerDistribution( "elogbook.openk", "testServiceDistributionsTwo_OneIsInactive.json");
+
+        assertEquals( 1, sdc.getDistributions().length);
+        assertTrue( sdc.getDistributions()[0].isActive());
+        assertEquals( "172.18.22.160", sdc.getDistributions()[0].getHost());
+    }
+
+    @Test (expected = HttpStatusException.class)
+    public void testFindDistribution_notFound() throws Exception {
+        ServiceDistributionCluster sdc = baseTestReadServerDistribution("elogbook.openK", "testServiceDistributions.json");
+        CentralController cc = new CentralController();
+        try {
+            Whitebox.invokeMethod(cc, "findDistribution", "elogbook.openK", "testService");
+        }
+        catch( HttpStatusException hse ) {
+            assertEquals(HttpStatus.NOT_FOUND_404, hse.getHttpStatus());
+            throw hse;
+        }
+    }
+
+    @Test
+    public void testFindDistribution_ok() throws Exception {
+        ServiceDistributionCluster sdc = baseTestReadServerDistribution("elogbook.openK", "testServiceDistributions.json");
+        CentralController cc = new CentralController();
+
+        Whitebox.invokeMethod(cc, "findDistribution", "elogbook.openK", "auth-n-auth.mics");
+
+    }
+
+
+    @Test (expected = HttpStatusException.class)
+    public void testFindDistribution_clusterNotFound() throws Exception {
+        ServiceDistributionCluster sdc = baseTestReadServerDistribution("elogbook.openK", "testServiceDistributions.json");
+        CentralController cc = new CentralController();
+        try {
+            Whitebox.invokeMethod(cc, "findDistribution", "invalidCluster", "auth-n-auth.mics");
+        }
+        catch( HttpStatusException hse ) {
+            assertEquals(HttpStatus.NOT_FOUND_404, hse.getHttpStatus());
+            throw hse;
+        }
+    }
+
+    @Test
+    public void testGetVersionInfo() throws Exception {
+        CentralController cc = new CentralController();
+        assertEquals("Bruno2.0", cc.getVersionInfo("Bruno2.0").getBackendVersion());
+        assertTrue(Whitebox.invokeMethod(cc, "createRestServiceWrapper", true) instanceof RestServiceWrapper );
+    }
+
+
+    @Test
+    public void testHealthCheck() throws Exception {
+        ServiceDistributionCluster sdc = baseTestReadServerDistribution("elogbook.openK", "testServiceDistributions.json");
+        CentralController cc = new CentralController() {
+            @Override
+            protected RestServiceWrapper createRestServiceWrapper( boolean isHttps ) {
+                RestServiceWrapper wrapper = EasyMock.createMock( RestServiceWrapper.class );
+                try {
+                    expect( wrapper.performGetRequest(  anyObject()) ).andReturn("Ist OK!").anyTimes();
+                } catch (HttpStatusException e) {
+                    return null;
+                }
+                replay( wrapper );
+                verify( wrapper );
+                return wrapper;
+            }
+
+        };
+
+
+        assertEquals("Ist OK!", cc.getServiceHealthState("elogbook.openK", "auth-n-auth.mics"));
+        assertEquals("Ist OK!", cc.getServiceHealthState("elogbook.openK", "homie"));
+
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/core/controller/DispatchControllerTest.java b/src/test/java/org/eclipse/openk/core/controller/DispatchControllerTest.java
new file mode 100644
index 0000000..6d7aad3
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/controller/DispatchControllerTest.java
@@ -0,0 +1,114 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.easymock.EasyMock;
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.api.ServiceRequestEnvelope;
+import org.eclipse.openk.core.common.JsonGeneratorBase;
+import org.eclipse.openk.core.common.util.ResourceLoaderBase;
+import org.eclipse.openk.core.communication.RestServiceWrapper;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import javax.ws.rs.core.Response;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.anyString;
+import static org.junit.Assert.assertEquals;
+
+public class DispatchControllerTest extends ResourceLoaderBase {
+
+    @Before
+    public void init() {
+        String clusterString = this.loadStringFromResource("servicesDistributionTest.json");
+        ServiceDistributionCluster[] cluster = JsonGeneratorBase.getGson()
+                .fromJson(clusterString, ServiceDistributionCluster[].class);
+        ServicesConfigCache cache = ServicesConfigCache.getInstance();
+        Whitebox.setInternalState(cache, "cache", cluster);
+
+
+    }
+
+    @Test
+    public void testDispatch_ok() throws HttpStatusException {
+        Response response = Response.ok().entity("{ret: '111'}").build();
+        final RestServiceWrapper rester = EasyMock.createMock(RestServiceWrapper.class);
+        EasyMock.expect(rester.performHttpRequest(anyObject(),
+                anyString(), anyObject(), anyString())).andReturn(response);
+        EasyMock.replay(rester);
+        ServiceRequestEnvelope envelope = JsonGeneratorBase.getGson().fromJson(
+                loadStringFromResource("serviceRequestEnvelope.json"), ServiceRequestEnvelope.class);
+
+
+        DispatchController controller = new DispatchController() {
+            @Override
+            protected RestServiceWrapper createRestServiceWrapper(boolean b) {
+                return rester;
+            }
+        };
+
+        Response resp2 = controller.dispatch("elogbook.openk", envelope);
+        assertEquals(HttpStatus.OK_200, resp2.getStatus());
+
+    }
+
+    @Test(expected = HttpStatusException.class)
+    public void testDispatch_InvCluster() throws HttpStatusException {
+
+        Response response = Response.ok().entity("{ret: '111'}").build();
+        final RestServiceWrapper rester = EasyMock.createMock(RestServiceWrapper.class);
+        EasyMock.expect(rester.performHttpRequest(anyObject(),
+                anyString(), anyObject(), anyString())).andReturn(response);
+        EasyMock.replay(rester);
+        ServiceRequestEnvelope envelope = JsonGeneratorBase.getGson().fromJson(
+                loadStringFromResource("serviceRequestEnvelope.json"), ServiceRequestEnvelope.class);
+
+
+        DispatchController controller = new DispatchController() {
+            @Override
+            protected RestServiceWrapper createRestServiceWrapper(boolean b) {
+                return rester;
+            }
+        };
+
+        try {
+            controller.dispatch("invalid", envelope);
+        } catch (HttpStatusException hse) {
+            assertEquals(HttpStatus.NOT_FOUND_404, hse.getHttpStatus());
+            throw hse;
+        }
+    }
+
+    @Test(expected = HttpStatusException.class)
+    public void testResolveMethod() throws Exception {
+        DispatchController ctrl = new DispatchController();
+        assertEquals(RestServiceWrapper.HttpMethod.GET, Whitebox.invokeMethod(ctrl, "resolveMethod", "get"));
+        assertEquals(RestServiceWrapper.HttpMethod.POST, Whitebox.invokeMethod(ctrl, "resolveMethod", "Post"));
+        assertEquals(RestServiceWrapper.HttpMethod.DELETE, Whitebox.invokeMethod(ctrl, "resolveMethod", "DELETE"));
+        assertEquals(RestServiceWrapper.HttpMethod.PUT, Whitebox.invokeMethod(ctrl, "resolveMethod", "put"));
+
+        String s;
+        try {
+            s = Whitebox.invokeMethod(ctrl, "resolveMethod", "invalid");
+        } catch (HttpStatusException hse) {
+            // the correct test path goes in here!!!!!!
+            assertEquals(HttpStatus.METHOD_NOT_ALLOWED_405, hse.getHttpStatus());
+            throw hse;
+        }
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/core/controller/ServicesConfigCacheTest.java b/src/test/java/org/eclipse/openk/core/controller/ServicesConfigCacheTest.java
new file mode 100644
index 0000000..e699fca
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/controller/ServicesConfigCacheTest.java
@@ -0,0 +1,73 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.core.common.util.ResourceLoaderBase;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class ServicesConfigCacheTest {
+
+    private ServiceDistributionCluster[] baseTestReadServerDistribution(String jsonFile) throws Exception {
+        ResourceLoaderBase resourceLoaderBase = new ResourceLoaderBase();
+        String json = resourceLoaderBase.loadStringFromResource(jsonFile);
+
+        ServicesConfigCache scc = ServicesConfigCache.getInstance();
+        return Whitebox.invokeMethod(scc, "readServerDistributionFromText", json);
+    }
+
+    @Test
+    public void testReadServerDistribution() throws Exception {
+
+        ServiceDistributionCluster[] sdc = baseTestReadServerDistribution("testServiceDistributions.json");
+
+        assertEquals("elogbook.openK", sdc[0].getClustername());
+        assertEquals(2, sdc[0].getDistributions().length);
+        assertEquals("172.18.22.160", sdc[0].getDistributions()[0].getHost());
+    }
+
+    @Test
+    public void testFailReadServerDistribution() throws Exception {
+        try {
+            baseTestReadServerDistribution("testServiceDist_False.json");
+        } catch( HttpStatusException e ) {
+            assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, e.getHttpStatus());
+        }
+    }
+
+    @Test
+    public void testReadServerDistribution_FileNotExist() throws Exception {
+        try {
+            baseTestReadServerDistribution("Nowhere.json");
+        } catch (HttpStatusException e) {
+            assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, e.getHttpStatus());
+        }
+    }
+
+    @Test
+    public void testReadServerDistribution_FileNotExistEither() throws Exception {
+        try {
+            ServicesConfigCache.getInstance().readServerDistribution("Nowhere.json");
+        } catch (HttpStatusException e) {
+            assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, e.getHttpStatus());
+        }
+    }
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/core/controller/ServicesConfigCacheTimerTaskTest.java b/src/test/java/org/eclipse/openk/core/controller/ServicesConfigCacheTimerTaskTest.java
new file mode 100644
index 0000000..e8f6557
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/controller/ServicesConfigCacheTimerTaskTest.java
@@ -0,0 +1,71 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.controller;
+
+import org.easymock.EasyMock;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import static org.easymock.EasyMock.*;
+
+public class ServicesConfigCacheTimerTaskTest {
+    private static ServicesConfigCache saveScc;
+
+    @BeforeClass
+    public static void SaveState() {
+        saveScc = Whitebox.getInternalState(ServicesConfigCache.class, "instance");
+
+    }
+
+    @AfterClass
+    public static void tearDown() {
+        Whitebox.setInternalState(ServicesConfigCache.class, "instance", saveScc);
+    }
+
+    @Test
+    public void testRun() throws Exception {
+        // ------------------ Prepare Test ----------------------
+        final String EXCEPTION_TEXT = "Exception";
+
+        // just to reach the sonar quality gate
+        Whitebox.invokeConstructor(InitServicesConfigCacheJob.class);
+
+        ServicesConfigCache scc = EasyMock.createMock(ServicesConfigCache.class);
+        scc.readServerDistribution(eq(EXCEPTION_TEXT));
+        expectLastCall().andThrow(new HttpStatusException(HttpStatus.INTERNAL_SERVER_ERROR_500)).anyTimes();
+
+        scc.readServerDistribution(not(eq(EXCEPTION_TEXT)));
+        expectLastCall().anyTimes();
+
+        replay( scc );
+
+        Whitebox.setInternalState(ServicesConfigCache.class, "instance", scc);
+
+
+        // ---------------------------- Test it ------------------------------------------
+        ServicesConfigCacheTimerTask task = new ServicesConfigCacheTimerTask(EXCEPTION_TEXT);
+
+        task.run();
+
+        // should run without problems
+        ServicesConfigCacheTimerTask task2 = new ServicesConfigCacheTimerTask("No Error");
+        task2.run();
+
+        tearDown();
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/core/exceptions/HttpStatusExceptionTest.java b/src/test/java/org/eclipse/openk/core/exceptions/HttpStatusExceptionTest.java
new file mode 100644
index 0000000..7ffc901
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/core/exceptions/HttpStatusExceptionTest.java
@@ -0,0 +1,27 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.core.exceptions;
+
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class HttpStatusExceptionTest {
+    @Test
+    public void testAll() {
+        HttpStatusException hse = new HttpStatusException( 200 );
+        assertEquals(HttpStatus.OK_200, hse.getHttpStatus());
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/health/ConfigFilePresentHealthCheckTest.java b/src/test/java/org/eclipse/openk/health/ConfigFilePresentHealthCheckTest.java
new file mode 100644
index 0000000..0ebe951
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/health/ConfigFilePresentHealthCheckTest.java
@@ -0,0 +1,54 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.health;
+
+import com.codahale.metrics.health.HealthCheck;
+import org.eclipse.openk.api.ServiceDistributionCluster;
+import org.eclipse.openk.core.controller.ServicesConfigCache;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import static junit.framework.TestCase.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ConfigFilePresentHealthCheckTest {
+    private boolean isHealthy(ConfigFilePresentHealthCheck hc) throws Exception {
+        HealthCheck.Result r = Whitebox.invokeMethod(hc, "check");
+        return r.isHealthy();
+    }
+
+    @Test
+    public void testConfigFilePresent_False() throws Exception {
+        ServicesConfigCache scc = ServicesConfigCache.getInstance();
+        ServiceDistributionCluster[] oldCache = scc.getCache();
+
+        try {
+            ConfigFilePresentHealthCheck hc = new ConfigFilePresentHealthCheck();
+
+            // test with invalid cluster
+            Whitebox.setInternalState(scc, "cache", (Object) null);
+            assertFalse(isHealthy(hc));
+
+            // test with invalid cluster
+            Whitebox.setInternalState(scc, "cache", new ServiceDistributionCluster[0]);
+            assertFalse(isHealthy(hc));
+
+            ServiceDistributionCluster[] arr = new ServiceDistributionCluster[1];
+            arr[0] = new ServiceDistributionCluster();
+            Whitebox.setInternalState(scc, "cache", arr);
+            assertTrue(isHealthy(hc));
+        } finally {
+            Whitebox.setInternalState(scc, "cache", oldCache);
+        }
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/resources/MicsCentralResourceTest.java b/src/test/java/org/eclipse/openk/resources/MicsCentralResourceTest.java
new file mode 100644
index 0000000..4597aef
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/resources/MicsCentralResourceTest.java
@@ -0,0 +1,39 @@
+/**
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+package org.eclipse.openk.resources;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.openk.core.controller.ServicesConfigCache;
+import org.eclipse.openk.core.exceptions.HttpStatusException;
+import org.junit.Test;
+
+import javax.ws.rs.core.Response;
+
+import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertEquals;
+
+public class MicsCentralResourceTest {
+    @Test
+    public void testGetVersionInfo() {
+        Response r = new MicsCentralResource().getVersionInfo();
+        assertNotNull( r );
+    }
+
+    @Test
+    public void testGetServiceDistribution() throws HttpStatusException {
+        ServicesConfigCache.getInstance().readServerDistribution("servicesDistributionDevLocal.json");
+        Response r = new MicsCentralResource().getServiceDistribution("elogbook.openk" );
+
+        assertEquals(HttpStatus.OK_200, r.getStatus());
+    }
+}
diff --git a/src/test/resources/serviceRequestEnvelope.json b/src/test/resources/serviceRequestEnvelope.json
new file mode 100644
index 0000000..9722f58
--- /dev/null
+++ b/src/test/resources/serviceRequestEnvelope.json
@@ -0,0 +1,17 @@
+{
+  "serviceName": "auth-n-auth.mics",
+  "isHttps": false,
+  "method": "GET",
+  "uriFragment": "versionInfo",
+  "payload": "eyAiYmFja2VuZFZlcnNpb24iOiAiMC4xLjMtU05BUFNIT1QifQ==",
+  "headers": [
+    {
+      "attribute": "Content-Type",
+      "value": "application/json"
+    },
+    {
+      "attribute": "accept",
+      "value": "application/json"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/servicesDistributionTest.json b/src/test/resources/servicesDistributionTest.json
new file mode 100644
index 0000000..f91ddc5
--- /dev/null
+++ b/src/test/resources/servicesDistributionTest.json
@@ -0,0 +1,20 @@
+[
+  {
+    "active": "true",
+    "clustername": "elogbook.openK",
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/authNAuth",
+        "healthUrlPath": "/portal/rest/beservice",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/src/test/resources/testServiceDist_False.json b/src/test/resources/testServiceDist_False.json
new file mode 100644
index 0000000..bf87303
--- /dev/null
+++ b/src/test/resources/testServiceDist_False.json
@@ -0,0 +1,19 @@
+[
+  {
+    "active": "true",
+
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/authNAuth",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/src/test/resources/testServiceDistributions.json b/src/test/resources/testServiceDistributions.json
new file mode 100644
index 0000000..0563fc1
--- /dev/null
+++ b/src/test/resources/testServiceDistributions.json
@@ -0,0 +1,31 @@
+[
+  {
+  "active": "true",
+  "clustername": "elogbook.openK",
+  "description": "elogbook service cluster for openKonsequenz",
+  "distributions": [
+      {
+      "active": "true",
+      "name": "auth-n-auth.mics",
+      "protocol": "http",
+      "host": "172.18.22.160",
+        "urlPath": "/authNAuth",
+        "healthUrlPath": "/portal/rest/beservice",
+      "portApp": "9002",
+      "portHealth": "9003",
+      "description": "Authentication Service"
+      },
+    {
+      "active": "true",
+      "name": "homie",
+      "protocol": "http",
+      "host": "172.18.22.160",
+      "urlPath": "/homie",
+      "healthUrlPath": "/portal/rest/beservice",
+      "portApp": "8080",
+      "portHealth": "8080",
+      "description": "Authentication Service"
+    }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/src/test/resources/testServiceDistributionsTwo_OneIsInactive.json b/src/test/resources/testServiceDistributionsTwo_OneIsInactive.json
new file mode 100644
index 0000000..0343c6c
--- /dev/null
+++ b/src/test/resources/testServiceDistributionsTwo_OneIsInactive.json
@@ -0,0 +1,57 @@
+[
+  {
+    "active": "false",
+    "clustername": "elogbook.openK",
+    "description": "elogbook service cluster for openKonsequenz",
+    "distributions": [
+      {
+        "active": "true",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/authNAuth",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      },
+      {
+        "active": "false",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/central",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      }
+    ]
+  },
+  {
+  "active": "true",
+  "clustername": "elogbook.openK",
+  "description": "elogbook service cluster for openKonsequenz",
+  "distributions": [
+      {
+        "active": "true",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "172.18.22.160",
+        "urlPath": "/authNAuth",
+        "healthUrlPath": "/portal/rest/beservice",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      },
+      {
+        "active": "false",
+        "name": "auth-n-auth.mics",
+        "protocol": "http",
+        "host": "localhost",
+        "urlPath": "/mics/central",
+        "portApp": "9002",
+        "portHealth": "9003",
+        "description": "Authentication Service"
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/templates/markdown.hbs b/templates/markdown.hbs
new file mode 100644
index 0000000..2a7e5cf
--- /dev/null
+++ b/templates/markdown.hbs
@@ -0,0 +1,107 @@
+#{{#info}}{{title}}
+
+
+## {{join schemes " | "}}://{{host}}{{basePath}}
+
+
+{{description}}
+
+{{#contact}}
+[**Contact the developer**](mailto:{{email}})
+{{/contact}}
+
+**Version** {{version}}
+
+[**Terms of Service**]({{termsOfService}})
+
+{{#license}}[**{{name}}**]({{url}}){{/license}}
+
+{{/info}}
+
+{{#if consumes}}**Consumes:** {{join consumes ", "}}{{/if}}
+
+{{#if produces}}**Produces:** {{join produces ", "}}{{/if}}
+
+{{#if securityDefinitions}}
+# Security Definitions
+{{/if}}
+{{> security}}
+
+# APIs
+
+{{#each paths}}
+## {{@key}}
+{{#this}}
+{{#get}}
+### GET
+{{> operation}}
+{{/get}}
+
+{{#put}}
+### PUT
+{{> operation}}
+{{/put}}
+
+{{#post}}
+### POST
+
+{{> operation}}
+
+{{/post}}
+
+{{#delete}}
+### DELETE
+{{> operation}}
+{{/delete}}
+
+{{#option}}
+### OPTION
+{{> operation}}
+{{/option}}
+
+{{#patch}}
+### PATCH
+{{> operation}}
+{{/patch}}
+
+{{#head}}
+### HEAD
+{{> operation}}
+{{/head}}
+
+{{/this}}
+{{/each}}
+
+# Definitions
+{{#each definitions}}
+## <a name="/definitions/{{key}}">{{@key}}</a>
+
+<table border="1">
+    <tr>
+        <th>name</th>
+        <th>type</th>
+        <th>required</th>
+        <th>description</th>
+        <th>example</th>
+    </tr>
+    {{#each this.properties}}
+    <tr>
+        <td>{{@key}}</td>
+        <td>
+            {{#ifeq type "array"}}
+            {{#items.$ref}}
+            {{type}}[<a href="{{items.$ref}}">{{basename items.$ref}}</a>]
+            {{/items.$ref}}
+            {{^items.$ref}}{{type}}[{{items.type}}]{{/items.$ref}}
+            {{else}}
+            {{#$ref}}<a href="{{$ref}}">{{basename $ref}}</a>{{/$ref}}
+            {{^$ref}}{{type}}{{#format}} ({{format}}){{/format}}{{/$ref}}
+            {{/ifeq}}
+        </td>
+        <td>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
+        <td>{{#description}}{{{description}}}{{/description}}{{^description}}-{{/description}}</td>
+        <td>{{example}}</td>
+    </tr>
+    {{/each}}
+</table>
+{{/each}}
\ No newline at end of file
diff --git a/templates/operation.hbs b/templates/operation.hbs
new file mode 100644
index 0000000..3ad3175
--- /dev/null
+++ b/templates/operation.hbs
@@ -0,0 +1,73 @@
+{{#deprecated}}-deprecated-{{/deprecated}}
+<a id="{{operationId}}">{{summary}}</a>
+
+{{description}}
+
+{{#if externalDocs.url}}{{externalDocs.description}}. [See external documents for more details]({{externalDocs.url}})
+{{/if}}
+
+{{#if security}}
+#### Security
+{{/if}}
+
+{{#security}}
+{{#each this}}
+* {{@key}}
+{{#this}}   * {{this}}
+{{/this}}
+{{/each}}
+{{/security}}
+
+#### Request
+
+{{#if consumes}}
+**Content-Type: ** {{join consumes ", "}}{{/if}}
+
+##### Parameters
+{{#if parameters}}
+<table border="1">
+    <tr>
+        <th>Name</th>
+        <th>Located in</th>
+        <th>Required</th>
+        <th>Description</th>
+        <th>Default</th>
+        <th>Schema</th>
+    </tr>
+    {{/if}}
+
+    {{#parameters}}
+    <tr>
+        <th>{{name}}</th>
+        <td>{{in}}</td>
+        <td>{{#if required}}yes{{else}}no{{/if}}</td>
+        <td>{{description}}{{#if pattern}} (**Pattern**: `{{pattern}}`){{/if}}</td>
+        <td> - </td>
+        {{#ifeq in "body"}}
+        <td>
+            {{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}}
+            {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a> {{/schema.$ref}}
+        </td>
+        {{else}}
+        {{#ifeq type "array"}}
+        <td>Array[{{items.type}}] ({{collectionFormat}})</td>
+        {{else}}
+        <td>{{type}} {{#format}}({{format}}){{/format}}</td>
+        {{/ifeq}}
+        {{/ifeq}}
+    </tr>
+    {{/parameters}}
+    {{#if parameters}}
+</table>
+{{/if}}
+
+
+#### Response
+
+{{#if produces}}**Content-Type: ** {{join produces ", "}}{{/if}}
+
+
+| Status Code | Reason      | Response Model |
+|-------------|-------------|----------------|
+{{#each responses}}| {{@key}}    | {{description}} | {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a>{{/schema.$ref}}{{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}}{{^schema}} - {{/schema}}|
+{{/each}}
\ No newline at end of file
diff --git a/templates/security.hbs b/templates/security.hbs
new file mode 100644
index 0000000..94badab
--- /dev/null
+++ b/templates/security.hbs
@@ -0,0 +1,88 @@
+{{#each securityDefinitions}}
+### {{@key}}
+{{#this}}
+{{#ifeq type "oauth2"}}
+<table>
+    <tr>
+        <th>type</th>
+        <th colspan="2">{{type}}</th>
+    </tr>
+    {{#if description}}
+    <tr>
+        <th>description</th>
+        <th colspan="2">{{description}}</th>
+    </tr>
+    {{/if}}
+    {{#if authorizationUrl}}
+    <tr>
+        <th>authorizationUrl</th>
+        <th colspan="2">{{authorizationUrl}}</th>
+    </tr>
+    {{/if}}
+    {{#if flow}}
+    <tr>
+        <th>flow</th>
+        <th colspan="2">{{flow}}</th>
+    </tr>
+    {{/if}}
+    {{#if tokenUrl}}
+    <tr>
+        <th>tokenUrl</th>
+        <th colspan="2">{{tokenUrl}}</th>
+    </tr>
+    {{/if}}
+    {{#if scopes}}
+    <tr>
+        <td rowspan="3">scopes</td>
+        {{#each scopes}}
+        <td>{{@key}}</td>
+        <td>{{this}}</td>
+    </tr>
+    <tr>
+        {{/each}}
+    </tr>
+    {{/if}}
+</table>
+{{/ifeq}}
+{{#ifeq type "apiKey"}}
+<table>
+    <tr>
+        <th>type</th>
+        <th colspan="2">{{type}}</th>
+    </tr>
+    {{#if description}}
+    <tr>
+        <th>description</th>
+        <th colspan="2">{{description}}</th>
+    </tr>
+    {{/if}}
+    {{#if name}}
+    <tr>
+        <th>name</th>
+        <th colspan="2">{{name}}</th>
+    </tr>
+    {{/if}}
+    {{#if in}}
+    <tr>
+        <th>in</th>
+        <th colspan="2">{{in}}</th>
+    </tr>
+    {{/if}}
+</table>
+{{/ifeq}}
+{{#ifeq type "basic"}}
+<table>
+    <tr>
+        <th>type</th>
+        <th colspan="2">{{type}}</th>
+    </tr>
+    {{#if description}}
+    <tr>
+        <th>description</th>
+        <th colspan="2">{{description}}</th>
+    </tr>
+    {{/if}}
+</table>
+{{/ifeq}}
+{{/this}}
+{{/each}}
\ No newline at end of file
diff --git a/templates/strapdown.html.hbs b/templates/strapdown.html.hbs
new file mode 100644
index 0000000..fd359ff
--- /dev/null
+++ b/templates/strapdown.html.hbs
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<title>API Document</title>
+
+<xmp theme="united" style="display:none;">
+    {{>markdown}}
+</xmp>
+
+<script src="http://strapdownjs.com/v/0.2/strapdown.js"></script>
+</html>
\ No newline at end of file