You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@edgent.apache.org by dj...@apache.org on 2016/03/10 19:29:06 UTC

[1/2] incubator-quarks git commit: QUARKS-10 Initial application service

Repository: incubator-quarks
Updated Branches:
  refs/heads/quarks-10 [created] d95a82300


QUARKS-10 Initial application service


Project: http://git-wip-us.apache.org/repos/asf/incubator-quarks/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-quarks/commit/1557098c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-quarks/tree/1557098c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-quarks/diff/1557098c

Branch: refs/heads/quarks-10
Commit: 1557098cc1aaf8bea6b7cd97f4b499bc7fccd02f
Parents: aaac8cb
Author: Dan Debrunner <dj...@apache.org>
Authored: Wed Mar 9 15:58:44 2016 -0800
Committer: Dan Debrunner <dj...@apache.org>
Committed: Wed Mar 9 16:04:46 2016 -0800

----------------------------------------------------------------------
 .../java/quarks/execution/mbeans/JobMXBean.java |  2 +-
 .../mbeans/ApplicationServiceMXBean.java        | 36 +++++++++
 .../topology/services/ApplicationService.java   | 60 ++++++++++++++
 build.xml                                       |  2 +
 runtime/.classpath                              |  1 +
 runtime/appservice/build.xml                    | 28 +++++++
 .../quarks/runtime/appservice/AppService.java   | 82 ++++++++++++++++++++
 .../runtime/appservice/AppServiceControl.java   | 61 +++++++++++++++
 test/.classpath                                 |  1 +
 test/fvtiot/build.xml                           | 27 +++++++
 .../java/quarks/test/fvt/iot/IotAppService.java | 27 +++++++
 11 files changed, 326 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/api/execution/src/main/java/quarks/execution/mbeans/JobMXBean.java
