9 changed files with 110 additions and 607 deletions
@ -1,177 +0,0 @@ |
|||||||
# Spring Bootstrap |
|
||||||
|
|
||||||
Spring Bootstrap is "Spring for Snowboarders". If you are kewl, or |
|
||||||
just impatient, and you want to use Spring, then this is the place to |
|
||||||
be. Spring Bootstrap is a toolkit and runtime platform that will get |
|
||||||
you up and running with Spring-powered, production-grade applications |
|
||||||
and services with absolute minimum fuss. It takes an opinionated view |
|
||||||
of the Spring family so that new and existing users can quickly get to |
|
||||||
the bits they need. Assumes no knowledge of the Java development |
|
||||||
ecosystem. Absolutely no code generation and no XML (unless you really |
|
||||||
want it). |
|
||||||
|
|
||||||
The goals are: |
|
||||||
|
|
||||||
* Radically faster and widely accessible getting started experience |
|
||||||
for Spring development |
|
||||||
* Be opinionated out of the box, but get out of the way quickly as |
|
||||||
requirements start to diverge from the defaults |
|
||||||
* Provide a range of non-functional features that are common to large |
|
||||||
classes of projects (e.g. embedded servers, security, metrics, |
|
||||||
health checks, externalized configuration) |
|
||||||
* First class support for REST-ful services, modern web applications, |
|
||||||
batch jobs, and enterprise integration |
|
||||||
* Applications that adapt their behaviour or configuration to their |
|
||||||
environment |
|
||||||
* Optionally use Groovy features like DSLs and AST transformations to |
|
||||||
accelerate the implementation of basic business requirements |
|
||||||
|
|
||||||
## Installing |
|
||||||
You need to build from source for now, but when it's done instructions will look like this: |
|
||||||
|
|
||||||
1) Get Java. Download and install the Java SDK from www.java.com |
|
||||||
|
|
||||||
2) Get Spring |
|
||||||
|
|
||||||
$ curl -s try.spring.io | bash |
|
||||||
|
|
||||||
or use the Windows installer |
|
||||||
|
|
||||||
3) Get to Work! |
|
||||||
|
|
||||||
$ cat > app.groovy |
|
||||||
@Controller |
|
||||||
class ThisWillActuallyRun { |
|
||||||
@RequestMapping("/") |
|
||||||
@ResponseBody |
|
||||||
String home() { |
|
||||||
return "Hello World!" |
|
||||||
} |
|
||||||
} |
|
||||||
$ spring run app.groovy |
|
||||||
$ curl localhost:8080 |
|
||||||
Hello World! |
|
||||||
|
|
||||||
|
|
||||||
## What? It's Groovy then? or like Grails? or another Roo? |
|
||||||
|
|
||||||
There is a command line tool that uses Groovy underneath so that we |
|
||||||
can present simple snippets that can just run just like the slimline |
|
||||||
`app.groovy` example above. Groovy makes this really easy. |
|
||||||
|
|
||||||
If you don't want to use the command line tool, or you would rather |
|
||||||
work using Java and an IDE you can. Just add a `main()` method that |
|
||||||
calls `SpringApplication` and add `@EnableAutoConfiguration`: |
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.stereotype.*; |
|
||||||
import org.springframework.web.bind.annotation.*; |
|
||||||
import org.springframework.bootstrap.context.annotation.*; |
|
||||||
|
|
||||||
@Controller |
|
||||||
@EnableAutoConfiguration |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
@RequestMapping("/") |
|
||||||
@ResponseBody |
|
||||||
String home() { |
|
||||||
return "Hello World!" |
|
||||||
} |
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception { |
|
||||||
SpringApplication.run(SampleController.class, args); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
## Spring Bootstrap Themes |
|
||||||
|
|
||||||
There are a number of themes in Bootstrap. Here are the important |
|
||||||
ones: |
|
||||||
|
|
||||||
### The Spring CLI |
|
||||||
|
|
||||||
The 'spring' command line application compiles and runs Groovy source, |
|
||||||
making it super easy to write the absolute minimum of code to get an |
|
||||||
application running. Spring CLI can also watch files, automatically |
|
||||||
recompiling and restarting when they change. |
|
||||||
|
|
||||||
### Bootstrap Core |
|
||||||
|
|
||||||
The main library providing features that support the other parts of |
|
||||||
Spring Bootstrap. Features include: |
|
||||||
|
|
||||||
* `SpringApplication` - a class with static convenience methods that |
|
||||||
make it really easy to write a standalone Spring Application. Its |
|
||||||
sole job is to create and refresh an appropriate Spring |
|
||||||
`ApplicationContext`. |
|
||||||
* Embedded web applications with a choice of container (Tomcat or |
|
||||||
Jetty for now) |
|
||||||
* `@EnableAutoConfigure` is an annotation that triggers |
|
||||||
auto-configuration of the Spring context. Auto-configuration |
|
||||||
attempts to guess what beans a user might want based on their |
|
||||||
classpath. For example, If a 'HSQLDB' is on the classpath the user |
|
||||||
probably wants an in-memory database to be |
|
||||||
defined. Auto-configuration will back away as the user starts to |
|
||||||
define their own beans. |
|
||||||
* `@Conditional` is an annotation in Spring 4.0 that allows you to |
|
||||||
control which parts of an application are used at runtime. Spring |
|
||||||
Bootstrap provides some concrete implementations of conditional |
|
||||||
configuration, e.g. `@ConditionalOnBean`, |
|
||||||
`@ConditionalOnMissingBean` and `@ConditionalOnClass`. |
|
||||||
|
|
||||||
### Spring Bootstrap Service |
|
||||||
|
|
||||||
<!-- FIXME: change the name --> |
|
||||||
|
|
||||||
Spring Bootstrap Service uses auto-configuration features to decorate |
|
||||||
your application with features that make it instantly deployable and |
|
||||||
supportable in production. For instance if you are writing a JSON web |
|
||||||
service then it will provide a server, security, logging, externalized |
|
||||||
configuration, management endpoints, an audit abstraction, and more. |
|
||||||
If you want to switch off the built in features, or extend or replace |
|
||||||
them, it makes that really easy as well. |
|
||||||
|
|
||||||
### Spring Bootstrap Applications |
|
||||||
|
|
||||||
<!-- FIXME: change the name --> |
|
||||||
|
|
||||||
Spring Bootstrap Applications are a set of convenient dependency |
|
||||||
descriptors that you can include in your application. You get a |
|
||||||
one-stop-shop for all the Spring and related technology that you need |
|
||||||
without having to hunt through sample code and copy paste loads of |
|
||||||
dependency descriptors. For example, if you want to get started using |
|
||||||
Spring and JPA for database access just include one dependency in your |
|
||||||
project, and you are good to go. |
|
||||||
|
|
||||||
## Building the code |
|
||||||
Use maven to build the source code. |
|
||||||
|
|
||||||
$ mvn clean install |
|
||||||
|
|
||||||
## Importing into eclipse |
|
||||||
You can use m2e or `maven eclipse:eclipse`. |
|
||||||
|
|
||||||
Project specific settings are configured for source formatting. If you |
|
||||||
are using m2e you can follow these steps to install eclipse support |
|
||||||
for formatting: |
|
||||||
|
|
||||||
* Select `Install new software` from the `help` menu |
|
||||||
* Click `Add...` to add a new repository |
|
||||||
* Click the `Archive...` button |
|
||||||
* Select `org.eclipse.m2e.maveneclipse.site-0.0.1-SNAPSHOT-site.zip` |
|
||||||
from the `eclipse` folder in this checkout |
|
||||||
* Install "Maven Integration for the maven-eclipse-plugin" |
|
||||||
|
|
||||||
Or if you prefer you can import settings manually from the `/eclipse` folder. |
|
||||||
|
|
||||||
## Samples |
|
||||||
The following samples are included. To run use `java -jar target/<archive>.jar` |
|
||||||
|
|
||||||
* spring-bootstrap-simple-sample - A simple command line application |
|
||||||
* spring-bootstrap-jetty-sample - Embedded Jetty |
|
||||||
* spring-bootstrap-tomcat-sample - Embedded Tomcat |
|
||||||
* spring-bootstrap-service-sample - Simple REST service with production features |
|
||||||
* spring-batch-sample - Define and run a Batch job in a few lines of code |
|
||||||
* spring-bootstrap-data-sample - Spring Data JPA + Hibernate + HSQLDB |
|
||||||
|
|
||||||
@ -1,387 +0,0 @@ |
|||||||
<style> |
|
||||||
table |
|
||||||
{ |
|
||||||
border-collapse:collapse; |
|
||||||
} |
|
||||||
table,th, td |
|
||||||
{ |
|
||||||
border: 1px solid black; |
|
||||||
} |
|
||||||
</style> |
|
||||||
|
|
||||||
# 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. | |
|
||||||
|Audit | Spring Security and Spring ApplicationEvent |Flexible abstraction with sensible defaults for security events | |
|
||||||
|Validation | JSR-303 |If on the classpath | |
|
||||||
|Management endpoints | Spring MVC | Health, basic metrics, request tracing, shutdown, thread dumps | |
|
||||||
|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 welcome to use gradle). These can be |
|
||||||
downloaded or installed easily in most operating systems. For Ubuntu: |
|
||||||
|
|
||||||
$ sudo apt-get install openjdk-6-jdk maven |
|
||||||
|
|
||||||
<!--FIXME: short instructions for Mac.--> |
|
||||||
|
|
||||||
## A basic project |
|
||||||
|
|
||||||
If you are using Maven create a really simple `pom.xml` with 2 dependencies: |
|
||||||
|
|
||||||
<project> |
|
||||||
<modelVersion>4.0.0</modelVersion> |
|
||||||
<groupId>com.mycompany</groupId> |
|
||||||
<artifactId>myproject</artifactId> |
|
||||||
<version>1.0.0-SNAPSHOT</version> |
|
||||||
<packaging>jar</packaging> |
|
||||||
<parent> |
|
||||||
<groupId>org.springframework.bootstrap</groupId> |
|
||||||
<artifactId>spring-bootstrap-applications</artifactId> |
|
||||||
<version>0.0.1-SNAPSHOT</version> |
|
||||||
</parent> |
|
||||||
<dependencies> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.bootstrap</groupId> |
|
||||||
<artifactId>spring-bootstrap-web-application</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.bootstrap</groupId> |
|
||||||
<artifactId>spring-bootstrap-service</artifactId> |
|
||||||
</dependency> |
|
||||||
</dependencies> |
|
||||||
<build> |
|
||||||
<plugins> |
|
||||||
<plugin> |
|
||||||
<groupId>org.apache.maven.plugins</groupId> |
|
||||||
<artifactId>maven-shade-plugin</artifactId> |
|
||||||
</plugin> |
|
||||||
</plugins> |
|
||||||
</build> |
|
||||||
</project> |
|
||||||
|
|
||||||
If you like Gradle, that's fine, and you will know what to do with |
|
||||||
those dependencies. The first dependency 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 you can just add the |
|
||||||
embedded Tomcat jars to your classpath instead of Jetty. |
|
||||||
|
|
||||||
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. You can also try `/trace` and `/dump` to get some |
|
||||||
interesting information about how and what your app is doing. |
|
||||||
|
|
||||||
What about the home page? |
|
||||||
|
|
||||||
$ curl localhost:8080/ |
|
||||||
{"status": 404, "error": "Not Found", "message": "Not Found"} |
|
||||||
|
|
||||||
That's OK, we haven't added any business content yet. But it shows |
|
||||||
that there are sensible defaults built in for rendering HTTP and |
|
||||||
server-side errors. |
|
||||||
|
|
||||||
## 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<String, String> 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 add a |
|
||||||
`start-class` in the properties section of the `pom` above pointing to |
|
||||||
the fully qualified name of your `SampleController`, e.g. |
|
||||||
|
|
||||||
<properties> |
|
||||||
<start-class>com.mycompany.sample.SampleController</start-class> |
|
||||||
</properties> |
|
||||||
|
|
||||||
and re-package: |
|
||||||
|
|
||||||
$ mvn package |
|
||||||
$ java -jar target/myproject-1.0.0-SNAPSHOT.jar |
|
||||||
$ curl localhost:8080/ |
|
||||||
{"message": "Hello World"} |
|
||||||
|
|
||||||
## Running the application |
|
||||||
|
|
||||||
You can package the app and run it as a jar (as above) and that's very |
|
||||||
convenient for production usage. Or there are other options, many of |
|
||||||
which are more convenient at development time. Here are a few: |
|
||||||
|
|
||||||
1. Use the Maven exec plugin, e.g. |
|
||||||
|
|
||||||
$ mvn exec:java |
|
||||||
|
|
||||||
2. Run directly in your IDE, e.g. Eclipse or IDEA let you right click |
|
||||||
on a class and run it. |
|
||||||
|
|
||||||
3. Use a different Maven plugin. |
|
||||||
|
|
||||||
4. Find feature in Gradle that does the same thing. |
|
||||||
|
|
||||||
5. Use the Spring executable. <!--FIXME: document this maybe.--> |
|
||||||
|
|
||||||
## Externalizing configuration |
|
||||||
|
|
||||||
Spring Bootstrap likes you to externalize your configuration so you |
|
||||||
can work with the same application code in different environments. To |
|
||||||
get started with this you create a file in the root of your classpath |
|
||||||
(`src/main/resources` if using Maven) - if you like YAML you can call |
|
||||||
it `application.yml`, e.g.: |
|
||||||
|
|
||||||
server: |
|
||||||
port: 9000 |
|
||||||
management: |
|
||||||
port: 9001 |
|
||||||
logging: |
|
||||||
file: target/log.out |
|
||||||
|
|
||||||
or if you like Java `Properties` files, you can call it |
|
||||||
`application.properties`, e.g.: |
|
||||||
|
|
||||||
server.port: 9000 |
|
||||||
management.port: 9001 |
|
||||||
logging.file: target/log.out |
|
||||||
|
|
||||||
Those examples are properties that Spring Bootstrap itself binds to |
|
||||||
out of the box, so if you make that change and run the app again, you |
|
||||||
will find the home page on port 9000 instead of 8080: |
|
||||||
|
|
||||||
$ curl localhost:9000/ |
|
||||||
{"message": "Hello World"} |
|
||||||
|
|
||||||
and the management endpoints on port 9001 instead of 8080: |
|
||||||
|
|
||||||
$ curl localhost:9001/healthz |
|
||||||
ok |
|
||||||
|
|
||||||
To externalize business configuration you can simply add a default |
|
||||||
value to your configuration file, e.g. |
|
||||||
|
|
||||||
server: |
|
||||||
port: 9000 |
|
||||||
management: |
|
||||||
port: 9001 |
|
||||||
logging: |
|
||||||
file: target/log.out |
|
||||||
service: |
|
||||||
message: Awesome Message |
|
||||||
|
|
||||||
and then bind to it in the application code. The simplest way to do |
|
||||||
that is to simply refer to it in an `@Value` annotation, e.g. |
|
||||||
|
|
||||||
@Controller |
|
||||||
@EnableAutoConfiguration |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
@Value("${service.message:Hello World}") |
|
||||||
private String value = "Goodbye Everypone" |
|
||||||
|
|
||||||
@RequestMapping("/") |
|
||||||
@ResponseBody |
|
||||||
public Map<String, String> helloWorld() { |
|
||||||
return Collections.singletonMap("message", message); |
|
||||||
} |
|
||||||
|
|
||||||
... |
|
||||||
} |
|
||||||
|
|
||||||
That's a little bit confusing because we have provided a message value |
|
||||||
in three different places - in the external configuration ("Awesome |
|
||||||
Message"), in the `@Value` annotation after the colon ("Hello World"), |
|
||||||
and in the filed initializer ("Goodbye Everyone"). That was only to |
|
||||||
show you how and you only need it once, so it's your choice (it's |
|
||||||
useful for unit testing to have the Java initializer as well as the |
|
||||||
external value). Note that the YAML object is flattened using period |
|
||||||
separators. |
|
||||||
|
|
||||||
For simple Strings where you have sensible defaults `@Value` is |
|
||||||
perfect, but if you want more and you like everything strongly typed |
|
||||||
then you can have Spring bind the properties and validate them |
|
||||||
automatically in a separate value object. For instance: |
|
||||||
|
|
||||||
// ServiceProperties.java |
|
||||||
@ConfigurationProperties(name="service") |
|
||||||
public class ServiceProperties { |
|
||||||
private String message; |
|
||||||
private int value = 0; |
|
||||||
... getters and setters |
|
||||||
} |
|
||||||
|
|
||||||
// SampleController.java |
|
||||||
@Controller |
|
||||||
@EnableAutoConfiguration |
|
||||||
@EnableConfigurationProperties(ServiceProperties.class) |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
@Autowired |
|
||||||
private ServiceProperties properties; |
|
||||||
|
|
||||||
@RequestMapping("/") |
|
||||||
@ResponseBody |
|
||||||
public Map<String, String> helloWorld() { |
|
||||||
return Collections.singletonMap("message", properties.getMessage()); |
|
||||||
} |
|
||||||
|
|
||||||
... |
|
||||||
} |
|
||||||
|
|
||||||
When you ask to |
|
||||||
`@EnableConfigurationProperties(ServiceProperties.class)` you are |
|
||||||
saying you want a bean of type `ServiceProperties` and that you want |
|
||||||
to bind it to the Spring Environment. The Spring Environment is a |
|
||||||
collection of name-value pairs taken from (in order of decreasing |
|
||||||
precedence) 1) the command line, 2) the external configuration file, |
|
||||||
3) System properties, 4) the OS environment. Validation is done based |
|
||||||
on JSR-303 annotations by default provided that library (and an |
|
||||||
implementation) is on the classpath. |
|
||||||
|
|
||||||
## Adding security |
|
||||||
|
|
||||||
If you add Spring Security java config to your runtime classpath you |
|
||||||
will enable HTTP basic authentication by default on all the endpoints. |
|
||||||
In the `pom.xml` it would look like this: |
|
||||||
|
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework.security</groupId> |
|
||||||
<artifactId>spring-security-javaconfig</artifactId> |
|
||||||
<version>1.0.0.BUILD-SNAPSHOT</version> |
|
||||||
</dependency> |
|
||||||
|
|
||||||
(Spring Security java config is still work in progress so we have used |
|
||||||
a snapshot. Beware of sudden changes.) |
|
||||||
|
|
||||||
<!--FIXME: update Spring Security to full release --> |
|
||||||
|
|
||||||
Try it out: |
|
||||||
|
|
||||||
$ curl localhost:8080/ |
|
||||||
{"status": 403, "error": "Forbidden", "message": "Access Denied"} |
|
||||||
$ curl user:password@localhost:8080/ |
|
||||||
{"message": "Hello World"} |
|
||||||
|
|
||||||
The default auto configuration has an in-memory user database with one |
|
||||||
entry. If you want to extend or expand that, or point to a database |
|
||||||
or directory server, you only need to provide a `@Bean` definition for |
|
||||||
an `AuthenticationManager`, e.g. in your `SampleController`: |
|
||||||
|
|
||||||
@Bean |
|
||||||
public AuthenticationManager authenticationManager() throws Exception { |
|
||||||
return new AuthenticationBuilder().inMemoryAuthentication().withUser("client") |
|
||||||
.password("secret").roles("USER").and().and().build(); |
|
||||||
} |
|
||||||
|
|
||||||
Try it out: |
|
||||||
|
|
||||||
$ curl user:password@localhost:8080/ |
|
||||||
{"status": 403, "error": "Forbidden", "message": "Access Denied"} |
|
||||||
$ curl client:secret@localhost:8080/ |
|
||||||
{"message": "Hello World"} |
|
||||||
|
|
||||||
## Adding a database |
|
||||||
|
|
||||||
Just add `spring-jdbc` and an embedded database to your dependencies: |
|
||||||
|
|
||||||
<dependency> |
|
||||||
<groupId>org.springframework</groupId> |
|
||||||
<artifactId>spring-jdbc</artifactId> |
|
||||||
</dependency> |
|
||||||
<dependency> |
|
||||||
<groupId>org.hsqldb</groupId> |
|
||||||
<artifactId>hsqldb</artifactId> |
|
||||||
</dependency> |
|
||||||
|
|
||||||
Then you will be able to inject a `DataSource` into your controller: |
|
||||||
|
|
||||||
@Controller |
|
||||||
@EnableAutoConfiguration |
|
||||||
@EnableConfigurationProperties(ServiceProperties.class) |
|
||||||
public class SampleController { |
|
||||||
|
|
||||||
private JdbcTemplate jdbcTemplate; |
|
||||||
|
|
||||||
@Autowired |
|
||||||
public SampleController(DataSource dataSource) { |
|
||||||
this.jdbcTemplate = new JdbcTemplate(dataSource); |
|
||||||
} |
|
||||||
|
|
||||||
@RequestMapping("/") |
|
||||||
@ResponseBody |
|
||||||
public Map<String, String> helloWorld() { |
|
||||||
return jdbcTemplate.queryForMap("SELECT * FROM MESSAGES WHERE ID=?", 0); |
|
||||||
} |
|
||||||
|
|
||||||
... |
|
||||||
} |
|
||||||
|
|
||||||
The app will run (going back to the default security configuration): |
|
||||||
|
|
||||||
$ curl user:password@localhost:8080/ |
|
||||||
{"error":"Internal Server Error", "status":500, "exception":...} |
|
||||||
|
|
||||||
but there's no data in the database yet and the `MESSAGES` table |
|
||||||
doesn't even exist, so there's an error. One easy way to fix it is |
|
||||||
to provide a `schema.sql` script in the root of the classpath, e.g. |
|
||||||
|
|
||||||
create table MESSAGES ( |
|
||||||
ID BIGINT NOT NULL PRIMARY KEY, |
|
||||||
MESSAGE VARCHAR(255) |
|
||||||
); |
|
||||||
INSERT INTO MESSAGES (ID, MESSAGE) VALUES (0, 'Hello Phil'); |
|
||||||
|
|
||||||
Now when you run the app you get a sensible response: |
|
||||||
|
|
||||||
$ curl user:password@localhost:8080/ |
|
||||||
{"ID":0, "MESSAGE":"Hello Phil"} |
|
||||||
|
|
||||||
Obviously, this is only the start, but hopefully you have a good grasp |
|
||||||
of the basics and are ready to try it out yourself. |
|
||||||
@ -0,0 +1,54 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* 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.springframework.bootstrap.actuate.properties; |
||||||
|
|
||||||
|
import java.net.InetAddress; |
||||||
|
import java.util.Collections; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.springframework.beans.MutablePropertyValues; |
||||||
|
import org.springframework.bootstrap.bind.RelaxedDataBinder; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertFalse; |
||||||
|
|
||||||
|
/** |
||||||
|
* Externalized configuration for server properties |
||||||
|
* |
||||||
|
* @author Dave Syer |
||||||
|
* |
||||||
|
*/ |
||||||
|
public class ServerPropertiesTests { |
||||||
|
|
||||||
|
private ServerProperties properties = new ServerProperties(); |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testAddressBinding() throws Exception { |
||||||
|
RelaxedDataBinder binder = new RelaxedDataBinder(this.properties, "server"); |
||||||
|
binder.bind(new MutablePropertyValues(Collections.singletonMap("server.address", |
||||||
|
"127.0.0.1"))); |
||||||
|
assertFalse(binder.getBindingResult().hasErrors()); |
||||||
|
assertEquals(InetAddress.getLocalHost(), this.properties.getAddress()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testPortBinding() throws Exception { |
||||||
|
new RelaxedDataBinder(this.properties, "server").bind(new MutablePropertyValues( |
||||||
|
Collections.singletonMap("server.port", "9000"))); |
||||||
|
assertEquals(9000, this.properties.getPort()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
Loading…
Reference in new issue