Examples, documentation and minor fixes
TOMEE-2706 New TomEE Embedded Bootstrap
diff --git a/boms/tomee-microprofile/pom.xml b/boms/tomee-microprofile/pom.xml
index 59d75ae..2b6a17d 100644
--- a/boms/tomee-microprofile/pom.xml
+++ b/boms/tomee-microprofile/pom.xml
@@ -18,6 +18,16 @@
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  THIS FILE IS GENERATED, DO NOT MODIFY
+
+  This file is generated by inspecting the libraries in the server
+  distributions found in tomee/apache-tomee/target/apache-tomee-*.zip
+
+  Any improvements that might need to be made to this pom must go in
+  org.apache.tomee.bootstrap.GenerateBoms
+  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
   <parent>
     <groupId>org.apache.tomee.bom</groupId>
     <artifactId>boms</artifactId>
@@ -26,7 +36,7 @@
 
   <modelVersion>4.0.0</modelVersion>
   <artifactId>tomee-microprofile</artifactId>
-  <packaging>pom</packaging>
+
   <name>TomEE :: BOMs :: TomEE MicroProfile</name>
 
   <dependencies>
@@ -1171,7 +1181,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mbean-annotation-api</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1182,7 +1192,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mp-common</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1193,7 +1203,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mp-jwt</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
diff --git a/boms/tomee-plume/pom.xml b/boms/tomee-plume/pom.xml
index 8d90935..15ae016 100644
--- a/boms/tomee-plume/pom.xml
+++ b/boms/tomee-plume/pom.xml
@@ -18,6 +18,16 @@
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  THIS FILE IS GENERATED, DO NOT MODIFY
+
+  This file is generated by inspecting the libraries in the server
+  distributions found in tomee/apache-tomee/target/apache-tomee-*.zip
+
+  Any improvements that might need to be made to this pom must go in
+  org.apache.tomee.bootstrap.GenerateBoms
+  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
   <parent>
     <groupId>org.apache.tomee.bom</groupId>
     <artifactId>boms</artifactId>
@@ -26,7 +36,7 @@
 
   <modelVersion>4.0.0</modelVersion>
   <artifactId>tomee-plume</artifactId>
-  <packaging>pom</packaging>
+
   <name>TomEE :: BOMs :: TomEE Plume</name>
 
   <dependencies>
@@ -1237,7 +1247,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mbean-annotation-api</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1248,7 +1258,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mp-common</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1259,7 +1269,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mp-jwt</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
diff --git a/boms/tomee-plus/pom.xml b/boms/tomee-plus/pom.xml
index 810d4ac..5a00831 100644
--- a/boms/tomee-plus/pom.xml
+++ b/boms/tomee-plus/pom.xml
@@ -18,6 +18,16 @@
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  THIS FILE IS GENERATED, DO NOT MODIFY
+
+  This file is generated by inspecting the libraries in the server
+  distributions found in tomee/apache-tomee/target/apache-tomee-*.zip
+
+  Any improvements that might need to be made to this pom must go in
+  org.apache.tomee.bootstrap.GenerateBoms
+  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
   <parent>
     <groupId>org.apache.tomee.bom</groupId>
     <artifactId>boms</artifactId>
@@ -26,7 +36,7 @@
 
   <modelVersion>4.0.0</modelVersion>
   <artifactId>tomee-plus</artifactId>
-  <packaging>pom</packaging>
+
   <name>TomEE :: BOMs :: TomEE Plus</name>
 
   <dependencies>
@@ -1292,7 +1302,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mbean-annotation-api</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1303,7 +1313,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mp-common</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
@@ -1314,7 +1324,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mp-jwt</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
diff --git a/boms/tomee-webprofile/pom.xml b/boms/tomee-webprofile/pom.xml
index d791ccc..a6536c2 100644
--- a/boms/tomee-webprofile/pom.xml
+++ b/boms/tomee-webprofile/pom.xml
@@ -18,6 +18,16 @@
 
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
+  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  THIS FILE IS GENERATED, DO NOT MODIFY
+
+  This file is generated by inspecting the libraries in the server
+  distributions found in tomee/apache-tomee/target/apache-tomee-*.zip
+
+  Any improvements that might need to be made to this pom must go in
+  org.apache.tomee.bootstrap.GenerateBoms
+  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
   <parent>
     <groupId>org.apache.tomee.bom</groupId>
     <artifactId>boms</artifactId>
@@ -26,7 +36,7 @@
 
   <modelVersion>4.0.0</modelVersion>
   <artifactId>tomee-webprofile</artifactId>
-  <packaging>pom</packaging>
+
   <name>TomEE :: BOMs :: TomEE WebProfile</name>
 
   <dependencies>
@@ -874,7 +884,7 @@
     <dependency>
       <groupId>org.apache.tomee</groupId>
       <artifactId>mbean-annotation-api</artifactId>
-      <version>8.0.5-SNAPSHOT</version>
+      <version>${project.version}</version>
       <exclusions>
         <exclusion>
           <artifactId>*</artifactId>
diff --git a/examples/pom.xml b/examples/pom.xml
index f1eb404..e404c51 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -146,6 +146,11 @@
     <module>schedule-methods-meta</module>
     <module>schedule-methods</module>
     <module>server-events</module>
+    <module>serverless-builder</module>
+    <module>serverless-tomee-webprofile</module>
+<!--    <module>serverless-tomee-microprofile</module>-->
+<!--    <module>serverless-tomee-plume</module>-->
+<!--    <module>serverless-tomee-plus</module>-->
     <module>singleton-startup-ordering</module>
     <module>simple-cdi-interceptor</module>
     <module>simple-ear</module>
