Commit 56e31a8c authored by Phillip Webb's avatar Phillip Webb

Polish

parent 1f0d45d7
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -16,8 +16,6 @@ ...@@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.data.rest; package org.springframework.boot.autoconfigure.data.rest;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
...@@ -26,10 +24,11 @@ import org.springframework.data.rest.core.config.RepositoryRestConfiguration; ...@@ -26,10 +24,11 @@ import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.fasterxml.jackson.databind.ObjectMapper;
/** /**
* A specialized {@link RepositoryRestMvcConfiguration} that applies configuration * A specialized {@link RepositoryRestMvcConfiguration} that applies configuration items
* items from the {@code spring.data.rest} namespace. Also configure Jackson if it's * from the {@code spring.data.rest} namespace. Also configures Jackson if it's available
* available
* <p> * <p>
* Favor an extension of this class instead of extending directly from * Favor an extension of this class instead of extending directly from
* {@link RepositoryRestMvcConfiguration}. * {@link RepositoryRestMvcConfiguration}.
...@@ -38,8 +37,7 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; ...@@ -38,8 +37,7 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
* @since 1.2.2 * @since 1.2.2
*/ */
@Configuration @Configuration
public class RepositoryRestMvcBootConfiguration extends public class RepositoryRestMvcBootConfiguration extends RepositoryRestMvcConfiguration {
RepositoryRestMvcConfiguration {
@Autowired(required = false) @Autowired(required = false)
private Jackson2ObjectMapperBuilder objectMapperBuilder; private Jackson2ObjectMapperBuilder objectMapperBuilder;
......
...@@ -117,16 +117,22 @@ public class JacksonAutoConfiguration { ...@@ -117,16 +117,22 @@ public class JacksonAutoConfiguration {
@Bean @Bean
public Module jodaDateTimeSerializationModule() { public Module jodaDateTimeSerializationModule() {
SimpleModule module = new SimpleModule(); SimpleModule module = new SimpleModule();
JacksonJodaFormat jacksonJodaFormat = getJacksonJodaFormat();
if (jacksonJodaFormat != null) {
module.addSerializer(DateTime.class, new DateTimeSerializer(
jacksonJodaFormat));
}
return module;
}
JacksonJodaFormat jacksonJodaFormat = null; private JacksonJodaFormat getJacksonJodaFormat() {
if (this.jacksonProperties.getJodaDateTimeFormat() != null) { if (this.jacksonProperties.getJodaDateTimeFormat() != null) {
jacksonJodaFormat = new JacksonJodaFormat(DateTimeFormat.forPattern( return new JacksonJodaFormat(DateTimeFormat.forPattern(
this.jacksonProperties.getJodaDateTimeFormat()).withZoneUTC()); this.jacksonProperties.getJodaDateTimeFormat()).withZoneUTC());
} }
else if (this.jacksonProperties.getDateFormat() != null) { if (this.jacksonProperties.getDateFormat() != null) {
try { try {
jacksonJodaFormat = new JacksonJodaFormat(DateTimeFormat.forPattern( return new JacksonJodaFormat(DateTimeFormat.forPattern(
this.jacksonProperties.getDateFormat()).withZoneUTC()); this.jacksonProperties.getDateFormat()).withZoneUTC());
} }
catch (IllegalArgumentException ex) { catch (IllegalArgumentException ex) {
...@@ -138,14 +144,9 @@ public class JacksonAutoConfiguration { ...@@ -138,14 +144,9 @@ public class JacksonAutoConfiguration {
} }
} }
} }
return null;
if (jacksonJodaFormat != null) {
module.addSerializer(DateTime.class, new DateTimeSerializer(
jacksonJodaFormat));
}
return module;
} }
} }
@Configuration @Configuration
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2002-2014 the original author or authors. * Copyright 2002-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
...@@ -51,15 +51,15 @@ class InitializrService { ...@@ -51,15 +51,15 @@ class InitializrService {
/** /**
* Accept header to use to retrieve the json meta-data. * Accept header to use to retrieve the json meta-data.
*/ */
public static final String ACCEPT_META_DATA = public static final String ACCEPT_META_DATA = "application/vnd.initializr.v2.1+"
"application/vnd.initializr.v2.1+json,application/vnd.initializr.v2+json"; + "json,application/vnd.initializr.v2+json";
/** /**
* Accept header to use to retrieve the service capabilities of the service. If the * Accept header to use to retrieve the service capabilities of the service. If the
* service does not offer such feature, the json meta-data are retrieved instead. * service does not offer such feature, the json meta-data are retrieved instead.
*/ */
public static final String ACCEPT_SERVICE_CAPABILITIES = public static final String ACCEPT_SERVICE_CAPABILITIES = "text/plain,"
"text/plain," + ACCEPT_META_DATA; + ACCEPT_META_DATA;
/** /**
* Late binding HTTP client. * Late binding HTTP client.
...@@ -110,27 +110,29 @@ class InitializrService { ...@@ -110,27 +110,29 @@ class InitializrService {
} }
/** /**
* Loads the service capabilities of the service at the specified url. * Loads the service capabilities of the service at the specified URL. If the service
* <p>If the service supports generating a textual representation of the * supports generating a textual representation of the capabilities, it is returned,
* capabilities, it is returned. Otherwhise the json meta-data as a * otherwise {@link InitializrServiceMetadata} is returned.
* {@link JSONObject} is returned.
* @param serviceUrl to url of the initializer service * @param serviceUrl to url of the initializer service
* @return the service capabilities (as a String) or the metadata describing the service * @return the service capabilities (as a String) or the
* {@link InitializrServiceMetadata} describing the service
* @throws IOException if the service capabilities cannot be loaded * @throws IOException if the service capabilities cannot be loaded
*/ */
public Object loadServiceCapabilities(String serviceUrl) throws IOException { public Object loadServiceCapabilities(String serviceUrl) throws IOException {
CloseableHttpResponse httpResponse = executeServiceCapabilitiesRetrieval(serviceUrl); HttpGet request = new HttpGet(serviceUrl);
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_SERVICE_CAPABILITIES));
CloseableHttpResponse httpResponse = execute(request, serviceUrl, "retrieve help");
validateResponse(httpResponse, serviceUrl); validateResponse(httpResponse, serviceUrl);
HttpEntity httpEntity = httpResponse.getEntity(); HttpEntity httpEntity = httpResponse.getEntity();
ContentType contentType = ContentType.getOrDefault(httpEntity); ContentType contentType = ContentType.getOrDefault(httpEntity);
if (contentType.getMimeType().equals("text/plain")) { if (contentType.getMimeType().equals("text/plain")) {
return getContent(httpEntity); return getContent(httpEntity);
} else {
return parseJsonMetadata(httpEntity);
} }
return parseJsonMetadata(httpEntity);
} }
private InitializrServiceMetadata parseJsonMetadata(HttpEntity httpEntity) throws IOException { private InitializrServiceMetadata parseJsonMetadata(HttpEntity httpEntity)
throws IOException {
try { try {
return new InitializrServiceMetadata(getContentAsJson(httpEntity)); return new InitializrServiceMetadata(getContentAsJson(httpEntity));
} }
...@@ -179,15 +181,6 @@ class InitializrService { ...@@ -179,15 +181,6 @@ class InitializrService {
return execute(request, url, "retrieve metadata"); return execute(request, url, "retrieve metadata");
} }
/**
* Retrieves the service capabilities of the service at the specified URL
*/
private CloseableHttpResponse executeServiceCapabilitiesRetrieval(String url) {
HttpGet request = new HttpGet(url);
request.setHeader(new BasicHeader(HttpHeaders.ACCEPT, ACCEPT_SERVICE_CAPABILITIES));
return execute(request, url, "retrieve help");
}
private CloseableHttpResponse execute(HttpUriRequest request, Object url, private CloseableHttpResponse execute(HttpUriRequest request, Object url,
String description) { String description) {
try { try {
......
...@@ -48,7 +48,7 @@ class ServiceCapabilitiesReportGenerator { ...@@ -48,7 +48,7 @@ class ServiceCapabilitiesReportGenerator {
/** /**
* Generate a report for the specified service. The report contains the available * Generate a report for the specified service. The report contains the available
* capabilities as advertized by the root endpoint. * capabilities as advertised by the root endpoint.
* @param url the url of the service * @param url the url of the service
* @return the report that describes the service * @return the report that describes the service
* @throws IOException if the report cannot be generated * @throws IOException if the report cannot be generated
...@@ -57,9 +57,8 @@ class ServiceCapabilitiesReportGenerator { ...@@ -57,9 +57,8 @@ class ServiceCapabilitiesReportGenerator {
Object content = this.initializrService.loadServiceCapabilities(url); Object content = this.initializrService.loadServiceCapabilities(url);
if (content instanceof InitializrServiceMetadata) { if (content instanceof InitializrServiceMetadata) {
return generateHelp(url, (InitializrServiceMetadata) content); return generateHelp(url, (InitializrServiceMetadata) content);
} else {
return content.toString();
} }
return content.toString();
} }
private String generateHelp(String url, InitializrServiceMetadata metadata) { private String generateHelp(String url, InitializrServiceMetadata metadata) {
......
...@@ -49,15 +49,18 @@ public abstract class AbstractHttpClientMockTests { ...@@ -49,15 +49,18 @@ public abstract class AbstractHttpClientMockTests {
protected final CloseableHttpClient http = mock(CloseableHttpClient.class); protected final CloseableHttpClient http = mock(CloseableHttpClient.class);
protected void mockSuccessfulMetadataTextGet() throws IOException { protected void mockSuccessfulMetadataTextGet() throws IOException {
mockSuccessfulMetadataGet("metadata/service-metadata-2.1.0.txt", "text/plain", true); mockSuccessfulMetadataGet("metadata/service-metadata-2.1.0.txt", "text/plain",
true);
} }
protected void mockSuccessfulMetadataGet(boolean serviceCapabilities) throws IOException { protected void mockSuccessfulMetadataGet(boolean serviceCapabilities)
throws IOException {
mockSuccessfulMetadataGet("metadata/service-metadata-2.1.0.json", mockSuccessfulMetadataGet("metadata/service-metadata-2.1.0.json",
"application/vnd.initializr.v2.1+json", serviceCapabilities); "application/vnd.initializr.v2.1+json", serviceCapabilities);
} }
protected void mockSuccessfulMetadataGetV2(boolean serviceCapabilities) throws IOException { protected void mockSuccessfulMetadataGetV2(boolean serviceCapabilities)
throws IOException {
mockSuccessfulMetadataGet("metadata/service-metadata-2.0.0.json", mockSuccessfulMetadataGet("metadata/service-metadata-2.0.0.json",
"application/vnd.initializr.v2+json", serviceCapabilities); "application/vnd.initializr.v2+json", serviceCapabilities);
} }
...@@ -68,7 +71,8 @@ public abstract class AbstractHttpClientMockTests { ...@@ -68,7 +71,8 @@ public abstract class AbstractHttpClientMockTests {
byte[] content = readClasspathResource(contentPath); byte[] content = readClasspathResource(contentPath);
mockHttpEntity(response, content, contentType); mockHttpEntity(response, content, contentType);
mockStatus(response, 200); mockStatus(response, 200);
given(this.http.execute(argThat(getForMetadata(serviceCapabilities)))).willReturn(response); given(this.http.execute(argThat(getForMetadata(serviceCapabilities))))
.willReturn(response);
} }
protected byte[] readClasspathResource(String contentPath) throws IOException { protected byte[] readClasspathResource(String contentPath) throws IOException {
...@@ -137,12 +141,10 @@ public abstract class AbstractHttpClientMockTests { ...@@ -137,12 +141,10 @@ public abstract class AbstractHttpClientMockTests {
} }
private Matcher<HttpGet> getForMetadata(boolean serviceCapabilities) { private Matcher<HttpGet> getForMetadata(boolean serviceCapabilities) {
if (serviceCapabilities) { if (!serviceCapabilities) {
return new HasAcceptHeader(InitializrService.ACCEPT_SERVICE_CAPABILITIES, true);
}
else {
return new HasAcceptHeader(InitializrService.ACCEPT_META_DATA, true); return new HasAcceptHeader(InitializrService.ACCEPT_META_DATA, true);
} }
return new HasAcceptHeader(InitializrService.ACCEPT_SERVICE_CAPABILITIES, true);
} }
private Matcher<HttpGet> getForNonMetadata() { private Matcher<HttpGet> getForNonMetadata() {
...@@ -206,6 +208,7 @@ public abstract class AbstractHttpClientMockTests { ...@@ -206,6 +208,7 @@ public abstract class AbstractHttpClientMockTests {
} }
return acceptHeader == null || !this.value.equals(acceptHeader.getValue()); return acceptHeader == null || !this.value.equals(acceptHeader.getValue());
} }
} }
} }
...@@ -37,7 +37,8 @@ public class ServiceCapabilitiesReportGeneratorTests extends AbstractHttpClientM ...@@ -37,7 +37,8 @@ public class ServiceCapabilitiesReportGeneratorTests extends AbstractHttpClientM
@Test @Test
public void listMetadataFromServer() throws IOException { public void listMetadataFromServer() throws IOException {
mockSuccessfulMetadataTextGet(); mockSuccessfulMetadataTextGet();
String expected = new String(readClasspathResource("metadata/service-metadata-2.1.0.txt")); String expected = new String(
readClasspathResource("metadata/service-metadata-2.1.0.txt"));
String content = this.command.generate("http://localhost"); String content = this.command.generate("http://localhost");
assertThat(content, equalTo(expected)); assertThat(content, equalTo(expected));
} }
......
...@@ -1483,6 +1483,7 @@ repository types (Elasticsearch, Solr). Just change the names of the annotations ...@@ -1483,6 +1483,7 @@ repository types (Elasticsearch, Solr). Just change the names of the annotations
respectively. respectively.
[[howto-use-exposing-spring-data-repositories-rest-endpoint]] [[howto-use-exposing-spring-data-repositories-rest-endpoint]]
=== Expose Spring Data repositories as REST endpoint === Expose Spring Data repositories as REST endpoint
...@@ -1497,6 +1498,7 @@ extending from `RepositoryRestMvcBootConfiguration` instead as the latter provid ...@@ -1497,6 +1498,7 @@ extending from `RepositoryRestMvcBootConfiguration` instead as the latter provid
the handling of `spring.data.rest` properties. the handling of `spring.data.rest` properties.
[[howto-database-initialization]] [[howto-database-initialization]]
== Database initialization == Database initialization
An SQL database can be initialized in different ways depending on what your stack is. Or An SQL database can be initialized in different ways depending on what your stack is. Or
......
...@@ -297,14 +297,13 @@ Maven '`project properties`' via `@..@` placeholders, e.g. ...@@ -297,14 +297,13 @@ Maven '`project properties`' via `@..@` placeholders, e.g.
NOTE: In the above example we used `+project.*+` to set some values to be used as NOTE: In the above example we used `+project.*+` to set some values to be used as
fallbacks if the Maven resource filtering has not been switched on for some reason. fallbacks if the Maven resource filtering has not been switched on for some reason.
TIP: The `spring-boot:run` maven goal adds `src/main/resources` directly to TIP: The `spring-boot:run` maven goal adds `src/main/resources` directly to the classpath
the classpath (for hot reloading purposes). This circumvents the resource (for hot reloading purposes). This circumvents the resource filtering and this feature.
filtering and this feature. You can use the `exec:java` goal instead or You can use the `exec:java` goal instead or customize the plugin's configuration, see the
customize the plugin's configuration, see the
{spring-boot-maven-plugin-site}/usage.html[plugin usage page] for more details. {spring-boot-maven-plugin-site}/usage.html[plugin usage page] for more details.
If you don't use the starter parent, in your `pom.xml` you need (inside the `<build/>`
NOTE: If you don't use the starter parent, in your `pom.xml` you need (inside the `<build/>` element): element):
[source,xml,indent=0] [source,xml,indent=0]
---- ----
...@@ -332,6 +331,8 @@ and (inside `<plugins/>`): ...@@ -332,6 +331,8 @@ and (inside `<plugins/>`):
</plugin> </plugin>
---- ----
[[production-ready-application-info-automatic-expansion-gradle]] [[production-ready-application-info-automatic-expansion-gradle]]
===== Automatic property expansion using Gradle ===== Automatic property expansion using Gradle
You can automatically expand info properties from the Gradle project by configuring You can automatically expand info properties from the Gradle project by configuring
......
...@@ -1271,7 +1271,7 @@ instance. By default the embedded server will listen for HTTP requests on port ` ...@@ -1271,7 +1271,7 @@ instance. By default the embedded server will listen for HTTP requests on port `
[[boot-features-embedded-container-servlets-and-filters]] [[boot-features-embedded-container-servlets-and-filters]]
==== Servlets and Filters ==== Servlets and Filters
When using an embedded servlet container you can register Servlets, Filters and all the When using an embedded servlet container you can register Servlets, Filters and all the
listeners from the Servlet spec (e.g. `HttpSessionListener`) directly as listeners from the Servlet spec (e.g. `HttpSessionListener`) directly as
Spring beans. This can be particularly convenient if you want to refer to a value from Spring beans. This can be particularly convenient if you want to refer to a value from
your `application.properties` during configuration. your `application.properties` during configuration.
...@@ -1281,10 +1281,9 @@ the case of multiple Servlet beans the bean name will be used as a path prefix. ...@@ -1281,10 +1281,9 @@ the case of multiple Servlet beans the bean name will be used as a path prefix.
will map to `+/*+`. will map to `+/*+`.
If convention-based mapping is not flexible enough you can use the If convention-based mapping is not flexible enough you can use the
`ServletRegistrationBean`, `FilterRegistrationBean` and `ServletRegistrationBean`, `FilterRegistrationBean` and `ServletListenerRegistrationBean`
`ServletListenerRegistrationBean` classes for complete control. You classes for complete control. You can also register items directly if your bean implements
can also register items directly if your bean implements the the `ServletContextInitializer` interface.
`ServletContextInitializer` interface.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment