You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by ni...@apache.org on 2016/04/14 18:34:15 UTC

[3/3] zest-java git commit: A Create Rest Application code generator.

A Create Rest Application code generator.


Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/45624ba4
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/45624ba4
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/45624ba4

Branch: refs/heads/develop
Commit: 45624ba4927d71a0cc6df7ab8a909116a7dd7de1
Parents: 852d583
Author: Niclas Hedhman <ni...@hedhman.org>
Authored: Fri Apr 15 00:31:55 2016 +0800
Committer: Niclas Hedhman <ni...@hedhman.org>
Committed: Fri Apr 15 00:31:55 2016 +0800

----------------------------------------------------------------------
 .../zest/library/restlet/ZrestApplication.java  | 256 +++++++++++++++++++
 tools/shell/src/bin/zest                        |   7 +-
 .../templates/defaultproject/project.properties |  15 --
 .../restproject/files/app/build.gradle_         |  20 ++
 .../src/main/java/__package__/app/package.html  |   3 +
 .../src/main/webapp/WEB-INF/___placeholder___   |   1 +
 .../app/src/test/java/__package__/package.html  |   1 +
 .../restproject/files/bootstrap/build.gradle_   |  16 ++
 .../__package__/bootstrap/config/package.html_  |   1 +
 .../bootstrap/connectivity/package.html_        |   1 +
 .../__package__/bootstrap/domain/package.html_  |   1 +
 .../bootstrap/infrastructure/package.html_      |   1 +
 .../src/test/java/__package__/package.html_     |   1 +
 .../templates/restproject/files/build.gradle_   |  26 ++
 .../files/gradle/wrapper/gradle-wrapper.jar_    | Bin 0 -> 51348 bytes
 .../gradle/wrapper/gradle-wrapper.properties_   |   6 +
 .../templates/restproject/files/gradlew.bat_    |  90 +++++++
 .../etc/templates/restproject/files/gradlew_    | 164 ++++++++++++
 .../restproject/files/model/build.gradle_       |   7 +
 .../java/__package__/model/orders/package.html_ |   1 +
 .../__package__/model/security/package.html_    |   1 +
 .../src/test/java/__package__/package.html_     |   1 +
 .../restproject/files/rest/build.gradle_        |   8 +
 .../__package__/rest/security/package.html_     |   1 +
 .../src/test/java/__package__/package.html_     |   1 +
 .../org/apache/zest/tools/shell/FileUtils.java  |  27 +-
 .../java/org/apache/zest/tools/shell/Main.java  |  39 ++-
 .../zest/tools/shell/create/CreateProject.java  |  38 ++-
 .../create/project/AbstractProjectCreator.java  |  61 +++++
 .../shell/create/project/ProjectCreator.java    |  14 +
 .../create/project/RestProjectCreator.java      |  71 +++++
 .../restapp/ApplicationAssemblerWriter.java     |  85 ++++++
 .../project/restapp/ApplicationWriter.java      | 114 +++++++++
 .../project/restapp/ConfigLayerWriter.java      |  61 +++++
 .../project/restapp/ConfigModuleWriter.java     |  57 +++++
 .../restapp/ConnectivityLayerWriter.java        |  54 ++++
 .../project/restapp/CrudModuleWriter.java       |  54 ++++
 .../create/project/restapp/CustomerWriter.java  |  48 ++++
 .../project/restapp/DomainLayerWriter.java      |  61 +++++
 .../restapp/FileConfigurationModuleWriter.java  |  56 ++++
 .../HardCodedSecurityRepositoryMixinWriter.java |  67 +++++
 .../create/project/restapp/IndexHtmlWriter.java |  37 +++
 .../project/restapp/IndexingModuleWriter.java   |  66 +++++
 .../restapp/InfrastructureLayerWriter.java      |  71 +++++
 .../create/project/restapp/OrderItemWriter.java |  46 ++++
 .../project/restapp/OrderModuleWriter.java      |  65 +++++
 .../create/project/restapp/OrderWriter.java     |  51 ++++
 .../project/restapp/RestModuleWriter.java       |  66 +++++
 .../project/restapp/SecurityModuleWriter.java   |  67 +++++
 .../restapp/SecurityRepositoryWriter.java       |  51 ++++
 .../restapp/SerializationModuleWriter.java      |  70 +++++
 .../create/project/restapp/SettingsWriter.java  |  55 ++++
 .../project/restapp/SimpleEnrolerWriter.java    |  68 +++++
 .../project/restapp/SimpleVerifierWriter.java   |  62 +++++
 .../project/restapp/StorageModuleWriter.java    |  67 +++++
 .../create/project/restapp/WebXmlWriter.java    |  65 +++++
 .../templates/default/project.properties        |  15 ++
 .../templates/restapp/project.properties        |  18 ++
 58 files changed, 2441 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/libraries/restlet/src/main/java/org/apache/zest/library/restlet/ZrestApplication.java