----------------------------------------------------------------------
diff --git a/api/execution/src/main/java/quarks/execution/mbeans/JobMXBean.java b/api/execution/src/main/java/quarks/execution/mbeans/JobMXBean.java
index cc98813..63795a6 100644
--- a/api/execution/src/main/java/quarks/execution/mbeans/JobMXBean.java
+++ b/api/execution/src/main/java/quarks/execution/mbeans/JobMXBean.java
@@ -12,7 +12,7 @@ public interface JobMXBean {
      * TYPE is used to identify this bean as a job bean when building the bean's {@code ObjectName}.
      * The value is {@value} 
      */
-    public static final String TYPE = "job";
+    String TYPE = "job";
 
     /**
      * Returns the identifier of the job.

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
----------------------------------------------------------------------
diff --git a/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java b/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
new file mode 100644
index 0000000..d09e3b8
--- /dev/null
+++ b/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
@@ -0,0 +1,36 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.topology.mbeans;
+
+import quarks.topology.services.ApplicationService;
+
+public interface ApplicationServiceMXBean {
+    
+    String TYPE = "appService";
+    
+    /**
+     * Submit an application registered with the application service.
+     * 
+     * @param applicationName Name of the application.
+     * @param jsonConfig JSON configuration serialized as a String.
+     * 
+     * @see ApplicationService
+     */
+    void submit(String applicationName, String jsonConfig);
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
----------------------------------------------------------------------
diff --git a/api/topology/src/main/java/quarks/topology/services/ApplicationService.java b/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
new file mode 100644
index 0000000..79dcb48
--- /dev/null
+++ b/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
@@ -0,0 +1,60 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.topology.services;
+
+import com.google.gson.JsonObject;
+
+import quarks.execution.Submitter;
+import quarks.function.BiConsumer;
+import quarks.topology.Topology;
+import quarks.topology.mbeans.ApplicationServiceMXBean;
+
+/**
+ * Application registration service.
+ *
+ * @see ApplicationServiceMXBean
+ */
+public interface ApplicationService {
+    
+    String ALIAS = "quarksApplication";
+    
+    /**
+     * Add a topology that can be started though a control mbean.
+     * <BR>
+     * When a {@link ApplicationServiceMXBean#submit(String, String) submit}
+     * is invoked {@code builder.accept(topology, config)} is called passing:
+     * <UL>
+     * <LI>
+     * {@code topology} - An empty topology with the name {@code applicationName}.
+     * </LI>
+     * <LI>
+     * {@code config} - JSON submission configuration from
+     * {@link ApplicationServiceMXBean#submit(String, String) submit}.
+     * </LI>
+     * </UL>
+     * Once {@code builder.accept(topology, config)} returns it is submitted
+     * to the {@link Submitter} associated with the implementation of this service.
+     * 
+     * @param applicationName Application name to register.
+     * @param builder How to build the topology for this application.
+     * 
+     * @see ApplicationServiceMXBean
+     */
+    void registerTopology(String applicationName, BiConsumer<Topology, JsonObject> builder);
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/build.xml
----------------------------------------------------------------------
diff --git a/build.xml b/build.xml
index 4ebb7d2..f311b40 100644
--- a/build.xml
+++ b/build.xml
@@ -90,6 +90,7 @@
         <ant dir="api/topology" target="@{target}" useNativeBasedir="true"/>
         <ant dir="spi/graph" target="@{target}" useNativeBasedir="true"/>
         <ant dir="spi/topology" target="@{target}" useNativeBasedir="true"/>
+        <ant dir="runtime/appservice" target="@{target}" useNativeBasedir="true"/>
         <ant dir="runtime/etiao" target="@{target}" useNativeBasedir="true"/>
         <ant dir="runtime/jmxcontrol" target="@{target}" useNativeBasedir="true"/>
         <ant dir="runtime/jsoncontrol" target="@{target}" useNativeBasedir="true"/>
@@ -124,6 +125,7 @@
         <ant dir="samples/console" target="@{target}" useNativeBasedir="true" />
         <ant dir="android/topology" target="@{target}" useNativeBasedir="true" />
         <ant dir="android/hardware" target="@{target}" useNativeBasedir="true" />
+        <ant dir="test/fvtiot" target="@{target}" useNativeBasedir="true" />
         <ant dir="test/svt" target="@{target}" useNativeBasedir="true" />
       </sequential>
   </macrodef>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/runtime/.classpath
----------------------------------------------------------------------
diff --git a/runtime/.classpath b/runtime/.classpath
index f05fc67..6f9b13e 100644
--- a/runtime/.classpath
+++ b/runtime/.classpath
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+	<classpathentry kind="src" path="appservice/src/main/java"/>
 	<classpathentry kind="src" path="etiao/src/main/java"/>
 	<classpathentry kind="src" path="etiao/src/test/java"/>
 	<classpathentry kind="src" path="jmxcontrol/src/main/java"/>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/runtime/appservice/build.xml
----------------------------------------------------------------------
diff --git a/runtime/appservice/build.xml b/runtime/appservice/build.xml
new file mode 100644
index 0000000..c6db1a5
--- /dev/null
+++ b/runtime/appservice/build.xml
@@ -0,0 +1,28 @@
+<project name="quarks.runtime.appservice" default="all" 
+    xmlns:jacoco="antlib:org.jacoco.ant"
+    >
+    <description>
+        Build the runtime Application service library.
+    </description>
+
+  <import file="../../common-build.xml"/>
+
+  <path id="compile.classpath">
+    <pathelement location="${lib}/quarks.api.execution.jar" />
+    <pathelement location="${lib}/quarks.api.topology.jar" />
+    <path refid="quarks.ext.classpath" />
+    <path refid="test.common.classpath"/>
+  </path>
+
+  <path id="test.compile.classpath">
+    <pathelement location="${jar}" />
+    <path refid="compile.classpath"/>
+  </path>
+
+  <path id="test.classpath">
+    <pathelement location="${test.classes}" />
+    <path refid="test.compile.classpath"/>
+  </path>
+
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
----------------------------------------------------------------------
diff --git a/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
new file mode 100644
index 0000000..b749850
--- /dev/null
+++ b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
@@ -0,0 +1,82 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.runtime.appservice;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gson.JsonObject;
+
+import quarks.execution.DirectSubmitter;
+import quarks.execution.services.ControlService;
+import quarks.function.BiConsumer;
+import quarks.topology.Topology;
+import quarks.topology.TopologyProvider;
+import quarks.topology.mbeans.ApplicationServiceMXBean;
+import quarks.topology.services.ApplicationService;
+
+public class AppService implements ApplicationService {
+    
+    public static ApplicationService createAndRegister(TopologyProvider provider, DirectSubmitter submitter) {
+        
+        AppService service = new AppService(provider, submitter, ALIAS);
+        
+        submitter.getServices().addService(ApplicationService.class, service);
+        
+        return service;
+        
+    }
+    
+    private final Map<String,BiConsumer<Topology, JsonObject>> applications =
+            Collections.synchronizedMap(new HashMap<>());
+    
+    private final TopologyProvider provider;
+    private final DirectSubmitter submitter;
+    
+    public AppService(TopologyProvider provider, DirectSubmitter submitter, String alias) {
+        this.provider = provider;
+        this.submitter = submitter;
+        
+        ControlService cs = submitter.getServices().getService(ControlService.class);
+        if (cs != null)
+            cs.registerControl(ApplicationServiceMXBean.TYPE,
+                    ALIAS+System.currentTimeMillis(), alias,
+                    ApplicationServiceMXBean.class,
+                    new AppServiceControl(this));
+    }
+
+    @Override
+    public void registerTopology(String applicationName, BiConsumer<Topology, JsonObject> builder) {
+        applications.put(applicationName, builder);
+    }
+    
+    BiConsumer<Topology, JsonObject> getBuilder(String applicationName) {
+        return applications.get(applicationName);
+    }
+    
+    TopologyProvider getProvider() {
+        return provider;
+    }
+    
+    
+    DirectSubmitter getSubmitter() {
+        return submitter;
+    }   
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
----------------------------------------------------------------------
diff --git a/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
new file mode 100644
index 0000000..26e688b
--- /dev/null
+++ b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
@@ -0,0 +1,61 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.runtime.appservice;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+import quarks.execution.Configs;
+import quarks.function.BiConsumer;
+import quarks.topology.Topology;
+import quarks.topology.mbeans.ApplicationServiceMXBean;
+
+public class AppServiceControl implements ApplicationServiceMXBean {
+    
+    private final AppService service;
+    
+    AppServiceControl(AppService service) {
+        this.service = service;
+    }
+
+    @Override
+    public void submit(String applicationName, String jsonConfig) {
+        
+        BiConsumer<Topology, JsonObject> builder = service.getBuilder(applicationName);
+        if (builder == null)
+            return;
+        
+        JsonObject config;
+        
+        if (jsonConfig != null)
+            config = (JsonObject) new JsonParser().parse(jsonConfig);
+        else
+            config = new JsonObject();
+        
+        Topology topology = service.getProvider().newTopology(applicationName);
+        
+        // Fill in the topology
+        builder.accept(topology, config);
+        
+        if (!config.has(Configs.JOB_NAME))
+            config.addProperty(Configs.JOB_NAME, applicationName);
+        
+        service.getSubmitter().submit(topology, config);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/test/.classpath
----------------------------------------------------------------------
diff --git a/test/.classpath b/test/.classpath
index 550db4d..efc056e 100644
--- a/test/.classpath
+++ b/test/.classpath
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
+	<classpathentry kind="src" path="fvtiot/src/main/java"/>
 	<classpathentry kind="src" path="svt/src/main/java"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/analytics"/>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/test/fvtiot/build.xml
----------------------------------------------------------------------
diff --git a/test/fvtiot/build.xml b/test/fvtiot/build.xml
new file mode 100644
index 0000000..a38ac29
--- /dev/null
+++ b/test/fvtiot/build.xml
@@ -0,0 +1,27 @@
+<project name="quarks.test.fvtiot" default="all" xmlns:jacoco="antlib:org.jacoco.ant">
+    <description>
+        FVT for iot scenario
+    </description>
+
+  <property name="component.path" value="test/fvtiot"/>
+  <import file="../../common-build.xml"/>
+
+  <path id="compile.classpath">
+    <pathelement location="${quarks.lib}/quarks.providers.direct.jar"/>
+    <pathelement location="${quarks.lib}/quarks.runtime.appservice.jar"/>
+    <pathelement location="${quarks.lib}/quarks.runtime.jsoncontrol.jar"/>
+    <path refid="quarks.ext.classpath"/>
+  </path>
+
+  <path id="test.compile.classpath">
+    <pathelement location="${jar}" />
+    <path refid="compile.classpath"/>
+  </path>
+
+  <path id="test.classpath">
+    <pathelement location="${test.classes}" />
+    <path refid="test.compile.classpath"/>
+    <path refid="test.common.classpath" />
+  </path>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/1557098c/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java
----------------------------------------------------------------------
diff --git a/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java b/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java
new file mode 100644
index 0000000..aeeb323
--- /dev/null
+++ b/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java
@@ -0,0 +1,27 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.test.fvt.iot;
+
+public class IotAppService {
+    
+    public void testAppService() {
+        
+    }
+    
+}


[2/2] incubator-quarks git commit: Add working application service and a simple test

Posted by dj...@apache.org.
Add working application service and a simple test


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

Branch: refs/heads/quarks-10
Commit: d95a82300e5179255ae12e877da6a6e9a8502880
Parents: 1557098
Author: Dan Debrunner <dj...@apache.org>
Authored: Thu Mar 10 10:20:22 2016 -0800
Committer: Dan Debrunner <dj...@apache.org>
Committed: Thu Mar 10 10:20:22 2016 -0800

----------------------------------------------------------------------
 .../src/main/java/quarks/execution/Configs.java |  4 +-
 .../mbeans/ApplicationServiceMXBean.java        |  3 +-
 .../quarks/topology/mbeans/package-info.java    | 82 ++++++++++++++++++++
 .../topology/services/ApplicationService.java   |  2 +-
 .../quarks/runtime/appservice/AppService.java   |  8 +-
 .../runtime/appservice/AppServiceControl.java   | 16 +++-
 .../runtime/jsoncontrol/JsonControlService.java | 10 ++-
 test/.classpath                                 |  4 +-
 .../java/quarks/test/fvt/iot/IotAppService.java | 27 -------
 .../java/quarks/test/fvt/iot/IotAppService.java | 70 +++++++++++++++++
 10 files changed, 187 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/api/execution/src/main/java/quarks/execution/Configs.java
----------------------------------------------------------------------
diff --git a/api/execution/src/main/java/quarks/execution/Configs.java b/api/execution/src/main/java/quarks/execution/Configs.java
index b46dbcd..d5546fb 100644
--- a/api/execution/src/main/java/quarks/execution/Configs.java
+++ b/api/execution/src/main/java/quarks/execution/Configs.java
@@ -17,7 +17,7 @@ package quarks.execution;
  *    <td align=center><b>Description</b></td>
  *  </tr>
  * <tr>
- *    <td>{@link #JOB_NAME}</td>
+ *    <td>{@link #JOB_NAME jobName}</td>
  *    <td>String</td>
  *    <td>The name of the job.</td>
  *  </tr>
@@ -30,5 +30,5 @@ public interface Configs {
      * containing the job name.
      * The value is {@value}.
      */
-    static final String JOB_NAME = "jobName";
+    String JOB_NAME = "jobName";
 }

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
----------------------------------------------------------------------
diff --git a/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java b/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
index d09e3b8..cf5d8c1 100644
--- a/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
+++ b/api/topology/src/main/java/quarks/topology/mbeans/ApplicationServiceMXBean.java
@@ -30,7 +30,8 @@ public interface ApplicationServiceMXBean {
      * @param applicationName Name of the application.
      * @param jsonConfig JSON configuration serialized as a String.
      * 
+     * @throws Exception Error submitting application.
      * @see ApplicationService
      */
-    void submit(String applicationName, String jsonConfig);
+    void submit(String applicationName, String jsonConfig) throws Exception;
 }

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/api/topology/src/main/java/quarks/topology/mbeans/package-info.java
----------------------------------------------------------------------
diff --git a/api/topology/src/main/java/quarks/topology/mbeans/package-info.java b/api/topology/src/main/java/quarks/topology/mbeans/package-info.java
new file mode 100644
index 0000000..2154587
--- /dev/null
+++ b/api/topology/src/main/java/quarks/topology/mbeans/package-info.java
@@ -0,0 +1,82 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+/**
+ * Controls for executing topologies.
+ * <h3>Application Service </h3>
+ * {@linkplain quarks.topology.services.ApplicationService Application service}
+ * allows an application to be registered
+ * so that it be be submitted remotely using a device command.
+ * 
+ * <BR>
+ * This service registers a control MBean
+ * {@link quarks.topology.mbeans.ApplicationServiceMXBean}
+ * to provide control of the service.
+ *  
+ * <h4>Submit an Application</h4>
+ * Method: {@link quarks.topology.mbeans.ApplicationServiceMXBean#submit(String, String)}
+ * <P>
+ * <table border=1 cellpadding=3 cellspacing=1>
+ * <caption>JSON Submit Application</caption>
+ * <tr>
+ *    <td align=center><b>Attribute name</b></td>
+ *    <td align=center><b>Type</b></td>
+ *    <td align=center><b>Value</b></td>
+ *    <td align=center><b>Description</b></td>
+ *  </tr>
+ * <tr>
+ *    <td>{@link quarks.runtime.jsoncontrol.JsonControlService#TYPE_KEY type}</td>
+ *    <td>String</td>
+ *    <td>{@link quarks.topology.mbeans.ApplicationServiceMXBean#TYPE appService}</td>
+ *    <td>{@code ApplicationServiceMXBean} control MBean type.</td>
+ *  </tr>
+ *  <tr>
+ *    <td>{@link quarks.runtime.jsoncontrol.JsonControlService#OP_KEY op}</td>
+ *    <td>String</td>
+ *    <td>{@code submit}</td>
+ *    <td>Invoke {@link quarks.topology.mbeans.ApplicationServiceMXBean#submit(String, String) submit} operation
+ *    against the control MBean.</td>
+ *  </tr>
+ *  <tr>
+ *    <td>{@link quarks.runtime.jsoncontrol.JsonControlService#ALIAS_KEY alias}</td>
+ *    <td>String</td>
+ *    <td>Alias of control MBean.</td>
+ *    <td>Default is {@link quarks.topology.services.ApplicationService#ALIAS quarksApplicationService}.</td>
+ *  </tr>
+ *  <tr>
+ *    <td rowspan="2">{@link quarks.runtime.jsoncontrol.JsonControlService#ARGS_KEY args}</td>
+ *    <td rowspan="2">List</td>
+ *    <td>String: application name</td>
+ *    <td>Registered application to submit.</td>
+ *  </tr>
+ *  <tr>
+ *    <td>JSON Object: submission configuration</td>
+ *    <td>Configuration for the submission,
+ *    see {@link quarks.execution.Submitter#submit(Object, com.google.gson.JsonObject) submit()}.
+ *    If {@code jobName} is not set in the configuration then the job is submitted with {@code jobName} set to the
+ *    application name.</td>
+ *  </tr>
+ * </table>
+ * <BR>
+ * Example submitting the application {@code EngineTemp} with no configuration, will result in a running
+ * job named {@code EngineTemp}.
+ * <BR>
+ * {@code {"type":"appService","alias":"quarksApplicationService","op":"submit","args":["EngineTemp",{}]}}
+ * </P>
+ */
+package quarks.topology.mbeans;

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
----------------------------------------------------------------------
diff --git a/api/topology/src/main/java/quarks/topology/services/ApplicationService.java b/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
index 79dcb48..c693c08 100644
--- a/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
+++ b/api/topology/src/main/java/quarks/topology/services/ApplicationService.java
@@ -32,7 +32,7 @@ import quarks.topology.mbeans.ApplicationServiceMXBean;
  */
 public interface ApplicationService {
     
-    String ALIAS = "quarksApplication";
+    String ALIAS = "quarksApplicationService";
     
     /**
      * Add a topology that can be started though a control mbean.

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
----------------------------------------------------------------------
diff --git a/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
index b749850..5d96998 100644
--- a/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
+++ b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppService.java
@@ -25,6 +25,7 @@ import java.util.Map;
 import com.google.gson.JsonObject;
 
 import quarks.execution.DirectSubmitter;
+import quarks.execution.Job;
 import quarks.execution.services.ControlService;
 import quarks.function.BiConsumer;
 import quarks.topology.Topology;
@@ -48,9 +49,10 @@ public class AppService implements ApplicationService {
             Collections.synchronizedMap(new HashMap<>());
     
     private final TopologyProvider provider;
-    private final DirectSubmitter submitter;
+    private final DirectSubmitter<Topology, Job> submitter;
     
-    public AppService(TopologyProvider provider, DirectSubmitter submitter, String alias) {
+    public AppService(TopologyProvider provider,
+            DirectSubmitter<Topology, Job> submitter, String alias) {
         this.provider = provider;
         this.submitter = submitter;
         
@@ -76,7 +78,7 @@ public class AppService implements ApplicationService {
     }
     
     
-    DirectSubmitter getSubmitter() {
+    DirectSubmitter<Topology, Job> getSubmitter() {
         return submitter;
     }   
 }

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
----------------------------------------------------------------------
diff --git a/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
index 26e688b..dbd0501 100644
--- a/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
+++ b/runtime/appservice/src/main/java/quarks/runtime/appservice/AppServiceControl.java
@@ -18,6 +18,8 @@ under the License.
 */
 package quarks.runtime.appservice;
 
+import java.util.concurrent.ExecutionException;
+
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 
@@ -35,7 +37,7 @@ public class AppServiceControl implements ApplicationServiceMXBean {
     }
 
     @Override
-    public void submit(String applicationName, String jsonConfig) {
+    public void submit(String applicationName, String jsonConfig) throws Exception {
         
         BiConsumer<Topology, JsonObject> builder = service.getBuilder(applicationName);
         if (builder == null)
@@ -56,6 +58,16 @@ public class AppServiceControl implements ApplicationServiceMXBean {
         if (!config.has(Configs.JOB_NAME))
             config.addProperty(Configs.JOB_NAME, applicationName);
         
-        service.getSubmitter().submit(topology, config);
+        try {
+            service.getSubmitter().submit(topology, config).get();
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (ExecutionException e) {
+            Throwable t = e.getCause();
+            if (t instanceof Error)
+                throw (Error) t;
+            throw (Exception) t;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/runtime/jsoncontrol/src/main/java/quarks/runtime/jsoncontrol/JsonControlService.java
----------------------------------------------------------------------
diff --git a/runtime/jsoncontrol/src/main/java/quarks/runtime/jsoncontrol/JsonControlService.java b/runtime/jsoncontrol/src/main/java/quarks/runtime/jsoncontrol/JsonControlService.java
index 4178723..8dfae06 100644
--- a/runtime/jsoncontrol/src/main/java/quarks/runtime/jsoncontrol/JsonControlService.java
+++ b/runtime/jsoncontrol/src/main/java/quarks/runtime/jsoncontrol/JsonControlService.java
@@ -11,6 +11,7 @@ import java.lang.reflect.Parameter;
 import java.util.HashMap;
 import java.util.Map;
 
+import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonNull;
@@ -57,6 +58,7 @@ public class JsonControlService implements ControlService {
      */
     public static final String ARGS_KEY = "args";
 
+    private final Gson gson = new Gson();
     private final Map<String, ControlMBean<?>> mbeans = new HashMap<>();
 
     private static String getControlId(String type, String id, String alias) {
@@ -177,8 +179,12 @@ public class JsonControlService implements ControlService {
             final JsonElement arg = args.get(i);
             Object jarg;
             
-            if (String.class == pt.getType())
-                jarg = arg.getAsString();
+            if (String.class == pt.getType()) {
+                if (arg instanceof JsonObject)
+                    jarg = gson.toJson(arg);
+                else
+                    jarg = arg.getAsString();
+            }
             else if (Integer.TYPE == pt.getType())
                 jarg = arg.getAsInt();
             else if (Long.TYPE == pt.getType())

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/test/.classpath
----------------------------------------------------------------------
diff --git a/test/.classpath b/test/.classpath
index efc056e..0b81af1 100644
--- a/test/.classpath
+++ b/test/.classpath
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-	<classpathentry kind="src" path="fvtiot/src/main/java"/>
+	<classpathentry kind="src" path="fvtiot/src/test/java"/>
 	<classpathentry kind="src" path="svt/src/main/java"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/analytics"/>
@@ -12,5 +12,7 @@
 	<classpathentry combineaccessrules="false" kind="src" path="/spi"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/utils"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/apps"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/runtime"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java
----------------------------------------------------------------------
diff --git a/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java b/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java
deleted file mode 100644
index aeeb323..0000000
--- a/test/fvtiot/src/main/java/quarks/test/fvt/iot/IotAppService.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
-*/
-package quarks.test.fvt.iot;
-
-public class IotAppService {
-    
-    public void testAppService() {
-        
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/incubator-quarks/blob/d95a8230/test/fvtiot/src/test/java/quarks/test/fvt/iot/IotAppService.java
----------------------------------------------------------------------
diff --git a/test/fvtiot/src/test/java/quarks/test/fvt/iot/IotAppService.java b/test/fvtiot/src/test/java/quarks/test/fvt/iot/IotAppService.java
new file mode 100644
index 0000000..8b8c14e
--- /dev/null
+++ b/test/fvtiot/src/test/java/quarks/test/fvt/iot/IotAppService.java
@@ -0,0 +1,70 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+package quarks.test.fvt.iot;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+
+import quarks.execution.services.ControlService;
+import quarks.providers.direct.DirectProvider;
+import quarks.runtime.appservice.AppService;
+import quarks.runtime.jsoncontrol.JsonControlService;
+import quarks.topology.Topology;
+import quarks.topology.mbeans.ApplicationServiceMXBean;
+import quarks.topology.services.ApplicationService;
+
+public class IotAppService {
+    
+    @Test
+    public void testAppService() throws Exception {
+        
+        DirectProvider provider = new DirectProvider();
+        
+        JsonControlService control = new JsonControlService();
+        provider.getServices().addService(ControlService.class, control);
+        
+        ApplicationService apps = AppService.createAndRegister(provider, provider);
+        
+        apps.registerTopology("AppOne", IotAppService::createApplicationOne);
+        
+
+        JsonObject submitAppOne = new JsonObject();   
+        submitAppOne.addProperty(JsonControlService.TYPE_KEY, ApplicationServiceMXBean.TYPE);
+        submitAppOne.addProperty(JsonControlService.ALIAS_KEY, ApplicationService.ALIAS);
+        JsonArray args = new JsonArray();
+        args.add(new JsonPrimitive("AppOne"));
+        args.add(new JsonObject());
+        submitAppOne.addProperty(JsonControlService.OP_KEY, "submit");
+        submitAppOne.add(JsonControlService.ARGS_KEY, args);
+        
+        JsonElement crr = control.controlRequest(submitAppOne);
+        
+        assertTrue(crr.getAsBoolean());
+    }
+    
+    public static void createApplicationOne(Topology topology, JsonObject config) {
+        topology.strings("A", "B", "C").print();
+    }
+}