You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by gb...@apache.org on 2015/08/23 22:30:41 UTC

helix git commit: Adds a Maven archetype to create OnlineOffline application

Repository: helix
Updated Branches:
  refs/heads/master 0cf986e17 -> 525a7723e


Adds a Maven archetype to create OnlineOffline application


Project: http://git-wip-us.apache.org/repos/asf/helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/helix/commit/525a7723
Tree: http://git-wip-us.apache.org/repos/asf/helix/tree/525a7723
Diff: http://git-wip-us.apache.org/repos/asf/helix/diff/525a7723

Branch: refs/heads/master
Commit: 525a7723eea2777ccabf0d530bdb691fdf349d40
Parents: 0cf986e
Author: Greg Brandt <br...@gmail.com>
Authored: Sun Aug 23 13:15:14 2015 -0700
Committer: Greg Brandt <br...@gmail.com>
Committed: Sun Aug 23 13:21:47 2015 -0700

----------------------------------------------------------------------
 helix-archetype/.gitignore                      |   9 ++
 helix-archetype/README.md                       |  95 ++++++++++++++++
 helix-archetype/pom.xml                         |  73 ++++++++++++
 .../META-INF/maven/archetype-metadata.xml       |  42 +++++++
 .../main/resources/archetype-resources/pom.xml  |  93 ++++++++++++++++
 .../src/main/java/__name__Main.java             |  66 +++++++++++
 .../java/participant/__name__Participant.java   | 110 +++++++++++++++++++
 .../__name__StateTransitionHandler.java         |  45 ++++++++
 .../__name__StateTransitionHandlerFactory.java  |  31 ++++++
 .../main/java/spectator/__name__Spectator.java  |  65 +++++++++++
 .../src/main/resources/log4j.xml                |  36 ++++++
 helix-archetype/src/test/conf/testng.xml        |  42 +++++++
 pom.xml                                         |   1 +
 13 files changed, 708 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/.gitignore