----------------------------------------------------------------------
diff --git a/libraries/restlet/src/main/java/org/apache/zest/library/restlet/ZrestApplication.java b/libraries/restlet/src/main/java/org/apache/zest/library/restlet/ZrestApplication.java
new file mode 100644
index 0000000..296c0a2
--- /dev/null
+++ b/libraries/restlet/src/main/java/org/apache/zest/library/restlet/ZrestApplication.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2015 Niclas Hedhman, niclas@hedhman.org
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.zest.library.restlet;
+
+import java.util.logging.Level;
+import org.apache.zest.api.composite.TransientBuilderFactory;
+import org.apache.zest.api.entity.Identity;
+import org.apache.zest.api.object.ObjectFactory;
+import org.apache.zest.api.service.ServiceFinder;
+import org.apache.zest.api.structure.Application;
+import org.apache.zest.api.structure.Module;
+import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
+import org.apache.zest.api.value.ValueBuilderFactory;
+import org.apache.zest.bootstrap.AssemblyException;
+import org.apache.zest.bootstrap.layered.LayeredApplicationAssembler;
+import org.apache.zest.library.restlet.crud.EntityListResource;
+import org.apache.zest.library.restlet.crud.EntityResource;
+import org.apache.zest.library.restlet.resource.CreationResource;
+import org.apache.zest.library.restlet.resource.DefaultResourceFactoryImpl;
+import org.apache.zest.library.restlet.resource.EntryPoint;
+import org.apache.zest.library.restlet.resource.EntryPointResource;
+import org.apache.zest.library.restlet.resource.ResourceFactory;
+import org.apache.zest.library.restlet.resource.ServerResource;
+import org.apache.zest.library.restlet.serialization.ZestConverter;
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.data.ChallengeScheme;
+import org.restlet.data.Parameter;
+import org.restlet.engine.Engine;
+import org.restlet.routing.Filter;
+import org.restlet.routing.Router;
+import org.restlet.routing.TemplateRoute;
+import org.restlet.security.ChallengeAuthenticator;
+import org.restlet.security.Enroler;
+import org.restlet.security.Verifier;
+import org.restlet.util.Series;
+
+/**
+ * This class is generic enough to be promoted to Zest's Restlet Library
+ */
+public abstract class ZrestApplication extends org.restlet.Application
+{
+    protected org.apache.zest.api.structure.Application zestApplication;
+    protected ServiceFinder serviceFinder;
+    protected ObjectFactory objectFactory;
+    protected TransientBuilderFactory transientBuilderFactory;
+    protected UnitOfWorkFactory unitOfWorkFactory;
+    protected ValueBuilderFactory valueBuilderFactory;
+
+    private Router router;
+
+    public ZrestApplication( Context context )
+        throws AssemblyException
+    {
+        super( context );
+    }
+
+    protected void printRoutes()
+    {
+        router.getRoutes().stream().forEach(
+            route -> System.out.println( route.toString() ) );
+    }
+
+    protected abstract LayeredApplicationAssembler createApplicationAssembler( String mode )
+        throws AssemblyException;
+
+    @Override
+    public synchronized void start()
+        throws Exception
+    {
+        Series<Parameter> parameters = getContext().getParameters();
+        String mode = parameters.getFirstValue( "org.sensorsink.kooda.mode" );
+        createApplication( mode );
+        zestApplication.activate();
+        Module module = zestApplication.findModule( getConnectivityLayer(), getConnectivityModule() );
+        serviceFinder = module;
+        objectFactory = module;
+        transientBuilderFactory = module;
+        unitOfWorkFactory = module.unitOfWorkFactory();
+        valueBuilderFactory = module;
+        super.start();
+    }
+
+    private void createApplication( String mode )
+    {
+        try
+        {
+            LayeredApplicationAssembler assembler = createApplicationAssembler(mode);
+            assembler.initialize();
+            zestApplication = assembler.application();
+            setName( zestApplication.name() );
+        }
+        catch( Throwable e )
+        {
+            e.printStackTrace();
+            getLogger().log( Level.SEVERE, "Unable to start Zest application.", e );
+            throw new InternalError( "Unable to start Zest application.", e );
+        }
+        getLogger().info( "RestApplication successfully created." );
+    }
+
+    @Override
+    public synchronized void stop()
+        throws Exception
+    {
+        super.stop();
+        zestApplication.passivate();
+    }
+
+    @Override
+    public Restlet createInboundRoot()
+    {
+        Context context = getContext();
+        Engine.getInstance().getRegisteredConverters().add( new ZestConverter( objectFactory ) );
+
+        if( zestApplication.mode() == Application.Mode.development )
+        {
+            setDebugging( true );
+        }
+        router = new Router( context );
+
+        addRoutes( router );
+        router.attach( "/", newZestRestlet( EntryPointResource.class, EntryPoint.class ) );
+
+        ChallengeAuthenticator guard = new ChallengeAuthenticator( context, ChallengeScheme.HTTP_BASIC, "Storm Clouds" );
+
+        Verifier verifier = createVerifier();
+        if( verifier != null )
+        {
+            guard.setVerifier( verifier );
+        }
+
+        Enroler enroler = createEnroler();
+        if( enroler != null )
+        {
+            guard.setEnroler( enroler );
+        }
+
+        // In the future, look into JAAS approach.
+//        Configuration jaasConfig = Configuration.getConfiguration();
+//        JaasVerifier verifier = new JaasVerifier( "BasicJaasAuthenticationApplication");
+//        verifier.setConfiguration( jaasConfig);
+//        verifier.setUserPrincipalClassName("com.sun.security.auth.UserPrincipal");
+//        guard.setVerifier(verifier);
+
+        return createInterceptors( guard );
+    }
+
+    private Restlet createInterceptors( ChallengeAuthenticator guard )
+    {
+        Filter inner = createInnerInterceptor();
+        if( inner != null )
+        {
+            inner.setNext( router );
+            guard.setNext( inner );             // guard -> interceptor -> router
+        }
+        else
+        {
+            guard.setNext( router );            // guard -> router
+        }
+        inner = guard;                      // inner = guard
+
+        Filter outer = createOuterInterceptor();
+        if( outer != null )
+        {
+            outer.setNext( inner );             // outer -> inner
+            return outer;
+        }
+        return inner;
+    }
+
+    protected Filter createOuterInterceptor()
+    {
+        return null;
+    }
+
+    protected Filter createInnerInterceptor()
+    {
+        return null;
+    }
+
+    protected Verifier createVerifier()
+    {
+        return null;
+    }
+
+    protected Enroler createEnroler()
+    {
+        return null;
+    }
+
+    protected abstract String getConnectivityLayer();
+
+    protected abstract String getConnectivityModule();
+
+    protected abstract void addRoutes( Router router );
+
+    protected void addResourcePath( String name,
+                                    Class<? extends Identity> type,
+                                    String basePath
+    )
+    {
+        addResourcePath( name, type, basePath, true, true );
+    }
+
+    protected void addResourcePath( String name,
+                                    Class<? extends Identity> type,
+                                    String basePath,
+                                    boolean createLink,
+                                    boolean rootRoute
+    )
+    {
+        if( createLink )
+        {
+            router.attach( basePath + name + "/create", newZestRestlet( CreationResource.class, type ) );
+        }
+        TemplateRoute route = router.attach( basePath + name + "/", newZestRestlet( EntityListResource.class, type ) );
+        if( rootRoute )
+        {
+            route.setName( name );
+        }
+        router.attach( basePath + name + "/{id}/", newZestRestlet( EntityResource.class, type ) );
+        router.attach( basePath + name + "/{id}/{invoke}", newZestRestlet( EntityResource.class, type ) );
+    }
+
+    private <K extends Identity, T extends ServerResource<K>> Restlet newZestRestlet( Class<T> resourceClass,
+                                                                                      Class<K> entityClass
+    )
+    {
+
+        @SuppressWarnings( "unchecked" )
+        ResourceFactory<K, T> factory = objectFactory.newObject( DefaultResourceFactoryImpl.class,
+                                                                 resourceClass, router
+        );
+        ZestConverter converter = new ZestConverter( objectFactory );
+        return objectFactory.newObject( ZestEntityRestlet.class,
+                                        factory,
+                                        router,
+                                        entityClass,
+                                        converter
+        );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/bin/zest
----------------------------------------------------------------------
diff --git a/tools/shell/src/bin/zest b/tools/shell/src/bin/zest
index 2438b07..778f318 100644
--- a/tools/shell/src/bin/zest
+++ b/tools/shell/src/bin/zest
@@ -15,5 +15,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-java -jar org.apache.zest.tools.shell-@@version@@.jar "$@"
+# Absolute path to this script, e.g. /home/user/bin/foo.sh
+ZESTSCRIPT=$(readlink -f "$0")
+# Absolute path this script is in, thus /home/user/bin
+ZESTPATH=$(dirname "$ZESTSCRIPT")
+
+java -Dzest.home=$ZESTPATH -jar org.apache.zest.tools.shell-@@version@@.jar "$@"
 

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/defaultproject/project.properties
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/defaultproject/project.properties b/tools/shell/src/etc/templates/defaultproject/project.properties
deleted file mode 100644
index a779d4f..0000000
--- a/tools/shell/src/etc/templates/defaultproject/project.properties
+++ /dev/null
@@ -1,15 +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.
-

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/app/build.gradle_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/app/build.gradle_ b/tools/shell/src/etc/templates/restproject/files/app/build.gradle_
new file mode 100644
index 0000000..5a19653
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/app/build.gradle_
@@ -0,0 +1,20 @@
+
+apply plugin: 'war'
+apply plugin: 'jetty'
+
+dependencies {
+  compile project( ":bootstrap" )
+  compile project( ":model" )
+  compile project( ":rest" )
+
+  compile "org.apache.zest.core:org.apache.zest.core.spi:$zestVersion"
+  compile "org.apache.zest.core:org.apache.zest.core.bootstrap:$zestVersion"
+  compile "org.apache.zest.library:org.apache.zest.library.servlet:$zestVersion"
+
+  compile "javax.servlet:servlet-api:2.5"
+  compile "org.restlet.jee:org.restlet:2.3.4"
+
+  runtime "org.apache.zest.core:org.apache.zest.core.runtime:$zestVersion"
+  runtime "org.restlet.jee:org.restlet.ext.servlet:2.3.4"
+
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/app/src/main/java/__package__/app/package.html
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/app/src/main/java/__package__/app/package.html b/tools/shell/src/etc/templates/restproject/files/app/src/main/java/__package__/app/package.html
new file mode 100644
index 0000000..e5eab74
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/app/src/main/java/__package__/app/package.html
@@ -0,0 +1,3 @@
+<html>
+<body>This package contains the bootstrap code.</body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/app/src/main/webapp/WEB-INF/___placeholder___
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/app/src/main/webapp/WEB-INF/___placeholder___ b/tools/shell/src/etc/templates/restproject/files/app/src/main/webapp/WEB-INF/___placeholder___
new file mode 100644
index 0000000..0e6b010
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/app/src/main/webapp/WEB-INF/___placeholder___
@@ -0,0 +1 @@
+Webapp directory.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/app/src/test/java/__package__/package.html
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/app/src/test/java/__package__/package.html b/tools/shell/src/etc/templates/restproject/files/app/src/test/java/__package__/package.html
new file mode 100644
index 0000000..0544e17
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/app/src/test/java/__package__/package.html
@@ -0,0 +1 @@
+<html><body>Test directory</body></html>

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/bootstrap/build.gradle_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/bootstrap/build.gradle_ b/tools/shell/src/etc/templates/restproject/files/bootstrap/build.gradle_
new file mode 100644
index 0000000..f26f7f8
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/bootstrap/build.gradle_
@@ -0,0 +1,16 @@
+
+dependencies {
+  compile project( ":model" )
+  compile project( ":rest" )
+
+  compile "org.apache.zest.core:org.apache.zest.core.spi:$zestVersion"
+  compile "org.apache.zest.core:org.apache.zest.core.bootstrap:$zestVersion"
+
+
+  compile "org.apache.zest.library:org.apache.zest.library.fileconfig:$zestVersion"
+  compile "org.apache.zest.library:org.apache.zest.library.restlet:$zestVersion"
+  compile "org.apache.zest.extension:org.apache.zest.extension.entitystore-file:$zestVersion"
+  compile "org.apache.zest.extension:org.apache.zest.extension.indexing-rdf:$zestVersion"
+  compile "org.apache.zest.extension:org.apache.zest.extension.valueserialization-jackson:$zestVersion"
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/config/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/config/package.html_ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/config/package.html_
new file mode 100644
index 0000000..e4bffa5
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/config/package.html_
@@ -0,0 +1 @@
+<html><body>This package contains the assembly information for the Config layer.</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/connectivity/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/connectivity/package.html_ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/connectivity/package.html_
new file mode 100644
index 0000000..21dbaa9
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/connectivity/package.html_
@@ -0,0 +1 @@
+<html><body>This package contains the assembly information for the Connectivity layer.</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/domain/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/domain/package.html_ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/domain/package.html_
new file mode 100644
index 0000000..2bdc426
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/domain/package.html_
@@ -0,0 +1 @@
+<html><body>This package contains the assembly information for the Domain layer.</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/infrastructure/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/infrastructure/package.html_ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/infrastructure/package.html_
new file mode 100644
index 0000000..cf2f9b5
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/main/java/__package__/bootstrap/infrastructure/package.html_
@@ -0,0 +1 @@
+<html><body>This package contains the assembly information for the Infrastructure layer.</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/bootstrap/src/test/java/__package__/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/bootstrap/src/test/java/__package__/package.html_ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/test/java/__package__/package.html_
new file mode 100644
index 0000000..300838d
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/bootstrap/src/test/java/__package__/package.html_
@@ -0,0 +1 @@
+<html><body>Tests package</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/build.gradle_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/build.gradle_ b/tools/shell/src/etc/templates/restproject/files/build.gradle_
new file mode 100644
index 0000000..9bfbb1e
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/build.gradle_
@@ -0,0 +1,26 @@
+
+version = 1.0
+
+rootProject.ext {
+ // zestVersion = @@version@@
+  zestVersion = 0           // 0 only during dev & testing
+}
+
+allprojects() {
+  apply plugin: 'java'
+  apply plugin: 'idea'
+  apply plugin: 'maven'
+
+  repositories {
+    mavenLocal()
+    mavenCentral()
+    maven { name 'restlet-repo'; url 'http://maven.restlet.org/' }
+  }
+
+
+  dependencies {
+    compile "org.apache.zest.core:org.apache.zest.core.api:$zestVersion"
+    testCompile "org.apache.zest.core:org.apache.zest.core.testsupport:$zestVersion"
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.jar_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.jar_ b/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.jar_
new file mode 100644
index 0000000..0087cd3
Binary files /dev/null and b/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.jar_ differ

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.properties_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.properties_ b/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.properties_
new file mode 100644
index 0000000..fafa8dd
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/gradle/wrapper/gradle-wrapper.properties_
@@ -0,0 +1,6 @@
+#Mon Jul 06 10:43:59 EEST 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.11-bin.zip

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/gradlew.bat_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/gradlew.bat_ b/tools/shell/src/etc/templates/restproject/files/gradlew.bat_
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/gradlew.bat_
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/gradlew_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/gradlew_ b/tools/shell/src/etc/templates/restproject/files/gradlew_
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/gradlew_
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/model/build.gradle_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/model/build.gradle_ b/tools/shell/src/etc/templates/restproject/files/model/build.gradle_
new file mode 100644
index 0000000..83f55b2
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/model/build.gradle_
@@ -0,0 +1,7 @@
+
+
+dependencies {
+
+  compile "org.restlet.jee:org.restlet:2.3.4"
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/orders/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/orders/package.html_ b/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/orders/package.html_
new file mode 100644
index 0000000..441cb85
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/orders/package.html_
@@ -0,0 +1 @@
+<html><body>Very simple Domain Model to showcase the features of the Restlet library</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/security/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/security/package.html_ b/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/security/package.html_
new file mode 100644
index 0000000..bcf0ee4
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/model/src/main/java/__package__/model/security/package.html_
@@ -0,0 +1 @@
+<html><body>Very simple Security Model to showcase the features of the Restlet library</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/model/src/test/java/__package__/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/model/src/test/java/__package__/package.html_ b/tools/shell/src/etc/templates/restproject/files/model/src/test/java/__package__/package.html_
new file mode 100644
index 0000000..300838d
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/model/src/test/java/__package__/package.html_
@@ -0,0 +1 @@
+<html><body>Tests package</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/rest/build.gradle_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/rest/build.gradle_ b/tools/shell/src/etc/templates/restproject/files/rest/build.gradle_
new file mode 100644
index 0000000..a89355a
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/rest/build.gradle_
@@ -0,0 +1,8 @@
+
+dependencies {
+  compile project( ":model" )
+
+  compile "org.apache.zest.core:org.apache.zest.core.api:$zestVersion"
+  compile "org.apache.zest.library:org.apache.zest.library.restlet:$zestVersion"
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/rest/src/main/java/__package__/rest/security/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/rest/src/main/java/__package__/rest/security/package.html_ b/tools/shell/src/etc/templates/restproject/files/rest/src/main/java/__package__/rest/security/package.html_
new file mode 100644
index 0000000..249f68c
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/rest/src/main/java/__package__/rest/security/package.html_
@@ -0,0 +1 @@
+<html><body>Package for the security handling in the Connectivity Layer</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/etc/templates/restproject/files/rest/src/test/java/__package__/package.html_
----------------------------------------------------------------------
diff --git a/tools/shell/src/etc/templates/restproject/files/rest/src/test/java/__package__/package.html_ b/tools/shell/src/etc/templates/restproject/files/rest/src/test/java/__package__/package.html_
new file mode 100644
index 0000000..300838d
--- /dev/null
+++ b/tools/shell/src/etc/templates/restproject/files/rest/src/test/java/__package__/package.html_
@@ -0,0 +1 @@
+<html><body>Tests package</body></html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/FileUtils.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/FileUtils.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/FileUtils.java
index bb50dcf..1afa788 100644
--- a/tools/shell/src/main/java/org/apache/zest/tools/shell/FileUtils.java
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/FileUtils.java
@@ -18,7 +18,12 @@
  */
 package org.apache.zest.tools.shell;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
@@ -27,14 +32,15 @@ import java.util.Properties;
 
 public class FileUtils
 {
-    public static void createDir( String directoryName )
+    public static File createDir( String directoryName )
     {
         File dir = new File( directoryName ).getAbsoluteFile();
         if( !dir.mkdirs() )
         {
             System.err.println( "Unable to create directory " + dir );
-            System.exit( 1 );
+//            System.exit( 1 );   during testing, I am tired of deleting directory over and over again.
         }
+        return dir;
     }
 
     public static Map<String, String> readPropertiesResource( String resourceName )
@@ -51,7 +57,7 @@ public class FileUtils
             }
             return result;
         }
-        catch( IOException e )
+        catch( Exception e )
         {
             System.err.println( "Unable to read resource " + resourceName );
             System.exit( 2 );
@@ -66,4 +72,19 @@ public class FileUtils
         p.load( in );
         return p;
     }
+
+    public static void copyFile( File srcFile, File dest )
+        throws IOException
+    {
+        byte[] buffer = new byte[100000];
+        try(BufferedInputStream in = new BufferedInputStream( new FileInputStream(srcFile) )){
+            try(BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream( dest ) )){
+                int bytes;
+                while( (bytes = in.read( buffer )) != -1 ){
+                    out.write( buffer, 0, bytes );
+                }
+                out.flush();
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/Main.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/Main.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/Main.java
index 7a545f6..6b5454a 100644
--- a/tools/shell/src/main/java/org/apache/zest/tools/shell/Main.java
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/Main.java
@@ -21,23 +21,29 @@ package org.apache.zest.tools.shell;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.io.PrintWriter;
-import java.util.TreeSet;
+import java.util.Map;
+import java.util.TreeMap;
 import org.apache.zest.tools.shell.create.CreateProject;
 import org.apache.zest.tools.shell.help.HelpCommand;
 
 public class Main
 {
-    private TreeSet<Command> commands = new TreeSet<Command>();
+    private Map<String, Command> commands = new TreeMap<>();
 
     public static void main( String[] args )
     {
         new Main().run( args );
     }
 
-    public Main()
+    private Main()
     {
-        this.commands.add( new HelpCommand() );
-        this.commands.add( new CreateProject() );
+        addCommand( new HelpCommand() );
+        addCommand( new CreateProject() );
+    }
+
+    private void addCommand( Command command )
+    {
+        commands.put( command.name(), command );
     }
 
     private void run( String[] args )
@@ -49,9 +55,21 @@ public class Main
         }
         if( args.length == 0 )
         {
-            HelpCommand helpCommand = new HelpCommand();
-            helpCommand.setCommands( commands );
-            helpCommand.execute( args, input(), output() );
+            commands.get( "help" ).execute( args, input(), error() );
+        }
+        else
+        {
+            Command command = commands.get( args[ 0 ] );
+            if( command == null )
+            {
+                System.err.println( "Command " + args[ 0 ] + " is unknown." );
+                System.err.println( "" );
+                commands.get( "help" ).execute( args, input(), error() );
+            }
+            else
+            {
+                command.execute( args, input(), output() );
+            }
         }
     }
 
@@ -67,6 +85,11 @@ public class Main
         return false;
     }
 
+    private PrintWriter error()
+    {
+        return new PrintWriter( System.err );
+    }
+
     private PrintWriter output()
     {
         return new PrintWriter( System.out );

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/CreateProject.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/CreateProject.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/CreateProject.java
index 47bc7f7..4c709c0 100644
--- a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/CreateProject.java
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/CreateProject.java
@@ -19,11 +19,13 @@
 package org.apache.zest.tools.shell.create;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.PrintWriter;
 import java.util.Map;
 import org.apache.zest.tools.shell.AbstractCommand;
 import org.apache.zest.tools.shell.FileUtils;
 import org.apache.zest.tools.shell.HelpNeededException;
+import org.apache.zest.tools.shell.create.project.ProjectCreator;
 
 public class CreateProject extends AbstractCommand
 {
@@ -32,24 +34,42 @@ public class CreateProject extends AbstractCommand
     public void execute( String[] args, BufferedReader input, PrintWriter output )
         throws HelpNeededException
     {
-        if( args.length < 1 )
+        if( args.length < 4 )
+        {
             throw new HelpNeededException();
-        String projectName = args[0];
-        String template = "defaultproject";
-        if( args.length < 2 )
-            template = args[1];
-        FileUtils.createDir( projectName );
+        }
+        String template = args[ 1 ];
+        String projectName = args[ 2 ];
+        String rootPackage = args[ 3 ];
+        File projectDir = FileUtils.createDir( projectName );
         Map<String, String> props = FileUtils.readPropertiesResource( "templates/" + template + "/project.properties" );
-        for( Map.Entry<String,String> p: props.entrySet() )
+        if( props == null )
         {
-
+            System.err.println( "Project Template " + template + " does not exist. " );
+            System.exit( 1 );
+        }
+        props.put( "project.dir", projectDir.getAbsolutePath() );
+        props.put( "project.name", projectName);
+        props.put( "template", template);
+        props.put( "root.package", rootPackage);
+        props.put( "zest.home", System.getProperty( "zest.home" ) );
+        String classname = props.get( "creator.class" );
+        try
+        {
+            ProjectCreator creator = (ProjectCreator) Class.forName( classname ).newInstance();
+            creator.create( args[ 0 ], projectDir, props );
+        }
+        catch( Exception e )
+        {
+            e.printStackTrace();
+            throw new RuntimeException( "Unable to create the Project Creator." );
         }
     }
 
     @Override
     public String description()
     {
-        return "create-project";
+        return "create project";
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/AbstractProjectCreator.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/AbstractProjectCreator.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/AbstractProjectCreator.java
new file mode 100644
index 0000000..ffe0440
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/AbstractProjectCreator.java
@@ -0,0 +1,61 @@
+package org.apache.zest.tools.shell.create.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import org.apache.zest.tools.shell.FileUtils;
+
+abstract class AbstractProjectCreator
+    implements ProjectCreator
+{
+
+    @Override
+    public void create( String projectName,
+                        File projectDir,
+                        Map<String, String> properties
+    )
+        throws IOException
+    {
+        File templateDir = new File( properties.get( "zest.home" ), properties.get( "template.dir" ) );
+        copyFiles( templateDir, projectDir, properties.get( "root.package" ) );
+    }
+
+    private void copyFiles( File fromDir, File toDir, String rootpackage )
+        throws IOException
+    {
+        File[] files = fromDir.listFiles();
+        if( files == null )
+        {
+            return;
+        }
+        toDir.mkdirs();     // create all directories needed.
+        for( File f : files )
+        {
+            String filename = f.getName();
+            if( f.isDirectory() )
+            {
+                if( filename.equals( "__package__" ) )
+                {
+                    toDir = new File( toDir, rootpackage.replaceAll( "\\.", "/" ) );
+                    copyFiles( f, toDir, rootpackage );
+                }
+                else
+                {
+                    copyFiles( f, new File( toDir, filename ), rootpackage );
+                }
+            }
+            if( f.isFile() )
+            {
+                if( !filename.equals( "___placeholder___" ) )  // skip these files that are needed for GIT.
+                {
+                    if( filename.endsWith( "_" ) )
+                    {
+                        filename = filename.substring( 0, filename.length() - 1 );
+                    }
+                    File dest = new File( toDir, filename );
+                    FileUtils.copyFile( f, dest );
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/ProjectCreator.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/ProjectCreator.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/ProjectCreator.java
new file mode 100644
index 0000000..f99fe30
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/ProjectCreator.java
@@ -0,0 +1,14 @@
+package org.apache.zest.tools.shell.create.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+public interface ProjectCreator
+{
+    void create( String projectName,
+                 File projectDir,
+                 Map<String, String> properties
+    )
+        throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/RestProjectCreator.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/RestProjectCreator.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/RestProjectCreator.java
new file mode 100644
index 0000000..5a67a0b
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/RestProjectCreator.java
@@ -0,0 +1,71 @@
+package org.apache.zest.tools.shell.create.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import org.apache.zest.tools.shell.create.project.restapp.ApplicationAssemblerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.ApplicationWriter;
+import org.apache.zest.tools.shell.create.project.restapp.ConfigLayerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.ConfigModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.ConnectivityLayerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.CrudModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.CustomerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.DomainLayerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.FileConfigurationModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.HardCodedSecurityRepositoryMixinWriter;
+import org.apache.zest.tools.shell.create.project.restapp.IndexingModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.InfrastructureLayerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.OrderItemWriter;
+import org.apache.zest.tools.shell.create.project.restapp.OrderWriter;
+import org.apache.zest.tools.shell.create.project.restapp.RestModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.OrderModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.SecurityModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.SecurityRepositoryWriter;
+import org.apache.zest.tools.shell.create.project.restapp.SerializationModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.SettingsWriter;
+import org.apache.zest.tools.shell.create.project.restapp.SimpleEnrolerWriter;
+import org.apache.zest.tools.shell.create.project.restapp.SimpleVerifierWriter;
+import org.apache.zest.tools.shell.create.project.restapp.StorageModuleWriter;
+import org.apache.zest.tools.shell.create.project.restapp.WebXmlWriter;
+
+public class RestProjectCreator extends AbstractProjectCreator
+    implements ProjectCreator
+{
+
+    @Override
+    public void create( String projectName,
+                        File projectDir,
+                        Map<String, String> properties
+    )
+        throws IOException
+    {
+        super.create( projectName, projectDir, properties );    // creates the directory structures.
+        new ApplicationAssemblerWriter().writeClass( properties );
+        new ConfigLayerWriter().writeClass( properties );
+        new ConfigModuleWriter().writeClass( properties );
+        new InfrastructureLayerWriter().writeClass( properties );
+        new FileConfigurationModuleWriter().writeClass( properties );
+        new StorageModuleWriter().writeClass( properties );
+        new IndexingModuleWriter().writeClass( properties );
+        new SerializationModuleWriter().writeClass( properties );
+        new DomainLayerWriter().writeClass( properties );
+        new OrderModuleWriter().writeClass( properties );
+        new CrudModuleWriter().writeClass( properties );
+        new ConnectivityLayerWriter().writeClass( properties );
+        new RestModuleWriter().writeClass( properties );
+
+        new ApplicationWriter().writeClass( properties );
+        new SimpleEnrolerWriter().writeClass( properties );
+        new SimpleVerifierWriter().writeClass( properties );
+
+        new SecurityModuleWriter().writeClass( properties );
+        new SecurityRepositoryWriter().writeClass( properties );
+        new HardCodedSecurityRepositoryMixinWriter().writeClass( properties );
+        new OrderWriter().writeClass( properties );
+        new OrderItemWriter().writeClass( properties );
+        new CustomerWriter().writeClass( properties );
+
+        new SettingsWriter().writeClass( properties );
+        new WebXmlWriter().writeClass( properties );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationAssemblerWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationAssemblerWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationAssemblerWriter.java
new file mode 100644
index 0000000..a74ca32
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationAssemblerWriter.java
@@ -0,0 +1,85 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class ApplicationAssemblerWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap;" );
+            pw.println();
+            pw.println( "import java.io.IOException;" );
+            pw.println( "import java.nio.file.Files;" );
+            pw.println( "import java.nio.file.Path;" );
+            pw.println( "import java.nio.file.Paths;" );
+            pw.println( "import java.util.function.Function;" );
+            pw.println();
+            pw.println( "import org.apache.zest.api.structure.Application;" );
+            pw.println( "import org.apache.zest.api.structure.Module;\n" );
+            pw.println( "import org.apache.zest.bootstrap.ApplicationAssembly;" );
+            pw.println( "import org.apache.zest.bootstrap.AssemblyException;" );
+            pw.println( "import org.apache.zest.bootstrap.LayerAssembly;" );
+            pw.println( "import org.apache.zest.bootstrap.ModuleAssembly;" );
+            pw.println( "import org.apache.zest.bootstrap.layered.LayeredApplicationAssembler;" );
+            pw.println();
+            pw.println( "import " + rootPackage + ".bootstrap.connectivity.ConnectivityLayer;" );
+            pw.println( "import " + rootPackage + ".bootstrap.domain.DomainLayer;" );
+            pw.println( "import " + rootPackage + ".bootstrap.config.ConfigurationLayer;" );
+            pw.println( "import " + rootPackage + ".bootstrap.infrastructure.InfrastructureLayer;" );
+            pw.println();
+            pw.print( "public class " );
+            pw.print( projectName );
+            pw.println( "ApplicationAssembler extends LayeredApplicationAssembler" );
+            pw.println( "{" );
+            pw.print( "    private static final String NAME = \"" );
+            pw.print( projectName );
+            pw.println( "\";" );
+            pw.println( "    private static final String VERSION = \"1.0.alpha\";" );
+            pw.println();
+            pw.print("    public ");
+            pw.print( projectName );
+            pw.println("ApplicationAssembler( Application.Mode mode )");
+            pw.println("    throws AssemblyException");
+            pw.println("    {");
+            pw.println("        super( NAME, VERSION, mode );");
+            pw.println("    }");
+            pw.println();
+            pw.println("    @Override");
+            pw.println("    protected void assembleLayers( ApplicationAssembly assembly )");
+            pw.println("        throws AssemblyException");
+            pw.println("    {");
+            pw.println("        LayerAssembly configLayer = createLayer( ConfigurationLayer.class );");
+            pw.println("        ModuleAssembly configModule = assemblerOf( ConfigurationLayer.class ).configModule();");
+            pw.println("        LayerAssembly domainLayer = createLayer( DomainLayer.class );");
+            pw.println("        Function<Application, Module> typeFinder = DomainLayer.typeFinder();");
+            pw.println("        LayerAssembly infraLayer = new InfrastructureLayer( configModule, typeFinder ).assemble( assembly.layer( InfrastructureLayer.NAME ) );");
+            pw.println("        LayerAssembly connectivityLayer = createLayer( ConnectivityLayer.class );");
+            pw.println("        connectivityLayer.uses( domainLayer );");
+            pw.println("        domainLayer.uses( infraLayer );");
+            pw.println("        infraLayer.uses( configLayer );");
+            pw.println("    }");
+            pw.println("}");
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/";
+        String classname = properties.get( "project.name" ) + "ApplicationAssembler";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ));
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationWriter.java
new file mode 100644
index 0000000..fd0b6dd
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ApplicationWriter.java
@@ -0,0 +1,114 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import static java.lang.String.format;
+
+public class ApplicationWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".app;" );
+            pw.println();
+            pw.println( "import java.lang.reflect.UndeclaredThrowableException;" );
+            pw.println( "import org.apache.zest.api.structure.Application;" );
+            pw.println( "import org.apache.zest.bootstrap.AssemblyException;" );
+            pw.println( "import org.apache.zest.bootstrap.layered.LayeredApplicationAssembler;" );
+            pw.println( "import org.apache.zest.library.restlet.ZrestApplication;" );
+            pw.println( "import org.restlet.Context;" );
+            pw.println( "import org.restlet.routing.Filter;" );
+            pw.println( "import org.restlet.routing.Router;" );
+            pw.println( "import org.restlet.security.Enroler;" );
+            pw.println( "import org.restlet.security.Verifier;" );
+            pw.println( format( "import %s.bootstrap.%sApplicationAssembler;", rootPackage, projectName ) );
+            pw.println( format( "import %s.bootstrap.connectivity.ConnectivityLayer;", rootPackage ) );
+            pw.println( format( "import %s.bootstrap.connectivity.RestModule;", rootPackage ) );
+            pw.println( format( "import %s.model.orders.Order;", rootPackage ) );
+            pw.println( format( "import %s.model.orders.Customer;", rootPackage ) );
+            pw.println(format("import %s.rest.security.SimpleEnroler;", rootPackage));
+            pw.println(format("import %s.rest.security.SimpleVerifier;", rootPackage));
+            pw.println();
+            pw.println( format( "public class %s extends ZrestApplication", projectName ) );
+            pw.println( "{\n" );
+            pw.println( format( "    public %s( Context context )", projectName ) );
+            pw.println( "        throws AssemblyException" );
+            pw.println( "    {" );
+            pw.println( "        super( context );" );
+            pw.println( "    }\n" );
+            pw.println( "    @Override" );
+            pw.println( "    protected void addRoutes( Router router )" );
+            pw.println( "    {" );
+            pw.println( "        addResourcePath( \"orders\", Order.class, \"/orders/{order}/\", true, false );" );
+            pw.println( "        addResourcePath( \"customers\", Customer.class, \"/customer/{customer}/\", true, false );" );
+            pw.println( "    }" );
+
+            pw.println( "    @Override" );
+            pw.println( "    protected LayeredApplicationAssembler createApplicationAssembler( String mode )" );
+            pw.println( "        throws AssemblyException" );
+            pw.println( "    {" );
+            pw.println( format("        return new %sApplicationAssembler( Application.Mode.valueOf( mode ) );", projectName) );
+            pw.println( "    }" );
+            pw.println();
+            pw.println( "    @Override" );
+            pw.println( "    protected Verifier createVerifier()" );
+            pw.println( "    {" );
+            pw.println( "        return newObject( SimpleVerifier.class );" );
+            pw.println( "    }" );
+            pw.println();
+            pw.println( "    @Override" );
+            pw.println( "    protected Enroler createEnroler()" );
+            pw.println( "    {" );
+            pw.println( "        return newObject( SimpleEnroler.class, this );" );
+            pw.println( "    }" );
+            pw.println();
+            pw.println( "    @Override" );
+            pw.println( "    protected String getConnectivityLayer()" );
+            pw.println( "    {" );
+            pw.println( "        return ConnectivityLayer.NAME;" );
+            pw.println( "    }" );
+            pw.println();
+            pw.println( "    @Override" );
+            pw.println( "    protected String getConnectivityModule()" );
+            pw.println( "    {" );
+            pw.println( "        return RestModule.NAME;" );
+            pw.println( "    }" );
+            pw.println();
+            pw.println( "    private <T> T newObject( Class<T> type, Object... uses )" );
+            pw.println( "    {" );
+            pw.println( "        try" );
+            pw.println( "        {" );
+            pw.println( "            T instamce = type.newInstance();" );
+            pw.println( "            objectFactory.injectTo( instamce, uses );" );
+            pw.println( "            return instamce;" );
+            pw.println( "        }" );
+            pw.println( "        catch( Exception e )" );
+            pw.println( "        {" );
+            pw.println( "            throw new UndeclaredThrowableException( e );" );
+            pw.println( "        }" );
+            pw.println( "    }" );
+            pw.println( "}" );
+            pw.println();
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/app/";
+        String classname = properties.get("project.name");
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "app/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigLayerWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigLayerWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigLayerWriter.java
new file mode 100644
index 0000000..e032026
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigLayerWriter.java
@@ -0,0 +1,61 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class ConfigLayerWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap.config;" );
+            pw.println();
+            pw.println(
+                "import org.apache.zest.bootstrap.AssemblyException;\n" +
+                "import org.apache.zest.bootstrap.LayerAssembly;\n" +
+                "import org.apache.zest.bootstrap.ModuleAssembly;\n" +
+                "import org.apache.zest.bootstrap.layered.LayerAssembler;\n" +
+                "import org.apache.zest.bootstrap.layered.LayeredLayerAssembler;\n" +
+                "\n" +
+                "public class ConfigurationLayer extends LayeredLayerAssembler\n" +
+                "    implements LayerAssembler\n" +
+                "{\n" +
+                "    public static final String NAME = \"Configuration Layer\";\n" +
+                "    private ModuleAssembly configModule;\n" +
+                "\n" +
+                "    @Override\n" +
+                "    public LayerAssembly assemble( LayerAssembly layer )\n" +
+                "        throws AssemblyException\n" +
+                "    {\n" +
+                "        configModule = createModule( layer, ConfigModule.class );\n" +
+                "        return layer;\n" +
+                "    }\n" +
+                "\n" +
+                "    public ModuleAssembly configModule()\n" +
+                "    {\n" +
+                "        return configModule;\n" +
+                "    }\n" +
+                "}\n"
+            );
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/config/";
+        String classname = "ConfigurationLayer";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigModuleWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigModuleWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigModuleWriter.java
new file mode 100644
index 0000000..805365a
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConfigModuleWriter.java
@@ -0,0 +1,57 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class ConfigModuleWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap.config;" );
+            pw.println();
+            pw.println(
+                "import org.apache.zest.api.common.Visibility;\n" +
+                "import org.apache.zest.bootstrap.AssemblyException;\n" +
+                "import org.apache.zest.bootstrap.LayerAssembly;\n" +
+                "import org.apache.zest.bootstrap.ModuleAssembly;\n" +
+                "import org.apache.zest.bootstrap.layered.ModuleAssembler;\n" +
+                "import org.apache.zest.entitystore.memory.MemoryEntityStoreService;\n" +
+                "import org.apache.zest.spi.uuid.UuidIdentityGeneratorService;\n" +
+                "import org.apache.zest.valueserialization.jackson.JacksonValueSerializationAssembler;\n" +
+                "\n" +
+                "public class ConfigModule\n" +
+                "    implements ModuleAssembler\n" +
+                "{\n" +
+                "    @Override\n" +
+                "    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )\n" +
+                "        throws AssemblyException\n" +
+                "    {\n" +
+                "        module.services( MemoryEntityStoreService.class ).visibleIn( Visibility.layer );\n" +
+                "        new JacksonValueSerializationAssembler().visibleIn( Visibility.layer ).assemble( module );\n" +
+                "        module.services( UuidIdentityGeneratorService.class ).visibleIn( Visibility.layer );\n" +
+                "        return module;\n" +
+                "    }\n" +
+                "}\n");
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/config/";
+        String classname = "ConfigModule";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConnectivityLayerWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConnectivityLayerWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConnectivityLayerWriter.java
new file mode 100644
index 0000000..117dfda
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/ConnectivityLayerWriter.java
@@ -0,0 +1,54 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class ConnectivityLayerWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap.connectivity;" );
+            pw.println();
+            pw.println(
+                "import org.apache.zest.bootstrap.AssemblyException;\n" +
+                "import org.apache.zest.bootstrap.LayerAssembly;\n" +
+                "import org.apache.zest.bootstrap.layered.LayerAssembler;\n" +
+                "import org.apache.zest.bootstrap.layered.LayeredLayerAssembler;\n" +
+                "\n" +
+                "public class ConnectivityLayer extends LayeredLayerAssembler\n" +
+                "    implements LayerAssembler\n" +
+                "{\n" +
+                "    public static String NAME;\n" +
+                "\n" +
+                "    @Override\n" +
+                "    public LayerAssembly assemble( LayerAssembly layer )\n" +
+                "        throws AssemblyException\n" +
+                "    {\n" +
+                "        createModule( layer, RestModule.class );\n" +
+                "        return layer;\n" +
+                "    }\n" +
+                "}\n"
+            );
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/connectivity/";
+        String classname = "ConnectivityLayer";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CrudModuleWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CrudModuleWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CrudModuleWriter.java
new file mode 100644
index 0000000..d6d80f8
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CrudModuleWriter.java
@@ -0,0 +1,54 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class CrudModuleWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap.domain;" );
+            pw.println();
+            pw.println(
+                "import org.apache.zest.bootstrap.AssemblyException;\n" +
+                "import org.apache.zest.bootstrap.LayerAssembly;\n" +
+                "import org.apache.zest.bootstrap.ModuleAssembly;\n" +
+                "import org.apache.zest.bootstrap.layered.ModuleAssembler;\n" +
+                "import org.apache.zest.library.restlet.assembly.CrudServiceAssembler;\n" +
+                "\n" +
+                "public class CrudModule\n" +
+                "    implements ModuleAssembler\n" +
+                "{\n" +
+                "    @Override\n" +
+                "    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )\n" +
+                "        throws AssemblyException\n" +
+                "    {\n" +
+                "        module.withDefaultUnitOfWorkFactory();\n" +
+                "        new CrudServiceAssembler().assemble( module );\n" +
+                "        return module;\n" +
+                "    }\n" +
+                "}\n"
+            );
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/domain/";
+        String classname = "CrudModule";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CustomerWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CustomerWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CustomerWriter.java
new file mode 100644
index 0000000..107d9cc
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/CustomerWriter.java
@@ -0,0 +1,48 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class CustomerWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".model.orders;" );
+            pw.println();
+            pw.println("import java.time.ZonedDateTime;");
+            pw.println("import org.apache.zest.api.entity.Identity;");
+            pw.println("import org.apache.zest.api.property.Property;");
+            pw.println();
+            pw.println(
+                "public interface Customer extends Identity\n" +
+                "{\n" +
+                "    Property<String> name();\n\n" +
+                "    Property<String> address();\n\n" +
+                "    Property<String> city();\n\n" +
+                "    Property<String> country();\n\n" +
+                "    Property<String> phone();\n\n" +
+                "    Property<ZonedDateTime> registered();\n\n" +
+                "}\n");
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/model/orders/";
+        String classname = "Customer";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "model/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/DomainLayerWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/DomainLayerWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/DomainLayerWriter.java
new file mode 100644
index 0000000..2e97765
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/DomainLayerWriter.java
@@ -0,0 +1,61 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class DomainLayerWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap.domain;" );
+            pw.println();
+            pw.println(
+                "import java.util.function.Function;\n" +
+                "import org.apache.zest.api.structure.Application;\n" +
+                "import org.apache.zest.api.structure.Module;\n" +
+                "import org.apache.zest.bootstrap.AssemblyException;\n" +
+                "import org.apache.zest.bootstrap.LayerAssembly;\n" +
+                "import org.apache.zest.bootstrap.layered.LayerAssembler;\n" +
+                "import org.apache.zest.bootstrap.layered.LayeredLayerAssembler;\n" +
+                "\n" +
+                "public class DomainLayer extends LayeredLayerAssembler\n" +
+                "    implements LayerAssembler\n" +
+                "{\n" +
+                "    @Override\n" +
+                "    public LayerAssembly assemble(LayerAssembly layer)\n" +
+                "        throws AssemblyException\n" +
+                "    {\n" +
+                "        createModule( layer, CrudModule.class );\n" +
+                "        createModule( layer, OrderModule.class );   // This is a simple sample that you typically remove.\n" +
+                "        return layer;\n" +
+                "    }\n" +
+                "\n" +
+                "    public static Function<Application, Module> typeFinder()\n" +
+                "    {\n" +
+                "        return application -> application.findModule( \"Domain Layer\", \"Assets Module\" );\n" +
+                "    }\n" +
+                "}\n"
+            );
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/domain/";
+        String classname = "DomainLayer";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-java/blob/45624ba4/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/FileConfigurationModuleWriter.java
----------------------------------------------------------------------
diff --git a/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/FileConfigurationModuleWriter.java b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/FileConfigurationModuleWriter.java
new file mode 100644
index 0000000..b9e9de5
--- /dev/null
+++ b/tools/shell/src/main/java/org/apache/zest/tools/shell/create/project/restapp/FileConfigurationModuleWriter.java
@@ -0,0 +1,56 @@
+package org.apache.zest.tools.shell.create.project.restapp;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+public class FileConfigurationModuleWriter
+{
+
+    public void writeClass( Map<String, String> properties )
+        throws IOException
+    {
+        String rootPackage = properties.get( "root.package" );
+        String projectName = properties.get( "project.name" );
+        try (PrintWriter pw = createPrinter( properties ))
+        {
+            pw.print( "package " );
+            pw.print( properties.get( "root.package" ) );
+            pw.println( ".bootstrap.infrastructure;" );
+            pw.println();
+            pw.println(
+                "import org.apache.zest.api.common.Visibility;\n" +
+                "import org.apache.zest.bootstrap.AssemblyException;\n" +
+                "import org.apache.zest.bootstrap.LayerAssembly;\n" +
+                "import org.apache.zest.bootstrap.ModuleAssembly;\n" +
+                "import org.apache.zest.bootstrap.layered.ModuleAssembler;\n" +
+                "import org.apache.zest.library.fileconfig.FileConfigurationAssembler;\n" +
+                "\n" +
+                "public class FileConfigurationModule\n" +
+                "    implements ModuleAssembler\n" +
+                "{\n" +
+                "    public static String NAME;\n" +
+                "\n" +
+                "    @Override\n" +
+                "    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )\n" +
+                "        throws AssemblyException\n" +
+                "    {\n" +
+                "        new FileConfigurationAssembler().visibleIn( Visibility.layer ).assemble( module );\n" +
+                "        return module;\n" +
+                "    }\n" +
+                "}\n"
+            );
+        }
+    }
+
+    private PrintWriter createPrinter( Map<String, String> properties )
+        throws IOException
+    {
+        String packagename = properties.get( "root.package" ).replaceAll( "\\.", "/" ) + "/bootstrap/infrastructure/";
+        String classname = "FileConfigurationModule";
+        File projectDir = new File( properties.get( "project.dir" ) );
+        return new PrintWriter( new FileWriter( new File( projectDir, "bootstrap/src/main/java/" + packagename + classname + ".java" ) ) );
+    }
+}