diff --git a/examples/serverless-builder/README.adoc b/examples/serverless-builder/README.adoc
new file mode 100644
index 0000000..f127dcc
--- /dev/null
+++ b/examples/serverless-builder/README.adoc
@@ -0,0 +1,210 @@
+:index-group: Serverless
+:jbake-type: page
+:jbake-status: status=published
+= Serverless Builder API
+
+The `Server.Builder` API allows you to build an embedded or serverless instance of Tomcat/TomEE inside your JVM, effectively running Tomcat/TomEE as a plain library.
+
+[source,java]
+----
+import org.apache.tomee.bootstrap.Server;
+
+public class Main {
+    public static void main(String[] args) {
+        final Server server = Server.builder().build();
+
+        System.out.println("Listening for requests at " + server.getURI());
+    }
+}
+----
+
+The design of the API might be best described as a functional-builder API (FBA) and effectively allows you to supply functions and method references that actually assist in the server building process.  Its through these functions that you can deploy applications, modify configurations and effectively run any code that you need that would help prepare the server instance.
+
+A high-level overview of the builder methods available after calling `Server.builder()` are as follows:
+
+[source,java]
+----
+public static class Builder
+    public Builder httpPort(final int port)
+    public Builder ajpPort(final int port)
+    public Builder add(final String name, final byte[] bytes)
+    public Builder add(final String name, final Supplier<byte[]> content)
+    public Builder add(final String name, final String content)
+    public Builder add(final String name, final File content)
+    public Builder add(final String name, final Archive contents)
+    public Builder home(final Consumer<File> customization)
+    public Builder and(final Consumer<Builder> consumer)
+    public Server build()
+----
+
+To really know how to use the API, we must first understand Tomcat's `catalina.home` and `catalina.base` concepts and what actually happens when we call `Server.builder().build()`
+
+
+=== Understanding Tomcat's home and base
+
+It's a little known fact that for decades Tomcat has had the ability to run several instances from a single Tomcat zip.  Tomcat uses a `catalina.home` variable to identify the location of the extracted zip where the server libraries can be found and a `catalina.base` per instance to define the location of that instance's configuration files, log files and webapps.
+
+In our situation, your JVM classpath is effectively the `catalina.home` and when we use the `Server` API we're creating a very thin `catalina.base` that holds the configuration files, log files and webapps for that built Server (Tomcat) instance.  If you use the `Server` API ten times in the same JVM, you will have 10 `catalina.base` directories.  These are considered temporary working locations, however, and will be deleted on JVM exit.
+
+=== Calling `Server.builder().build()`
+
+When the `build()` method of the `Server.Builder` is called the following actions are taken in this order:
+
+ 1. Any functions added via `and(final Consumer<Builder> consumer)` are executed.  This allows a function to be supplied that further modifies the builder just before any building is executed.  Several builder modifications can be wrapped into one function that installs them all.
+ 1. A temp directory is created that will serve as `catalina.home` and `catalina.base` and default configurations such as `server.xml`, `logging.properties`, and `tomee.xml` are copied in.
+ 1. Any functions added via `add(final String destinationPath, final Supplier<byte[]> content)` are executed and any supplied bytes, Strings or Files are written to the `destinationPath` inside the temp directory.  This allows the default configurations like `server.xml` to be overwritten or applications to be written to the `webapps/` directory.
+ 1. Ports are set by modifying the `conf/server.xml`.  If `httpPort` was not set, ports will be random.
+ 1. Any functions added via `home(final Consumer<File> customization)` are executed.  The temp directory will be supplied as the value of `File`.
+ 1. The Tomcat/TomEE instance is started and returned as an instance of `Server`
+
+=== Seeing the Result of `Server.builder().build()`
+
+It helps greatly to be able to see what was built.  We can do that by installing a function or method reference like the one below.
+
+[source,java]
+----
+import org.apache.tomee.bootstrap.Server;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+
+public class Main {
+
+    public static void main(String[] args) {
+        Server.builder()
+                .home(Main::list)
+                .build();
+    }
+
+    private static void list(final File home) {
+        try {
+            Files.walk(home.toPath())
+                    .sorted()
+                    .forEach(System.out::println);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+}
+----
+
+When we run that we should see output similar to the following:
+
+[source,console]
+----
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/catalina.policy
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/catalina.properties
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/context.xml
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/jaspic-providers.xml
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/jaspic-providers.xsd
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/logging.properties
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/server.xml
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/system.properties
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/tomcat-users.xml
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/tomcat-users.xsd
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/tomee.xml
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/conf/web.xml
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/logs
+/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp9107162877421339516dir/apache-tomee/webapps
+----
+
+The above represents what comes out of the box from calling `Server.builder().build()` with no modifications.
+
+== Creating Apps with `Archive`
+
+The second class to learn is `Archive` and is essentially a no-frills app builder.  With this approach all your classes are effectively already in the classpath and visible, so ultimately the only classes that need to be included are annotated Servlets, EJBs, CDI Beans, JAX-RS classes, etc.
+
+[source,java]
+----
+public class Archive
+    public static Archive archive()
+    public Archive manifest(final String key, final Object value)
+    public Archive manifest(final String key, final Class value)
+    public Archive add(final String name, final byte[] bytes)
+    public Archive add(final String name, final Supplier<byte[]> content)
+    public Archive add(final String name, final String content)
+    public Archive add(final String name, final File content)
+    public Archive add(final String name, final Archive archive)
+    public Archive add(final String name, final URL content)
+    public Archive add(final Class<?> clazz)
+    public Archive addDir(final File dir)
+    public Archive addJar(final File file)
+    public File toJar()
+    public File toJar(final File file)
+    public File toDir()
+    public void toDir(final File dir)
+----
+
+NOTE: You can use APIs like ShrinkWrap to build the jars and war files as an alternative to `Archive`.  Anything that can produce a jar file, war file or an exploded (unzipped) war directory structure will work.
+
+=== Creating a ROOT war
+
+In this example we are effectively adding three classes to an `Archive` which is itself added to a new `webapps/ROOT/WEB-INF/classes` directory.
+
+[source,java]
+----
+import org.apache.tomee.bootstrap.Archive;
+import org.apache.tomee.bootstrap.Server;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+
+public class Main {
+
+    public static void main(String[] args) {
+
+        final Server server = Server.builder()
+                .add("webapps/ROOT/WEB-INF/classes", Archive.archive()
+                        .add(Api.class)
+                        .add(Movie.class)
+                        .add(MovieService.class))
+                .home(Main::list)
+                .build();
+
+        System.out.println("Listening for requests at " + server.getURI());
+    }
+
+    private static void list(final File home) {
+        try {
+            Files.walk(home.toPath())
+                    .map(Path::toFile)
+                    .filter(File::isFile)
+                    .map(File::getAbsolutePath)
+                    .map(s -> "..." + s.substring(49))
+                    .sorted()
+                    .forEach(System.out::println);
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+}
+----
+
+When this runs we'll see out `Main.list` method which executes just before server start will have printed the following:
+
+[source,console]
+----
+...temp710654453954858189dir/apache-tomee/conf/catalina.policy
+...temp710654453954858189dir/apache-tomee/conf/catalina.properties
+...temp710654453954858189dir/apache-tomee/conf/context.xml
+...temp710654453954858189dir/apache-tomee/conf/jaspic-providers.xml
+...temp710654453954858189dir/apache-tomee/conf/jaspic-providers.xsd
+...temp710654453954858189dir/apache-tomee/conf/logging.properties
+...temp710654453954858189dir/apache-tomee/conf/server.xml
+...temp710654453954858189dir/apache-tomee/conf/system.properties
+...temp710654453954858189dir/apache-tomee/conf/tomcat-users.xml
+...temp710654453954858189dir/apache-tomee/conf/tomcat-users.xsd
+...temp710654453954858189dir/apache-tomee/conf/tomee.xml
+...temp710654453954858189dir/apache-tomee/conf/web.xml
+...temp710654453954858189dir/apache-tomee/webapps/ROOT/WEB-INF/classes/org/superbiz/movie/Api.class
+...temp710654453954858189dir/apache-tomee/webapps/ROOT/WEB-INF/classes/org/superbiz/movie/Movie.class
+...temp710654453954858189dir/apache-tomee/webapps/ROOT/WEB-INF/classes/org/superbiz/movie/MovieService.class
+----
\ No newline at end of file
diff --git a/examples/serverless-builder/pom.xml b/examples/serverless-builder/pom.xml
new file mode 100644
index 0000000..d8c85e9
--- /dev/null
+++ b/examples/serverless-builder/pom.xml
@@ -0,0 +1,74 @@
+<?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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.superbiz</groupId>
+  <artifactId>serverless-builder</artifactId>
+  <version>8.0.5-SNAPSHOT</version>
+
+  <name>TomEE :: Examples :: Serverless Apache TomEE WebProfile</name>
+  
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <version.tomee>8.0.5-SNAPSHOT</version.tomee>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.tomee.bom</groupId>
+      <artifactId>tomee-webprofile</artifactId>
+      <version>${version.tomee}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.5.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <!--
+  This section allows you to configure where to publish libraries for sharing.
+  It is not required and may be deleted.  For more information see:
+  http://maven.apache.org/plugins/maven-deploy-plugin/
+  -->
+  <distributionManagement>
+    <repository>
+      <id>localhost</id>
+      <url>file://${basedir}/target/repo/</url>
+    </repository>
+    <snapshotRepository>
+      <id>localhost</id>
+      <url>file://${basedir}/target/snapshot-repo/</url>
+    </snapshotRepository>
+  </distributionManagement>
+</project>
diff --git a/examples/serverless-builder/src/main/java/org/superbiz/movie/Api.java b/examples/serverless-builder/src/main/java/org/superbiz/movie/Api.java
new file mode 100644
index 0000000..a7c43d3
--- /dev/null
+++ b/examples/serverless-builder/src/main/java/org/superbiz/movie/Api.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.superbiz.movie;
+
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.core.Application;
+
+@ApplicationPath("/api")
+public class Api extends Application {
+}
diff --git a/examples/serverless-builder/src/main/java/org/superbiz/movie/Movie.java b/examples/serverless-builder/src/main/java/org/superbiz/movie/Movie.java
new file mode 100644
index 0000000..450959b
--- /dev/null
+++ b/examples/serverless-builder/src/main/java/org/superbiz/movie/Movie.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.superbiz.movie;
+
+public class Movie {
+
+    private String title;
+    private String director;
+    private String genre;
+    private int id;
+    private int year;
+
+    public Movie() {
+    }
+
+    public Movie(final String title, final String director, final String genre, final int id, final int year) {
+        this.title = title;
+        this.director = director;
+        this.genre = genre;
+        this.id = id;
+        this.year = year;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+
+    public String getDirector() {
+        return director;
+    }
+
+    public void setDirector(final String director) {
+        this.director = director;
+    }
+
+    public String getGenre() {
+        return genre;
+    }
+
+    public void setGenre(final String genre) {
+        this.genre = genre;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(final int id) {
+        this.id = id;
+    }
+
+    public int getYear() {
+        return year;
+    }
+
+    public void setYear(final int year) {
+        this.year = year;
+    }
+}
diff --git a/examples/serverless-builder/src/main/java/org/superbiz/movie/MovieService.java b/examples/serverless-builder/src/main/java/org/superbiz/movie/MovieService.java
new file mode 100644
index 0000000..b8acbc2
--- /dev/null
+++ b/examples/serverless-builder/src/main/java/org/superbiz/movie/MovieService.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.superbiz.movie;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.RequestScoped;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Path("/movies")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestScoped
+public class MovieService {
+
+    private Map<Integer, Movie> store = new ConcurrentHashMap<>();
+
+    @PostConstruct
+    public void construct(){
+        this.addMovie(new Movie("Wedding Crashers", "David Dobkin", "Comedy", 1, 2005));
+        this.addMovie(new Movie("Starsky & Hutch", "Todd Phillips", "Action", 2, 2004));
+        this.addMovie(new Movie("Shanghai Knights", "David Dobkin", "Action", 3, 2003));
+        this.addMovie(new Movie("I-Spy", "Betty Thomas", "Adventure", 4, 2002));
+        this.addMovie(new Movie("The Royal Tenenbaums", "Wes Anderson", "Comedy", 5, 2001));
+        this.addMovie(new Movie("Zoolander", "Ben Stiller", "Comedy", 6, 2001));
+    }
+    @GET
+    public List<Movie> getAllMovies() {
+        return new ArrayList<>(store.values());
+    }
+
+    @POST
+    public Movie addMovie(final Movie newMovie) {
+        store.put(newMovie.getId(), newMovie);
+        return newMovie;
+    }
+
+}
diff --git a/examples/serverless-builder/src/test/java/org/superbiz/movie/MovieServiceTest.java b/examples/serverless-builder/src/test/java/org/superbiz/movie/MovieServiceTest.java
new file mode 100644
index 0000000..08b5a69
--- /dev/null
+++ b/examples/serverless-builder/src/test/java/org/superbiz/movie/MovieServiceTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.superbiz.movie;
+
+import org.apache.tomee.bootstrap.Archive;
+import org.apache.tomee.bootstrap.Server;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import java.net.URI;
+
+import static javax.ws.rs.client.Entity.entity;
+import static org.junit.Assert.assertEquals;
+
+public class MovieServiceTest {
+
+    private static URI serverURI;
+
+    @BeforeClass
+    public static void setup() {
+        // Add any classes you need to an Archive
+        // or add them to a jar via any means
+        final Archive classes = Archive.archive()
+                .add(Api.class)
+                .add(Movie.class)
+                .add(MovieService.class);
+
+        // Place the classes where you would want
+        // them in a Tomcat install
+        final Server server = Server.builder()
+                // This effectively creates a webapp called ROOT
+                .add("webapps/ROOT/WEB-INF/classes", classes)
+                .build();
+
+        serverURI = server.getURI();
+    }
+
+    @Test
+    public void getAllMovies() {
+        final WebTarget target = ClientBuilder.newClient().target(serverURI);
+
+        final Movie[] movies = target.path("/api/movies").request().get(Movie[].class);
+
+        assertEquals(6, movies.length);
+
+        final Movie movie = movies[1];
+        assertEquals("Todd Phillips", movie.getDirector());
+        assertEquals("Starsky & Hutch", movie.getTitle());
+        assertEquals("Action", movie.getGenre());
+        assertEquals(2004, movie.getYear());
+        assertEquals(2, movie.getId());
+    }
+
+    @Test
+    public void addMovie() {
+        final WebTarget target = ClientBuilder.newClient().target(serverURI);
+
+        final Movie movie = new Movie("Shanghai Noon", "Tom Dey", "Comedy", 7, 2000);
+
+        final Movie posted = target.path("/api/movies").request()
+                .post(entity(movie, MediaType.APPLICATION_JSON))
+                .readEntity(Movie.class);
+
+        assertEquals("Tom Dey", posted.getDirector());
+        assertEquals("Shanghai Noon", posted.getTitle());
+        assertEquals("Comedy", posted.getGenre());
+        assertEquals(2000, posted.getYear());
+        assertEquals(7, posted.getId());
+    }
+}
diff --git a/examples/serverless-tomee-microprofile/README.adoc b/examples/serverless-tomee-microprofile/README.adoc
new file mode 100644
index 0000000..4a6a942
--- /dev/null
+++ b/examples/serverless-tomee-microprofile/README.adoc
@@ -0,0 +1,168 @@
+:index-group: Serverless
+:jbake-type: page
+:jbake-status: status=published
+= Serverless TomEE MicroProfile
+
+Apache TomEE can be run as a library inside your JVM with no need for separate processes or a standalone server install.  In this approach we include the right libraries in our project and then bootstrap TomEE using the `Server.Builder` API.
+
+== Include the `tomee-microprofile` dependency
+
+To make things as easy as possible there is just one dependency that will give you a classpath that is 100% identical to your favorite Apache TomEE distribution.  The following dependency will pull give you an environment identical to an Apache TomEE MicroProfile binary distribution.
+
+[source,xml]
+----
+<dependency>
+  <groupId>org.apache.tomee.bom</groupId>
+  <artifactId>tomee-microprofile</artifactId>
+  <version>${version.tomee}</version>
+</dependency>
+----
+
+NOTE: The `org.apache.tomee.bom:tomee-microprofile` is actually generated by analyzing the apache-tomee-microprofile-x.y.z.zip, so is guaranteed to be 100% identical making it easy to transition from a zip file to a simple maven dependency.
+
+== Write Regular Code
+
+Here we see a simple JAX-RS API for sending/recieving `Movie` objects as JSON.
+
+[source,java]
+----
+@Path("/movies")
+@Produces(MediaType.APPLICATION_JSON)
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestScoped
+public class MovieService {
+
+    private Map<Integer, Movie> store = new ConcurrentHashMap<>();
+
+    @PostConstruct
+    public void construct(){
+        this.addMovie(new Movie("Wedding Crashers", "David Dobkin", "Comedy", 1, 2005));
+        this.addMovie(new Movie("Starsky & Hutch", "Todd Phillips", "Action", 2, 2004));
+        this.addMovie(new Movie("Shanghai Knights", "David Dobkin", "Action", 3, 2003));
+        this.addMovie(new Movie("I-Spy", "Betty Thomas", "Adventure", 4, 2002));
+        this.addMovie(new Movie("The Royal Tenenbaums", "Wes Anderson", "Comedy", 5, 2001));
+        this.addMovie(new Movie("Zoolander", "Ben Stiller", "Comedy", 6, 2001));
+    }
+    @GET
+    public List<Movie> getAllMovies() {
+        return new ArrayList<>(store.values());
+    }
+
+    @POST
+    public Movie addMovie(final Movie newMovie) {
+        store.put(newMovie.getId(), newMovie);
+        return newMovie;
+    }
+
+}
+----
+
+== Bootstrap TomEE with the Server Builder
+
+A this point we have a Maven project with the right dependencies and some application code in our project.  From here we use the `Server.Builder` API to construct a `Server` instance inside our JVM.
+
+Here we see a simple Main class that bootstraps a `Server` instance on port `8080` and blocks:
+
+[source,java]
+----
+import org.apache.tomee.bootstrap.Archive;
+import org.apache.tomee.bootstrap.Server;
+
+import java.util.concurrent.Semaphore;
+
+public class Main {
+    public static void main(String[] args) throws InterruptedException {
+
+        final Server server = Server.builder()
+                .httpPort(8080)
+                .add("webapps/ROOT/WEB-INF/classes", Archive.archive()
+                        .add(Api.class)
+                        .add(Movie.class)
+                        .add(MovieService.class))
+                .build();
+
+        System.out.println("Listening for requests at " + server.getURI());
+        new Semaphore(0).acquire();
+    }
+}
+----
+
+The example below bootstraps a `Server` instance on random ports inside a test case and exits when the test case is complete:
+
+[source,java]
+----
+import org.apache.tomee.bootstrap.Archive;
+import org.apache.tomee.bootstrap.Server;
+//...
+
+public class MovieServiceTest {
+
+    private static URI serverURI;
+
+    @BeforeClass
+    public static void setup() {
+        // Add any classes you need to an Archive
+        // or add them to a jar via any means
+        final Archive classes = Archive.archive()
+                .add(Api.class)
+                .add(Movie.class)
+                .add(MovieService.class);
+
+        // Place the classes where you would want
+        // them in a Tomcat install
+        final Server server = Server.builder()
+                // This effectively creates a webapp called ROOT
+                .add("webapps/ROOT/WEB-INF/classes", classes)
+                .build();
+
+        serverURI = server.getURI();
+    }
+
+    @Test
+    public void getAllMovies() {
+        final WebTarget target = ClientBuilder.newClient().target(serverURI);
+
+        final Movie[] movies = target.path("/api/movies").request().get(Movie[].class);
+
+        assertEquals(6, movies.length);
+
+        final Movie movie = movies[1];
+        assertEquals("Todd Phillips", movie.getDirector());
+        assertEquals("Starsky & Hutch", movie.getTitle());
+        assertEquals("Action", movie.getGenre());
+        assertEquals(2004, movie.getYear());
+        assertEquals(2, movie.getId());
+    }
+}
+----
+
+In the above code we have assembled the classes `Api`, `Movie` and `MovieService` into a virtual archive, then we add that archive into a virtual Tomcat install at the location `webapps/ROOT/WEB-INF/classes`.  When we call `build()` the Tomcat server instance is started in our JVM and will begin serving HTTP requests at the host/port identified by `server.getURI()`
+
+In short, we've bootstrapped a Tomcat server in our JVM that has a very tiny disk footprint; three classes and a handful of default configuration files.
+
+== Running
+
+Were we to run the above Main class or Test Case we'd see output like the following:
+
+[source,bash]
+----
+Sep 03, 2020 8:41:29 AM org.apache.openejb.server.cxf.rs.CxfRsHttpListener deployApplication
+INFO:      org.apache.cxf.jaxrs.validation.ValidationExceptionMapper@2d313c8c
+Sep 03, 2020 8:41:29 AM org.apache.openejb.server.cxf.rs.CxfRsHttpListener logEndpoints
+INFO: REST Application: http://localhost:8080/api        -> org.superbiz.movie.Api@6b2dd3df
+Sep 03, 2020 8:41:29 AM org.apache.openejb.server.cxf.rs.CxfRsHttpListener logEndpoints
+INFO:      Service URI: http://localhost:8080/api/movies -> Pojo org.superbiz.movie.MovieService
+Sep 03, 2020 8:41:29 AM org.apache.openejb.server.cxf.rs.CxfRsHttpListener logEndpoints
+INFO:               GET http://localhost:8080/api/movies ->      List<Movie> getAllMovies()
+Sep 03, 2020 8:41:29 AM org.apache.openejb.server.cxf.rs.CxfRsHttpListener logEndpoints
+INFO:              POST http://localhost:8080/api/movies ->      Movie addMovie(Movie)     
+Sep 03, 2020 8:41:29 AM jdk.internal.reflect.DelegatingMethodAccessorImpl invoke
+INFO: Deployment of web application directory [/private/var/folders/bd/f9ntqy1m8xj_fs006s6crtjh0000gn/T/temp14966428831095231081dir/apache-tomee/webapps/ROOT] has finished in [1,798] ms
+Sep 03, 2020 8:41:29 AM jdk.internal.reflect.DelegatingMethodAccessorImpl invoke
+INFO: Starting ProtocolHandler ["http-nio-8080"]
+Sep 03, 2020 8:41:29 AM jdk.internal.reflect.DelegatingMethodAccessorImpl invoke
+INFO: Server startup in [1877] milliseconds
+Sep 03, 2020 8:41:29 AM jdk.internal.reflect.DelegatingMethodAccessorImpl invoke
+INFO: Full bootstrap in [3545] milliseconds
+Listening for requests at http://localhost:8080
+----
diff --git a/examples/serverless-tomee-microprofile/pom.xml b/examples/serverless-tomee-microprofile/pom.xml
new file mode 100644
index 0000000..005fc60
--- /dev/null
+++ b/examples/serverless-tomee-microprofile/pom.xml
@@ -0,0 +1,74 @@
+<?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/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.superbiz</groupId>
+  <artifactId>serverless-tomee-microprofile</artifactId>
+  <version>8.0.5-SNAPSHOT</version>
+
+  <name>TomEE :: Examples :: Serverless Apache TomEE MicroProfile</name>
+  
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <version.tomee>8.0.5-SNAPSHOT</version.tomee>
+  </properties>
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.tomee.bom</groupId>
+      <artifactId>tomee-microprofile</artifactId>
+      <version>${version.tomee}</version>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.12</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.5.1</version>
+        <configuration>
+          <source>1.8</source>
+          <target>1.8</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <!--
+  This section allows you to configure where to publish libraries for sharing.
+  It is not required and may be deleted.  For more information see:
+  http://maven.apache.org/plugins/maven-deploy-plugin/
+  -->
+  <distributionManagement>
+    <repository>
+      <id>localhost</id>
+      <url>file://${basedir}/target/repo/</url>
+    </repository>
+    <snapshotRepository>
+      <id>localhost</id>
+      <url>file://${basedir}/target/snapshot-repo/</url>
+    </snapshotRepository>
+  </distributionManagement>
+</project>
diff --git a/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Archive.java b/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Archive.java
index 418650c..accf82c 100644
--- a/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Archive.java
+++ b/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Archive.java
@@ -25,6 +25,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.net.URL;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -32,6 +33,7 @@
 import java.util.function.Supplier;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
@@ -69,10 +71,21 @@
     }
 
     public Archive add(final String name, final File content) {
+        if (content.isDirectory()) {
+            return addDir(name, content);
+        }
         return add(name, () -> readBytes(content));
     }
 
-    public static byte[] readBytes(final File content) {
+    public Archive add(final String name, final Archive archive) {
+        this.manifest.putAll(archive.manifest);
+        for (final Map.Entry<String, Supplier<byte[]>> entry : archive.entries.entrySet()) {
+            this.entries.put(name + "/" + entry.getKey(), entry.getValue());
+        }
+        return this;
+    }
+
+    private static byte[] readBytes(final File content) {
         try {
             return IO.readBytes(content);
         } catch (IOException e) {
@@ -80,45 +93,39 @@
         }
     }
 
-    public static byte[] readBytes(final URL content) {
+    public Archive add(final String name, final URL content) {
         try {
-            return IO.readBytes(content);
+            return add(name, IO.readBytes(content));
         } catch (IOException e) {
-            throw new IllegalStateException(e);
+            throw new UncheckedIOException(e);
         }
     }
 
-    public Archive add(final String name, final URL content) throws IOException {
-        return add(name, IO.readBytes(content));
-    }
-
     public Archive add(final Class<?> clazz) {
-        try {
-            final String name = clazz.getName().replace('.', '/') + ".class";
+        final String name = clazz.getName().replace('.', '/') + ".class";
 
-            final URL resource = this.getClass().getClassLoader().getResource(name);
+        final URL resource = this.getClass().getClassLoader().getResource(name);
+        if (resource == null) throw new IllegalStateException("Cannot find class file for " + clazz.getName());
+        add(name, resource);
 
-            if (resource == null) throw new IllegalStateException("Cannot find class file for " + clazz.getName());
-
-            return add(name, resource);
-        } catch (final IOException e) {
-            throw new IllegalStateException(e);
+        // Add any parent classes needed
+        if (!clazz.isAnonymousClass() && clazz.getDeclaringClass() != null) {
+            add(clazz.getDeclaringClass());
         }
-    }
 
-    public Archive addDir(final File dir) {
-        try {
-
-            addDir(null, dir);
-
-        } catch (final IOException e) {
-            throw new IllegalStateException(e);
-        }
+        // Add any anonymous nested classes
+        Stream.of(clazz.getDeclaredClasses())
+                .filter(Class::isAnonymousClass)
+                .forEach(this::add);
 
         return this;
     }
 
-    private void addDir(final String path, final File dir) throws IOException {
+    public Archive addDir(final File dir) {
+        return addDir(null, dir);
+    }
+
+    private Archive addDir(final String path, final File dir) {
         for (final File file : dir.listFiles()) {
 
             final String childPath = (path != null) ? path + "/" + file.getName() : file.getName();
@@ -129,6 +136,7 @@
                 addDir(childPath, file);
             }
         }
+        return this;
     }
 
     public Archive addJar(final File file) {
@@ -148,36 +156,34 @@
         }
     }
 
-    public File toJar() throws IOException {
-        final File file = File.createTempFile("archive-", ".jar");
+    public File toJar() {
+        final File file;
+        try {
+            file = File.createTempFile("archive-", ".jar");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
         file.deleteOnExit();
 
         return toJar(file);
     }
 
-    public File toJar(final File file) throws IOException {
+    public File toJar(final File file) {
         // Create the ZIP file
-        final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
-
-        for (final Map.Entry<String, Supplier<byte[]>> entry : entries().entrySet()) {
-            out.putNextEntry(new ZipEntry(entry.getKey()));
-            out.write(entry.getValue().get());
-        }
-
-        // Complete the ZIP file
-        out.close();
-        return file;
-    }
-
-    public File asJar() {
         try {
-            return toJar();
-        } catch (final IOException e) {
-            throw new RuntimeException(e);
+            try (final ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
+                for (final Map.Entry<String, Supplier<byte[]>> entry : entries().entrySet()) {
+                    out.putNextEntry(new ZipEntry(entry.getKey()));
+                    out.write(entry.getValue().get());
+                }
+            }
+            return file;
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
         }
     }
 
-    public File toDir() throws IOException {
+    public File toDir() {
 
         final File classpath = Files.tmpdir();
 
@@ -186,7 +192,7 @@
         return classpath;
     }
 
-    public void toDir(final File dir) throws IOException {
+    public void toDir(final File dir) {
         Files.exists(dir);
         Files.dir(dir);
         Files.writable(dir);
@@ -207,17 +213,11 @@
         }
     }
 
-    public File asDir() {
-        try {
-            return toDir();
-        } catch (final IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     private HashMap<String, Supplier<byte[]>> entries() {
         final HashMap<String, Supplier<byte[]>> entries = new HashMap<>(this.entries);
-        entries.put("META-INF/MANIFEST.MF", buildManifest()::getBytes);
+        if (manifest.size() > 0) {
+            entries.put("META-INF/MANIFEST.MF", buildManifest()::getBytes);
+        }
         return entries;
     }
 
diff --git a/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Server.java b/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Server.java
index 7360e54..348f1f8 100644
--- a/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Server.java
+++ b/tomee/tomee-bootstrap/src/main/java/org/apache/tomee/bootstrap/Server.java
@@ -31,21 +31,14 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
 public class Server {
 
-    public static void main(String[] args) {
-        final Server server = Server.builder().build();
-        System.out.println(server.toURI());
-    }
-
     private static final Log log = LogFactory.getLog(Server.class);
 
     private final File home;
@@ -56,7 +49,7 @@
         this.uri = URI.create("http://localhost:" + port);
     }
 
-    public URI toURI() {
+    public URI getURI() {
         return uri;
     }
 
@@ -125,7 +118,6 @@
         private int ajpPort;
         protected final ArrayList<Consumer<File>> homeConsumers = new ArrayList<>();
         protected final ArrayList<Consumer<Builder>> builderConsumers = new ArrayList<>();
-        protected final Map<String, String> env = new HashMap<>();
         protected final Archive modifications = Archive.archive();
 
         public Builder httpPort(final int port) {
@@ -143,23 +135,28 @@
             return this;
         }
 
-        public Builder add(final String name, final byte[] bytes) {
-            modifications.add(name, bytes);
+        public Builder add(final String destinationPath, final byte[] bytes) {
+            modifications.add(destinationPath, bytes);
             return this;
         }
 
-        public Builder add(final String name, final Supplier<byte[]> content) {
-            modifications.add(name, content);
+        public Builder add(final String destinationPath, final Supplier<byte[]> content) {
+            modifications.add(destinationPath, content);
             return this;
         }
 
-        public Builder add(final String name, final String content) {
-            modifications.add(name, content);
+        public Builder add(final String destinationPath, final String content) {
+            modifications.add(destinationPath, content);
             return this;
         }
 
-        public Builder add(final String name, final File content) {
-            modifications.add(name, content);
+        public Builder add(final String destinationPath, final File content) {
+            modifications.add(destinationPath, content);
+            return this;
+        }
+
+        public Builder add(final String name, final Archive contents) {
+            modifications.add(name, contents);
             return this;
         }
 
@@ -184,8 +181,8 @@
             // copy user files
             try {
                 modifications.toDir(home);
-            } catch (IOException e) {
-                throw new UncheckedIOException("Failed to apply home modifications to " + home.getAbsolutePath(), e);
+            } catch (Exception e) {
+                throw new IllegalStateException("Failed to apply home modifications to " + home.getAbsolutePath(), e);
             }
         }
 
@@ -201,13 +198,9 @@
             applyBuilderConsumers();
 
             final File home = Files.mkdir(Files.tmpdir(), "apache-tomee");
-            final File bin = Files.mkdir(home, "bin");
             final File conf = Files.mkdir(home, "conf");
-            final File lib = Files.mkdir(home, "lib");
             final File logs = Files.mkdir(home, "logs");
-            final File temp = Files.mkdir(home, "temp");
             final File webapps = Files.mkdir(home, "webapps");
-            final File work = Files.mkdir(home, "work");
 
             cp(conf, "catalina.policy");
             cp(conf, "catalina.properties");
diff --git a/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/ArchiveTest.java b/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/ArchiveTest.java
new file mode 100644
index 0000000..ec68c61
--- /dev/null
+++ b/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/ArchiveTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.tomee.bootstrap;
+
+import org.apache.openejb.loader.IO;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Copied with permission from tomitribe-util
+ */
+public class ArchiveTest {
+
+    @Test
+    public void addString() throws IOException {
+        final Archive archive = new Archive()
+                .add("colors/red.txt", "crimson")
+                .add("colors/green/emerald.txt", "#50c878");
+
+        final File dir = archive.toDir();
+
+        assertTrue(dir.isDirectory());
+        assertEquals(1, dir.listFiles().length);
+        assertEquals("colors", dir.listFiles()[0].getName());
+        assertFile(dir, "colors/red.txt", "crimson");
+        assertFile(dir, "colors/green/emerald.txt", "#50c878");
+    }
+
+    @Test
+    public void addArchive() throws IOException {
+
+        final Archive nested = new Archive()
+                .add("red.txt", "crimson")
+                .add("green/emerald.txt", "#50c878");
+        final Archive archive = new Archive();
+        archive.add("colors", nested);
+        final File dir = archive.toDir();
+
+        assertTrue(dir.isDirectory());
+        assertEquals(1, dir.listFiles().length);
+        assertEquals("colors", dir.listFiles()[0].getName());
+        assertFile(dir, "colors/red.txt", "crimson");
+        assertFile(dir, "colors/green/emerald.txt", "#50c878");
+    }
+
+    /**
+     * When adding an inner class we must also add the parent as the child
+     * cannot be loaded without the parent class
+     */
+    @Test
+    public void addInnerClass() throws IOException {
+
+        final Archive archive = new Archive().add(MomINeedYou.class);
+        final File dir = archive.toDir();
+
+        assertTrue(dir.isDirectory());
+        assertEquals(1, dir.listFiles().length);
+        assertEquals("org", dir.listFiles()[0].getName());
+
+        final File parent = new File(dir, "org/apache/tomee/bootstrap/ArchiveTest.class");
+        final File child = new File(dir, "org/apache/tomee/bootstrap/ArchiveTest$MomINeedYou.class");
+        assertTrue(parent.exists());
+        assertTrue(child.exists());
+    }
+
+    private static void assertFile(final File dir, final String name, final String expected) throws IOException {
+        final File file = new File(dir, name);
+        assertTrue(name, file.exists());
+        assertEquals(expected, IO.slurp(file));
+    }
+
+    /**
+     * Inner classes cannot be loaded without their parent,
+     * so we must always include the parent by default
+     */
+    public static class MomINeedYou {
+
+    }
+}
\ No newline at end of file
diff --git a/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/GenerateBoms.java b/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/GenerateBoms.java
index dd45aec..3407522 100644
--- a/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/GenerateBoms.java
+++ b/tomee/tomee-bootstrap/src/test/java/org/apache/tomee/bootstrap/GenerateBoms.java
@@ -141,7 +141,9 @@
                 .filter(distribution -> distribution.getMissing().size() > 0)
                 .collect(Collectors.toList());
 
-        throw new IncompleteMappingException(incomplete);
+        if (incomplete.size() > 0) {
+            throw new IncompleteMappingException(incomplete);
+        }
     }
 
     /**
@@ -400,17 +402,15 @@
                 return new Artifact("org.apache.tomee", "openejb-javaagent", "${project.version}");
             }
 
-            if (jar.getName().startsWith("openejb-")) {
+            if (jar.getName().startsWith("openejb-") ||
+                    jar.getName().startsWith("tomee-") ||
+                    jar.getName().startsWith("mp-common-") ||
+                    jar.getName().startsWith("mp-jwt-") ||
+                    jar.getName().startsWith("mbean-annotation-")) {
                 final String artifact = jar.getName().replaceAll("-8.0.*", "");
                 return new Artifact("org.apache.tomee", artifact, "${project.version}");
             }
 
-            if (jar.getName().startsWith("tomee-")) {
-                final String artifact = jar.getName().replaceAll("-8.0.*", "");
-                return new Artifact("org.apache.tomee", artifact, "${project.version}");
-            }
-
-
             // /Users/dblevins/.m2/repository//org/apache/xbean/xbean-naming/4.14/xbean-naming-4.14.jar
             final File file = getFile(jar);
             final File versionDir = file.getParentFile();
diff --git a/tomee/tomee-bootstrap/src/test/resources/pom-template.xml b/tomee/tomee-bootstrap/src/test/resources/pom-template.xml
index f20e82e..d357b9f 100644
--- a/tomee/tomee-bootstrap/src/test/resources/pom-template.xml
+++ b/tomee/tomee-bootstrap/src/test/resources/pom-template.xml
@@ -36,7 +36,7 @@
 
   <modelVersion>4.0.0</modelVersion>
   <artifactId>tomee-microprofile</artifactId>
-  <packaging>pom</packaging>
+
   <name>TomEE :: BOMs :: TomEE MicroProfile</name>
 
   <dependencies>