----------------------------------------------------------------------
diff --git a/helix-archetype/.gitignore b/helix-archetype/.gitignore
new file mode 100644
index 0000000..4f032a1
--- /dev/null
+++ b/helix-archetype/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+*.ipr
+*.iws
+
+target
+
+dependency-reduced-pom.xml
+
+.idea

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/README.md
----------------------------------------------------------------------
diff --git a/helix-archetype/README.md b/helix-archetype/README.md
new file mode 100644
index 0000000..86b6bad
--- /dev/null
+++ b/helix-archetype/README.md
@@ -0,0 +1,95 @@
+<!--
+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.
+-->
+
+helix-archetype
+===============
+
+A maven archetype that sets up a sample [Apache Helix](http://helix.apache.org/) project.
+
+Generate
+--------
+
+First, clone this repository and install the archetype
+
+```
+git clone git@github.com:brandtg/helix-archetype.git
+cd helix-archetype
+mvn install
+```
+
+Then generate your application
+
+```
+mvn archetype:generate \
+  -DarchetypeGroupId=org.apache.helix \
+  -DarchetypeArtifactId=helix-archetype \
+  -DarchetypeVersion=1.0-SNAPSHOT \
+  -DgroupId=com.example \
+  -DartifactId=my-app \
+  -Dname=MyApp \
+  -DinteractiveMode=false
+```
+
+This creates a simple OnlineOffline application, though it should be straightforward to change the state model by referencing the Helix documentation.
+
+The `pom.xml` creates a single versioned artifact, which can run all of your cluster's roles via the `${name}Main` entry point.
+
+This makes it a little nicer to manage multiple different cluster roles: just build this artifact, and deploy it everywhere with different CLI args.
+
+Example
+-------
+
+To get started, build the artifact after generating your application:
+
+```
+cd my-app
+mvn install
+```
+
+Run a ZooKeeper
+
+```
+java -jar target/my-app-1.0-SNAPSHOT.jar zookeeper 2191 /tmp/zk
+```
+
+Set up a cluster, then add a node and a resource with 4 partitions
+
+```
+java -jar target/my-app-1.0-SNAPSHOT.jar setup --zkSvr localhost:2191 --addCluster TEST_CLUSTER
+java -jar target/my-app-1.0-SNAPSHOT.jar setup --zkSvr localhost:2191 --addNode TEST_CLUSTER node0
+java -jar target/my-app-1.0-SNAPSHOT.jar setup --zkSvr localhost:2191 --addResource TEST_CLUSTER test 4 OnlineOffline
+```
+
+Run a controller
+
+```
+java -jar target/my-app-1.0-SNAPSHOT.jar controller --zkSvr localhost:2191 --cluster TEST_CLUSTER
+```
+
+Run a participant (note: does nothing)
+
+```
+java -jar target/my-app-1.0-SNAPSHOT.jar participant localhost:2181 TEST_CLUSTER node0
+```
+
+Rebalance the resource (should work...)
+
+```
+java -jar target/my-app-1.0-SNAPSHOT.jar setup  --zkSvr localhost:2191 --rebalance TEST_CLUSTER test 1
+```

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/pom.xml
----------------------------------------------------------------------
diff --git a/helix-archetype/pom.xml b/helix-archetype/pom.xml
new file mode 100644
index 0000000..d0b30ac
--- /dev/null
+++ b/helix-archetype/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.apache.helix</groupId>
+    <artifactId>helix</artifactId>
+    <version>0.7.2-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>helix-archetype</artifactId>
+  <packaging>jar</packaging>
+
+  <name>Apache Helix :: Archetype</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.testng</groupId>
+      <artifactId>testng</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+        <includes>
+          <include>archetype-resources/pom.xml</include>
+        </includes>
+      </resource>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>false</filtering>
+        <excludes>
+          <exclude>archetype-resources/pom.xml</exclude>
+        </excludes>
+      </resource>
+    </resources>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-resources-plugin</artifactId>
+          <version>2.5</version>
+          <configuration>
+            <escapeString>\</escapeString>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/helix-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
new file mode 100644
index 0000000..d60c037
--- /dev/null
+++ b/helix-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy 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.
+-->
+<archetype-descriptor xmlns="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                      xsi:schemaLocation="http://maven.apache.org/plugins/maven-archetype-plugin/archetype-descriptor/1.0.0 http://maven.apache.org/xsd/archetype-descriptor-1.0.0.xsd"
+                      name="helix-archetype">
+  <requiredProperties>
+    <requiredProperty key="name"/>
+  </requiredProperties>
+
+  <fileSets>
+    <fileSet filtered="true">
+      <directory>src/main/java</directory>
+      <includes>
+        <include>**/*</include>
+      </includes>
+    </fileSet>
+
+    <fileSet filtered="true">
+      <directory>src/main/resources</directory>
+      <includes>
+        <include>**/*</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</archetype-descriptor>

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/pom.xml
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/pom.xml b/helix-archetype/src/main/resources/archetype-resources/pom.xml
new file mode 100644
index 0000000..a1df913
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/pom.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+ 
+  <groupId>\${groupId}</groupId>
+  <artifactId>\${artifactId}</artifactId>
+  <version>\${version}</version>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.helix</groupId>
+      <artifactId>helix-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.12</version>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-log4j12</artifactId>
+      <version>1.7.12</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <forceCreation>true</forceCreation>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-shade-plugin</artifactId>
+        <version>2.3</version>
+        <configuration>
+          <createDependencyReducedPom>true</createDependencyReducedPom>
+          <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>
+            <configuration>
+              <transformers>
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
+                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                  <mainClass>\${package}.\${name}Main</mainClass>
+                </transformer>
+              </transformers>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/src/main/java/__name__Main.java
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/src/main/java/__name__Main.java b/helix-archetype/src/main/resources/archetype-resources/src/main/java/__name__Main.java
new file mode 100644
index 0000000..7836ebd
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/src/main/java/__name__Main.java
@@ -0,0 +1,66 @@
+package ${package};
+
+/*
+ * 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.
+ */
+
+import ${package}.participant.${name}Participant;
+import org.apache.helix.controller.HelixControllerMain;
+import org.apache.helix.tools.ClusterSetup;
+import org.apache.zookeeper.server.ZooKeeperServerMain;
+
+import java.util.Arrays;
+
+/**
+ * An executable to start the various cluster roles.
+ */
+public class ${name}Main {
+  private enum Mode {
+    PARTICIPANT,
+    CONTROLLER,
+    ZOOKEEPER,
+    SETUP
+  }
+
+  public static void main(String[] args) throws Exception {
+    if (args.length == 0) {
+      System.err.println("usage: <mode> args...");
+      System.exit(1);
+    }
+
+    Mode mode = Mode.valueOf(args[0].toUpperCase());
+    String[] subArgs = Arrays.copyOfRange(args, 1, args.length);
+
+    switch (mode) {
+      case PARTICIPANT:
+        ${name}Participant.main(subArgs);
+        break;
+      case CONTROLLER:
+        HelixControllerMain.main(subArgs);
+        break;
+      case ZOOKEEPER:
+        ZooKeeperServerMain.main(subArgs);
+        break;
+      case SETUP:
+        ClusterSetup.main(subArgs);
+        break;
+      default:
+        throw new IllegalStateException("Unsupported mode " + mode);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__Participant.java
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__Participant.java b/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__Participant.java
new file mode 100644
index 0000000..542c471
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__Participant.java
@@ -0,0 +1,110 @@
+package ${package}.participant;
+
+/*
+ * 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.
+ */
+
+import org.apache.helix.HelixConnection;
+import org.apache.helix.HelixParticipant;
+import org.apache.helix.api.id.ClusterId;
+import org.apache.helix.api.id.ParticipantId;
+import org.apache.helix.api.id.StateModelDefId;
+import org.apache.helix.manager.zk.ZkHelixConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.CountDownLatch;
+
+public class ${name}Participant {
+  private static final Logger LOG = LoggerFactory.getLogger(${name}Participant.class);
+
+  private final String zkConnectString;
+  private final ClusterId clusterId;
+  private final ParticipantId participantId;
+
+  private HelixConnection connection;
+  private HelixParticipant participant;
+
+  /**
+   * A Participant in the cluster.
+   *
+   * <p>
+   *   http://helix.apache.org/0.7.1-docs/tutorial_participant.html
+   * </p>
+   *
+   * @param zkConnectString
+   *  The ZooKeeper cluster for Helix.
+   * @param clusterId
+   *  The cluster name.
+   * @param participantId
+   *  This participant id.
+   */
+  public ${name}Participant(String zkConnectString, ClusterId clusterId, ParticipantId participantId) {
+    this.zkConnectString = zkConnectString;
+    this.clusterId = clusterId;
+    this.participantId = participantId;
+  }
+
+  public void start() {
+    LOG.info("Connecting to {}", zkConnectString);
+    connection = new ZkHelixConnection(zkConnectString);
+    connection.connect();
+
+    participant = connection.createParticipant(clusterId, participantId);
+    participant.getStateMachineEngine().registerStateModelFactory(
+        StateModelDefId.OnlineOffline, new ${name}StateTransitionHandlerFactory());
+
+    LOG.info("Starting participant {} :: {}", clusterId, participantId);
+    participant.start();
+  }
+
+  public void stop() {
+    LOG.info("Stopping participant {} :: {}", clusterId, participantId);
+    participant.stop();
+
+    LOG.info("Disconnecting from cluster {}", zkConnectString);
+    connection.disconnect();
+  }
+
+  public static void main(String[] args) throws Exception {
+    if (args.length != 3) {
+      System.err.println("usage: zkConnectString clusterId participantId");
+      System.exit(1);
+    }
+
+    // Parse args
+    String zkConnectString = args[0];
+    ClusterId clusterId = ClusterId.from(args[1]);
+    ParticipantId participantId = ParticipantId.from(args[2]);
+
+    final ${name}Participant participant = new ${name}Participant(zkConnectString, clusterId, participantId);
+
+    Runtime.getRuntime().addShutdownHook(new Thread() {
+      @Override
+      public void run() {
+        participant.stop();
+      }
+    });
+
+    participant.start();
+
+    // Block
+    final CountDownLatch latch = new CountDownLatch(1);
+    latch.await();
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandler.java
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandler.java b/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandler.java
new file mode 100644
index 0000000..dd2dea9
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandler.java
@@ -0,0 +1,45 @@
+package ${package}.participant;
+
+/*
+ * 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.
+ */
+
+import org.apache.helix.NotificationContext;
+import org.apache.helix.api.TransitionHandler;
+import org.apache.helix.model.Message;
+import org.apache.helix.participant.statemachine.StateModelInfo;
+import org.apache.helix.participant.statemachine.Transition;
+
+@StateModelInfo(states = "{'OFFLINE','ONLINE'}", initialState = "OFFLINE")
+public class ${name}StateTransitionHandler extends TransitionHandler {
+  @Transition(from = "OFFLINE", to = "ONLINE")
+  public void onBecomeOnlineFromOffline(Message message, NotificationContext context) {
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    // Application logic to handle transition                                                     //
+    // For example, you might start a service, run initialization, etc                            //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+  }
+
+  @Transition(from = "ONLINE", to = "OFFLINE")
+  public void onBecomeOfflineFromOnline(Message message, NotificationContext context) {
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+    // Application logic to handle transition                                                     //
+    // For example, you might shutdown a service, log this event, or change monitoring settings   //
+    ////////////////////////////////////////////////////////////////////////////////////////////////
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandlerFactory.java
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandlerFactory.java b/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandlerFactory.java
new file mode 100644
index 0000000..54a51fe
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/src/main/java/participant/__name__StateTransitionHandlerFactory.java
@@ -0,0 +1,31 @@
+package ${package}.participant;
+
+/*
+ * 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.
+ */
+
+import org.apache.helix.api.StateTransitionHandlerFactory;
+import org.apache.helix.api.id.PartitionId;
+import org.apache.helix.api.id.ResourceId;
+
+public class ${name}StateTransitionHandlerFactory extends StateTransitionHandlerFactory<${name}StateTransitionHandler> {
+  @Override
+  public ${name}StateTransitionHandler createStateTransitionHandler(ResourceId resourceId, PartitionId partitionId) {
+    return new ${name}StateTransitionHandler();
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/src/main/java/spectator/__name__Spectator.java
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/src/main/java/spectator/__name__Spectator.java b/helix-archetype/src/main/resources/archetype-resources/src/main/java/spectator/__name__Spectator.java
new file mode 100644
index 0000000..86ce355
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/src/main/java/spectator/__name__Spectator.java
@@ -0,0 +1,65 @@
+package ${package}.spectator;
+
+/*
+ * 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.
+ */
+
+import org.apache.helix.HelixManager;
+import org.apache.helix.HelixManagerFactory;
+import org.apache.helix.InstanceType;
+import org.apache.helix.api.id.ClusterId;
+import org.apache.helix.api.id.ParticipantId;
+import org.apache.helix.spectator.RoutingTableProvider;
+
+public class ${name}Spectator {
+  private final String zkConnectString;
+  private final ClusterId clusterId;
+  private final ParticipantId participantId;
+
+  private HelixManager manager;
+  private RoutingTableProvider routingTableProvider;
+
+  public ${name}Spectator(String zkConnectString, ClusterId clusterId, ParticipantId participantId) {
+    this.zkConnectString = zkConnectString;
+    this.clusterId = clusterId;
+    this.participantId = participantId;
+  }
+
+  public void start() {
+    try {
+      manager = HelixManagerFactory.getZKHelixManager(
+          clusterId.stringify(),
+          participantId.stringify(),
+          InstanceType.SPECTATOR,
+          zkConnectString);
+      manager.connect();
+      routingTableProvider = new RoutingTableProvider();
+      manager.addExternalViewChangeListener(routingTableProvider);
+    } catch (Exception e) {
+      throw new IllegalStateException(e);
+    }
+  }
+
+  public void stop() {
+    manager.disconnect();
+  }
+
+  public RoutingTableProvider getRoutingTableProvider() {
+    return routingTableProvider;
+  }
+}

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/main/resources/archetype-resources/src/main/resources/log4j.xml
----------------------------------------------------------------------
diff --git a/helix-archetype/src/main/resources/archetype-resources/src/main/resources/log4j.xml b/helix-archetype/src/main/resources/archetype-resources/src/main/resources/log4j.xml
new file mode 100644
index 0000000..94ee9b9
--- /dev/null
+++ b/helix-archetype/src/main/resources/archetype-resources/src/main/resources/log4j.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy 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.
+-->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration debug="true"
+                     xmlns:log4j='http://jakarta.apache.org/log4j/'>
+
+    <appender name="console" class="org.apache.log4j.ConsoleAppender">
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern"
+                   value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
+        </layout>
+    </appender>
+
+    <root>
+        <level value="INFO" />
+        <appender-ref ref="console" />
+    </root>
+
+</log4j:configuration>

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/helix-archetype/src/test/conf/testng.xml
----------------------------------------------------------------------
diff --git a/helix-archetype/src/test/conf/testng.xml b/helix-archetype/src/test/conf/testng.xml
new file mode 100644
index 0000000..70045c9
--- /dev/null
+++ b/helix-archetype/src/test/conf/testng.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy 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.
+-->
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<suite name="Suite" parallel="none">
+  <test name="Test" preserve-order="true">
+    <packages>
+    	<package name="org.apache.helix.*"/>
+    <!--
+      <package name="org.apache.helix.messaging.handling"/>
+      <package name="org.apache.helix.agent.file"/>
+      <package name="org.apache.helix.monitoring"/>
+      <package name="org.apache.helix.store.zk"/>
+      <package name="org.apache.helix.messaging"/>
+      <package name="org.apache.helix.controller.stages"/>
+      <package name="org.apache.helix.store.file"/>
+      <package name="org.apache.helix.store"/>
+      <package name="org.apache.helix.monitoring.mbeans"/>
+      <package name="org.apache.helix.participant"/>
+      <package name="org.apache.helix"/>
+      <package name="org.apache.helix.agent.zk"/>
+      <package name="org.apache.helix.integration"/>
+      -->
+    </packages>
+  </test>
+</suite>	

http://git-wip-us.apache.org/repos/asf/helix/blob/525a7723/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 4faf806..9c77dfd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -210,6 +210,7 @@ under the License.
     <module>helix-examples</module>
     <module>helix-ipc</module>
     <module>helix-ui</module>
+    <module>helix-archetype</module>
     <module>recipes</module>
   </modules>