
Many of the new JVM-based web frameworks are ditching containers and WAR files and instead using a [WAR-less / Containerless approach][1]. But that doesn't mean you have to ditch your favorite Java web framework. A while back I posted about [going containerless with Tapestry][2]. Now lets do the same with Spring MVC. You can [grab the full source code from GitHub][3].

First we need a build that defines the dependencies. Here is the [build.gradle][4] file for my Gradle build:

```groovy
apply plugin:'java'
apply plugin:'application'

version = '0.0.1-SNAPSHOT'

mainClassName = "com.jamesward.Webapp"
applicationName = "webapp"

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.springframework:spring-webmvc:3.1.2.RELEASE'
    compile 'cglib:cglib:2.2.2'
    compile 'org.eclipse.jetty:jetty-webapp:8.1.5.v20120716'
}
```

There isn't much to this build except a few dependencies: Spring MVC, CGLib, and Jetty.

The [src/main/resources/assets/index.html][5] file just contains simple HTML:

```html4strict
<!doctype html>


hello, world


```

The [src/main/java/com/jamesward/WebConfig.java][6] file uses Spring annotations to configure Spring MVC:

```java
package com.jamesward;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/assets/");
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("redirect:index.html");
    }

}
```

Finally, a simple "static void main" Java class is used to start Jetty. The [src/main/java/com/jamesward/Webapp.java][7] file just sets up the HTTP listener and starts it:

```java
package com.jamesward;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;


public class Webapp {

    public static void main(String[] args) throws Exception {

        final AnnotationConfigWebApplicationContext applicationContext = new AnnotationConfigWebApplicationContext();
        applicationContext.register(WebConfig.class);

        final ServletHolder servletHolder = new ServletHolder(new DispatcherServlet(applicationContext));
        final ServletContextHandler context = new ServletContextHandler();
        context.setContextPath("/");
        context.addServlet(servletHolder, "/*");

        String webPort = System.getenv("PORT");
        if (webPort == null || webPort.isEmpty()) {
            webPort = "8080";
        }

        final Server server = new Server(Integer.valueOf(webPort));

        server.setHandler(context);

        server.start();
        server.join();
    }

}
```

That's it! To build and run this project locally you can simple run:

```bash
./gradlew run
```

(Note: Run "gradlew.bat" on Windows.)

So simple it's hard to believe it works. :) Let me know if you have any questions.

 [1]: http://www.jamesward.com/2011/08/23/war-less-java-web-apps
 [2]: http://www.jamesward.com/2012/02/08/deploy-containerless-tapestry-apps-on-heroku
 [3]: https://github.com/jamesward/containerless-springmvc
 [4]: https://github.com/jamesward/containerless-springmvc/blob/master/build.gradle
 [5]: https://github.com/jamesward/containerless-springmvc/blob/master/src/main/resources/assets/index.html
 [6]: https://github.com/jamesward/containerless-springmvc/blob/master/src/main/java/com/jamesward/WebConfig.java
 [7]: https://github.com/jamesward/containerless-springmvc/blob/master/src/main/java/com/jamesward/Webapp.java
