title: Gretty build fails with SpringBoot
body: <p>I'm building out a REST API for a personal project (project name: no-hold), built in Java.
  I'm using Spring Boot and Jetty to do so, and deploying it onto Google App Engine as a WAR.</p>
  
  <p>However, when I attempt to run <code>mvn jetty:run-exploded</code>, I get the following error:</p>
  
  <pre><code>[INFO] --- jetty-maven-plugin:9.4.3.v20170317:run-exploded (default-cli) @ no-hold ---
      [INFO] Configuring Jetty for project: no-hold
      [INFO] Logging initialized @3732ms to org.eclipse.jetty.util.log.Slf4jLog
      [INFO] Context path = /
      [INFO] Tmp directory = /Users/lucasjohnston/code/no-hold/target/tmp
      [INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
      [INFO] Web overrides =  none
      [INFO] jetty-9.4.3.v20170317
      [INFO] Scanning elapsed time=575ms
      [WARNING] Failed startup of context o.e.j.m.p.JettyWebAppContext@3c0bbc9f{/,file:///Users/lucasjohnston/code/no-hold/target/no-hold-1.0-SNAPSHOT/,UNAVAILABLE}{/Users/lucasjohnston/code/no-hold/target/no-hold-1.0-SNAPSHOT}
      org.eclipse.jetty.util.MultiException: Multiple exceptions
          at org.eclipse.jetty.annotations.AnnotationConfiguration.scanForAnnotations (AnnotationConfiguration.java:452)
          at org.eclipse.jetty.annotations.AnnotationConfiguration.configure (AnnotationConfiguration.java:365)
          at org.eclipse.jetty.webapp.WebAppContext.configure (WebAppContext.java:512)
          at org.eclipse.jetty.webapp.WebAppContext.startContext (WebAppContext.java:1437)
          at org.eclipse.jetty.server.handler.ContextHandler.doStart (ContextHandler.java:799)
          at org.eclipse.jetty.servlet.ServletContextHandler.doStart (ServletContextHandler.java:261)
          at org.eclipse.jetty.webapp.WebAppContext.doStart (WebAppContext.java:540)
          at org.eclipse.jetty.maven.plugin.JettyWebAppContext.doStart (JettyWebAppContext.java:432)
          at org.eclipse.jetty.util.component.AbstractLifeCycle.start (AbstractLifeCycle.java:68)
          at org.eclipse.jetty.util.component.ContainerLifeCycle.start (ContainerLifeCycle.java:131)
          at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart (ContainerLifeCycle.java:113)
          at org.eclipse.jetty.server.handler.AbstractHandler.doStart (AbstractHandler.java:113)
          at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart (ContextHandlerCollection.java:161)
          at org.eclipse.jetty.util.component.AbstractLifeCycle.start (AbstractLifeCycle.java:68)
          at org.eclipse.jetty.util.component.ContainerLifeCycle.start (ContainerLifeCycle.java:131)
          at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart (ContainerLifeCycle.java:113)
          at org.eclipse.jetty.server.handler.AbstractHandler.doStart (AbstractHandler.java:113)
          at org.eclipse.jetty.util.component.AbstractLifeCycle.start (AbstractLifeCycle.java:68)
          at org.eclipse.jetty.util.component.ContainerLifeCycle.start (ContainerLifeCycle.java:131)
          at org.eclipse.jetty.server.Server.start (Server.java:452)
          at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart (ContainerLifeCycle.java:105)
          at org.eclipse.jetty.server.handler.AbstractHandler.doStart (AbstractHandler.java:113)
          at org.eclipse.jetty.server.Server.doStart (Server.java:419)
          at org.eclipse.jetty.util.component.AbstractLifeCycle.start (AbstractLifeCycle.java:68)
          at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.startJetty (AbstractJettyMojo.java:460)
          at org.eclipse.jetty.maven.plugin.AbstractJettyMojo.execute (AbstractJettyMojo.java:328)
          at org.eclipse.jetty.maven.plugin.JettyRunWarExplodedMojo.execute (JettyRunWarExplodedMojo.java:69)
          at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
          at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:208)
          at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:154)
          at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:146)
          at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
          at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
          at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
          at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
          at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
          at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
          at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
          at org.apache.maven.cli.MavenCli.execute (MavenCli.java:956)
          at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:290)
          at org.apache.maven.cli.MavenCli.main (MavenCli.java:194)
          at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
          at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
          at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
          at java.lang.reflect.Method.invoke (Method.java:498)
          at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:289)
          at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:229)
          at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:415)
          at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:356)
      Caused by: org.eclipse.jetty.util.MultiException: Multiple exceptions
          at org.eclipse.jetty.annotations.AnnotationParser.parseJar (AnnotationParser.java:878)
          at org.eclipse.jetty.annotations.AnnotationParser.parse (AnnotationParser.java:837)
          at org.eclipse.jetty.annotations.AnnotationConfiguration$ParserTask.call (AnnotationConfiguration.java:159)
          at org.eclipse.jetty.annotations.AnnotationConfiguration$1.run (AnnotationConfiguration.java:464)
          at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:672)
          at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run (QueuedThreadPool.java:590)
          at java.lang.Thread.run (Thread.java:745)
      Caused by: java.lang.RuntimeException: Error scanning entry META-INF/versions/9/org/apache/logging/log4j/util/ProcessIdUtil.class from jar file:///Users/lucasjohnston/code/no-hold/target/no-hold-1.0-SNAPSHOT/WEB-INF/lib/log4j-api-2.10.0.jar
          at org.eclipse.jetty.annotations.AnnotationParser.parseJar (AnnotationParser.java:891)
          at org.eclipse.jetty.annotations.AnnotationParser.parse (AnnotationParser.java:837)
          at org.eclipse.jetty.annotations.AnnotationConfiguration$ParserTask.call (AnnotationConfiguration.java:159)
          at org.eclipse.jetty.annotations.AnnotationConfiguration$1.run (AnnotationConfiguration.java:464)
          at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:672)
          at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run (QueuedThreadPool.java:590)
          at java.lang.Thread.run (Thread.java:745)
      Caused by: java.lang.IllegalArgumentException
          at org.objectweb.asm.ClassReader.&lt;init&gt; (Unknown Source)
          at org.objectweb.asm.ClassReader.&lt;init&gt; (Unknown Source)
          at org.objectweb.asm.ClassReader.&lt;init&gt; (Unknown Source)
          at org.eclipse.jetty.annotations.AnnotationParser.scanClass (AnnotationParser.java:959)
          at org.eclipse.jetty.annotations.AnnotationParser.parseJarEntry (AnnotationParser.java:940)
          at org.eclipse.jetty.annotations.AnnotationParser.parseJar (AnnotationParser.java:887)
          at org.eclipse.jetty.annotations.AnnotationParser.parse (AnnotationParser.java:837)
          at org.eclipse.jetty.annotations.AnnotationConfiguration$ParserTask.call (AnnotationConfiguration.java:159)
          at org.eclipse.jetty.annotations.AnnotationConfiguration$1.run (AnnotationConfiguration.java:464)
          at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob (QueuedThreadPool.java:672)
          at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run (QueuedThreadPool.java:590)
          at java.lang.Thread.run (Thread.java:745)
  </code></pre>
  
  <p>When deployed to GAE, a 403 Forbidden is thrown.</p>
  
  <p>This is my current setup:</p>
  
  <p>pom.xml:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;project&gt;
  
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;packaging&gt;war&lt;/packaging&gt;
  
    &lt;groupId&gt;com.bytelucas.flex.nohold&lt;/groupId&gt;
    &lt;artifactId&gt;no-hold&lt;/artifactId&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
  
    &lt;properties&gt;
      &lt;maven.compiler.source&gt;1.8&lt;/maven.compiler.source&gt;
      &lt;maven.compiler.target&gt;1.8&lt;/maven.compiler.target&gt;
      &lt;project.build.sourceEncoding&gt;UTF-8&lt;/project.build.sourceEncoding&gt;
  
      &lt;failOnMissingWebXml&gt;false&lt;/failOnMissingWebXml&gt;
      &lt;appengine.maven.plugin&gt;1.3.2&lt;/appengine.maven.plugin&gt;
      &lt;jetty.maven.plugin&gt;9.4.3.v20170317&lt;/jetty.maven.plugin&gt;
    &lt;/properties&gt;
  
    &lt;dependencyManagement&gt;
      &lt;dependencies&gt;
        &lt;dependency&gt;
          &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
          &lt;artifactId&gt;spring-boot-dependencies&lt;/artifactId&gt;
          &lt;version&gt;2.0.1.RELEASE&lt;/version&gt;
          &lt;type&gt;pom&lt;/type&gt;
          &lt;scope&gt;import&lt;/scope&gt;
        &lt;/dependency&gt;
      &lt;/dependencies&gt;
    &lt;/dependencyManagement&gt;
  
    &lt;dependencies&gt;
      &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
        &lt;exclusions&gt;
          &lt;exclusion&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-starter-tomcat&lt;/artifactId&gt;
          &lt;/exclusion&gt;
        &lt;/exclusions&gt;
      &lt;/dependency&gt;
      &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-jetty&lt;/artifactId&gt;
      &lt;/dependency&gt;
    &lt;/dependencies&gt;
  
    &lt;build&gt;
      &lt;outputDirectory&gt;${project.build.directory}/${project.build.finalName}/WEB-INF/classes&lt;/outputDirectory&gt;
  
      &lt;plugins&gt;
        &lt;plugin&gt;
          &lt;groupId&gt;org.eclipse.jetty&lt;/groupId&gt;
          &lt;artifactId&gt;jetty-maven-plugin&lt;/artifactId&gt;
          &lt;version&gt;${jetty.maven.plugin}&lt;/version&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
          &lt;groupId&gt;com.google.cloud.tools&lt;/groupId&gt;
          &lt;artifactId&gt;appengine-maven-plugin&lt;/artifactId&gt;
          &lt;version&gt;${appengine.maven.plugin}&lt;/version&gt;
          &lt;configuration&gt;
            &lt;!-- deploy configuration --&gt;
  &lt;!--
            &lt;deploy.promote&gt;true&lt;/deploy.promote&gt;                           &lt;!~~ DEFAULT value ~~&gt;
            &lt;deploy.stopPreviousVersion&gt;true&lt;/deploy.stopPreviousVersion&gt;   &lt;!~~ DEFAULT value ~~&gt;
   --&gt;
          &lt;/configuration&gt;
        &lt;/plugin&gt;
  
      &lt;/plugins&gt;
    &lt;/build&gt;
  &lt;/project&gt;
  </code></pre>
  
  <p>build.gradle:</p>
  
  <pre><code>buildscript {
      repositories {
          jcenter()
          mavenCentral()
      }
      dependencies {
          classpath 'com.google.cloud.tools:appengine-gradle-plugin:+'
          classpath 'org.akhikhl.gretty:gretty:+'
          classpath "org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE"
      }
  }
  
  repositories {
      maven {
          url 'https://maven-central.storage.googleapis.com'             // Google's mirror of Maven Central
      }
  
      jcenter()
      mavenCentral()
  }
  
  apply plugin: 'java'
  apply plugin: 'war'
  apply plugin: 'org.akhikhl.gretty'
  apply plugin: 'com.google.cloud.tools.appengine'
  apply plugin: "org.springframework.boot"
  
  dependencies {
      providedCompile 'com.google.appengine:appengine:+'
      compile('org.springframework.boot:spring-boot-starter-web') {
          exclude module: 'spring-boot-starter-tomcat'
      }
      compile 'org.eclipse.jetty:jetty-webapp:9.+'
      compile 'org.eclipse.jetty:jetty-jsp:9.+'
      compile group: 'org.akhikhl.gretty', name: 'gretty-spring-boot-plugin-commons', version: '0.0.24'
      compile group: "com.twilio.sdk", name: "twilio", version: "7.17.+"
  }
  
  gretty {
      httpPort = 8080
      contextPath = '/'
      servletContainer = 'jetty9'
      springBoot = true
      springBootVersion = '2.0.1.RELEASE'
  }
  
  appengine {
      deploy {
          stopPreviousVersion = true
          promote = true
      }
  
  }
  
  group = 'com.bytelucas.appengine'
  version = '1.0-SNAPSHOT'
  
  sourceCompatibility = 1.8
  targetCompatibility = 1.8
  </code></pre>
  
  <p>Api.java:</p>
  
  <pre><code>package com.bytelucas.appengine.nohold;
  
  import org.springframework.boot.SpringApplication;
  import org.springframework.boot.autoconfigure.SpringBootApplication;
  import org.springframework.boot.builder.SpringApplicationBuilder;
  import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
  import org.springframework.context.annotation.ComponentScan;
  
  @SpringBootApplication
  @ComponentScan(basePackageClasses = ApiController.class)
  public class Api extends SpringBootServletInitializer {
    public static void main(String[] args) {
      SpringApplication.run(Api.class, args);
    }
  
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
      return application.sources(Api.class);
    }
  }
  </code></pre>
  
  <p>ApiController.java</p>
  
  <pre><code>package com.bytelucas.appengine.nohold;
  
  import javax.validation.constraints.NotNull;
  import org.springframework.web.bind.annotation.GetMapping;
  import org.springframework.web.bind.annotation.RequestParam;
  import org.springframework.web.bind.annotation.RestController;
  
  @RestController
  public class ApiController {
    @GetMapping("/api")
    public Name apiGetRequest(
        @NotNull @RequestParam(value="name") String name) {
      return new Name(name);
    }
  }
  </code></pre>
  
  <p>I've sort of hit a brick wall at this point so any help would be greatly appreciated!</p>