diff --git a/spring-bootstrap-applications/pom.xml b/spring-bootstrap-applications/pom.xml index aa7edccbdd3..b8c2a75ba93 100644 --- a/spring-bootstrap-applications/pom.xml +++ b/spring-bootstrap-applications/pom.xml @@ -11,6 +11,7 @@ pom ${project.basedir}/.. + 0.0.1-SNAPSHOT spring-bootstrap-application @@ -19,4 +20,81 @@ spring-bootstrap-jpa-application spring-bootstrap-web-application - + + + junit + junit + test + + + org.mockito + mockito-core + test + + + org.hamcrest + hamcrest-library + test + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + + org.springframework.bootstrap + spring-bootstrap + ${spring.bootstrap.version} + + + + true + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + package + + shade + + + + + META-INF/spring.handlers + + + META-INF/spring.factories + + + META-INF/spring.schemas + + + + ${start-class} + + + + + + + + + + diff --git a/spring-bootstrap-service/README.md b/spring-bootstrap-service/README.md new file mode 100644 index 00000000000..7e48ed6edd8 --- /dev/null +++ b/spring-bootstrap-service/README.md @@ -0,0 +1,151 @@ + + +# Spring Bootstrap Services + +Minimum fuss for getting RESTful services up and running in +production, and in other environments. + +|Feature |Implementation |Notes | +|---|---|---| +|Server |Tomcat or Jetty | Whatever is on the classpath | +|REST |Spring MVC | | +|Security |Spring Security | If on the classpath | +|Logging |Logback, Log4j or JDK | Whatever is on the classpath. Sensible defaults. | +|Database |HSQLDB or H2 | Per classpath, or define a DataSource to override | +|Externalized configuration | Properties or YAML | Support for Spring profiles. Bind automatically to @Bean. | +|Validation | JSR-303 | | +|Management endpoints | Spring MVC | Health, basic metrics, request tracing, shutdown | +|Error pages | Spring MVC | Sensible defaults based on exception and status code | +|JSON |Jackson 2 | | +|ORM |Spring Data JPA | If on the classpath | +|Batch |Spring Batch | If enabled and on the classpath | +|Integration Patterns |Spring Integration | If on the classpath | + +# Getting Started + +You will need Java (6 at least) and a build tool (Maven is what we use +below, but you are more than wecome to use gradle). These can be +downloaded or installed easily in most operating systems. FIXME: +short instructions for Mac and Linux. + +## A basic project + +If you are using Maven create a really simple `pom.xml` with 2 dependencies: + + + 4.0.0 + com.mycompany + myproject + 1.0.0-SNAPSHOT + jar + + org.springframework.bootstrap + spring-bootstrap-applications + 0.0.1-SNAPSHOT + + + 0.0.1-SNAPSHOT + org.springframework.bootstrap.SpringApplication + + + org.springframework.bootstrap + spring-bootstrap-web-application + ${spring.bootstrap.version} + + + org.springframework.bootstrap + spring-bootstrap-service + ${spring.bootstrap.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + + + + + +If you like Gradle, that's fine, and you will know what to do with +those co-ordinates. The first one adds Spring Bootstrap auto +configuration and the Jetty container to your application, and the +second one adds some more opinionated stuff like the default +management endpoints. If you prefer Tomcat FIXME: use a different +dependency. + +You should be able to run it already: + + $ mvn package + $ java -jar target/myproject-1.0.0-SNAPSHOT.jar + +Then in another terminal + + $ curl localhost:8080/healthz + ok + $ curl localhost:8080/varz + {"counter.status.200.healthz":1.0,"gauge.response.healthz":10.0,"mem":120768.0,"mem.free":105012.0,"processors":4.0} + +`/healthz` is the default location for the health endpoint - it tells +you if the application is running and healthy. `/varz` is the default +location for the metrics endpoint - it gives you basic counts and +response timing data by default but there are plenty of ways to +customize it. + + $ curl localhost:8080/ + {"status": 404, "error": "Not Found", "message": "Not Found"} + +That's OK, we haven't added any business content yet. + +## Adding a business endpoint + +To do something useful to your business you need to add at least one +endpoint. An endpoint can be implemented as a Spring MVC +`@Controller`, e.g. + + @Controller + @EnableAutoConfiguration + public class SampleController { + + @RequestMapping("/") + @ResponseBody + public Map helloWorld() { + return Collections.singletonMap("message", "Hello World"); + } + + public static void main(String[] args) throws Exception { + SpringApplication.run(SampleController.class, args); + } + + } + +You can launch that straight away using the Spring Bootstrap CLI +(without the `@EnableAutoConfiguration` and even without the import +statements that your IDE will add if you are using one), or you can +use the main method to launch it from your project jar. Just change +the `start-class` in the `pom` above to the fully qualified name of +your `SampleController`, e.g. + + com.mycompany.sample.SampleController + +and re-package: + + $ mvn package + $ java -jar target/myproject-1.0.0-SNAPSHOT.jar + $ curl localhost:8080/ + {"message": "Hello World"} + +# Add a database + +Just add `spring-jdbc` and an embedded database to your dependencies: + +FIXME: TBD diff --git a/spring-bootstrap/src/main/java/org/springframework/bootstrap/SpringApplication.java b/spring-bootstrap/src/main/java/org/springframework/bootstrap/SpringApplication.java index 8613e68f73a..667f26b8528 100644 --- a/spring-bootstrap/src/main/java/org/springframework/bootstrap/SpringApplication.java +++ b/spring-bootstrap/src/main/java/org/springframework/bootstrap/SpringApplication.java @@ -27,6 +27,9 @@ import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.bootstrap.autoconfigure.batch.BatchAutoConfiguration; +import org.springframework.bootstrap.autoconfigure.data.JpaRepositoriesAutoConfiguration; +import org.springframework.bootstrap.context.annotation.EnableAutoConfiguration; import org.springframework.bootstrap.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; @@ -608,4 +611,13 @@ public class SpringApplication { } + public static void main(String[] args) { + run(new Class[] { AutoMain.class }, args); + } + + @EnableAutoConfiguration(exclude = { JpaRepositoriesAutoConfiguration.class, + BatchAutoConfiguration.class }) + public static class AutoMain { + } + } diff --git a/spring-bootstrap/src/test/java/org/springframework/bootstrap/SpringApplicationTests.java b/spring-bootstrap/src/test/java/org/springframework/bootstrap/SpringApplicationTests.java index 1f4e0fb8eaf..de226e4f14b 100644 --- a/spring-bootstrap/src/test/java/org/springframework/bootstrap/SpringApplicationTests.java +++ b/spring-bootstrap/src/test/java/org/springframework/bootstrap/SpringApplicationTests.java @@ -26,6 +26,7 @@ import org.springframework.beans.BeansException; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.DefaultBeanNameGenerator; +import org.springframework.bootstrap.SpringApplication.AutoMain; import org.springframework.bootstrap.context.embedded.AnnotationConfigEmbeddedWebApplicationContext; import org.springframework.bootstrap.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.context.ApplicationContext; @@ -152,6 +153,15 @@ public class SpringApplicationTests { assertThat(getEnvironment().getProperty("foo"), equalTo("bar")); } + @Test + public void emptytApplicationContext() throws Exception { + // This is the class that will be used for main() + SpringApplication application = new SpringApplication(AutoMain.class); + this.context = application.run(); + assertThat(this.context, + instanceOf(AnnotationConfigEmbeddedWebApplicationContext.class)); + } + @Test public void defaultApplicationContext() throws Exception { SpringApplication application = new SpringApplication(ExampleConfig.class);