This commit is contained in:
Phillip Webb 2014-05-15 09:15:35 +01:00
parent 158b6a5c07
commit 01fcf61140
15 changed files with 170 additions and 131 deletions

View File

@ -153,14 +153,12 @@ public class DataSourceAutoConfiguration {
@ConfigurationProperties(prefix = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
@Bean
public DataSource dataSource() {
// @formatter:off
DataSourceBuilder factory = DataSourceBuilder
.create(this.properties.getClassLoader())
.driverClassName(this.properties.getDriverClassName())
.url(this.properties.getUrl())
.username(this.properties.getUsername())
.password(this.properties.getPassword());
// @formatter:on
return factory.build();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2014 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.
@ -37,6 +37,7 @@ import org.springframework.util.ClassUtils;
* <code>@ConfigurationProperties</code>.
*
* @author Dave Syer
* @since 1.1.0
*/
public class DataSourceBuilder {

View File

@ -26,6 +26,7 @@ import org.springframework.util.StringUtils;
* Base class for configuration of a database pool.
*
* @author Dave Syer
* @since 1.1.0
*/
@ConfigurationProperties(prefix = DataSourceAutoConfiguration.CONFIGURATION_PREFIX)
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2014 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.
@ -36,6 +36,7 @@ import org.springframework.util.ClassUtils;
* <code>@Bean</code> definition.
*
* @author Dave Syer
* @since 1.1.0
*/
public class EntityManagerFactoryBuilder {
@ -48,7 +49,6 @@ public class EntityManagerFactoryBuilder {
/**
* Create a new instance passing in the common pieces that will be shared if multiple
* EntityManagerFactory instances are created.
*
* @param jpaVendorAdapter a vendor adapter
* @param properties common configuration options, including generic map for JPA
* vendor properties
@ -68,8 +68,6 @@ public class EntityManagerFactoryBuilder {
/**
* A fluent builder for a LocalContainerEntityManagerFactoryBean.
*
* @author Dave Syer
*/
public class Builder {
@ -85,7 +83,6 @@ public class EntityManagerFactoryBuilder {
/**
* The names of packages to scan for <code>@Entity</code> annotations.
*
* @param packagesToScan packages to scan
* @return the builder for fluent usage
*/
@ -97,7 +94,6 @@ public class EntityManagerFactoryBuilder {
/**
* The classes whose packages should be scanned for <code>@Entity</code>
* annotations.
*
* @param basePackageClasses the classes to use
* @return the builder for fluent usage
*/
@ -114,7 +110,6 @@ public class EntityManagerFactoryBuilder {
* The name of the persistence unit. If only building one EntityManagerFactory you
* can omit this, but if there are more than one in the same application you
* should give them distinct names.
*
* @param persistenceUnit the name of the persistence unit
* @return the builder for fluent usage
*/
@ -127,7 +122,6 @@ public class EntityManagerFactoryBuilder {
* Generic properties for standard JPA or vendor-specific configuration. These
* properties override any values provided in the {@link JpaProperties} used to
* create the builder.
*
* @param properties the properties to use
* @return the builder for fluent usage
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2014 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.
@ -30,6 +30,7 @@ import org.springframework.orm.jpa.vendor.Database;
* External configuration properties for a JPA EntityManagerFactory created by Spring.
*
* @author Dave Syer
* @since 1.1.0
*/
@ConfigurationProperties(prefix = "spring.jpa")
public class JpaProperties {

View File

@ -39,7 +39,7 @@ import redis.clients.jedis.JedisPoolConfig;
/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Redis support.
*
*
* @author Dave Syer
* @author Andy Wilkinson
* @author Christian Dupuis
@ -80,13 +80,7 @@ public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean
RedisConnectionFactory redisConnectionFactory() throws UnknownHostException {
JedisConnectionFactory factory = null;
if (this.properties.getPool() == null) {
factory = new JedisConnectionFactory();
}
else {
factory = new JedisConnectionFactory(jedisPoolConfig());
}
JedisConnectionFactory factory = createJedisConnectionFactory();
factory.setHostName(this.properties.getHost());
factory.setPort(this.properties.getPort());
if (this.properties.getPassword() != null) {
@ -95,6 +89,13 @@ public class RedisAutoConfiguration {
return factory;
}
private JedisConnectionFactory createJedisConnectionFactory() {
if (this.properties.getPool() != null) {
return new JedisConnectionFactory(jedisPoolConfig());
}
return new JedisConnectionFactory();
}
private JedisPoolConfig jedisPoolConfig() {
JedisPoolConfig config = new JedisPoolConfig();
RedisProperties.Pool props = this.properties.getPool();

View File

@ -48,9 +48,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* Test that a {@link DataSource} can be exposed as JSON for actuator endpoints.
*
* @author Dave Syer
*/
public class JsonSerializationTests {
public class DataSourceJsonSerializationTests {
@Test
public void serializerFactory() throws Exception {
@ -69,7 +71,6 @@ public class JsonSerializationTests {
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(DataSource.class, DataSourceJson.class);
String value = mapper.writeValueAsString(dataSource);
System.err.println(value);
assertTrue(value.contains("\"url\":"));
assertEquals(1, StringUtils.countOccurrencesOf(value, "\"url\""));
}

View File

@ -28,6 +28,8 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* Tests for {@link RedisAutoConfiguration}.
*
* @author Dave Syer
* @author Christian Dupuis
*/

View File

@ -298,7 +298,7 @@ to specify profile-specific values.
[[howto-discover-build-in-options-for-external-properties]]
=== Discover built-in options for external properties
Spring Boot binds external properties from `application.properties` (or `.yml`) (and
other places) into an application at runtime. There is not (and technically cannot be)
other places) into an application at runtime. There is not (and technically cannot be)
an exhaustive list of all supported properties in a single location because contributions
can come from additional jar files on your classpath.
@ -739,7 +739,7 @@ exposed in the `MultipartProperties` class. If you want to specify that files be
unlimited, for example, set the `multipart.maxFileSize` property to `-1`.
The multipart support is helpful when you want to receive multipart encoded file data as
a `@RequestParam`-annotated parameter of type `MultipartFile` in a Spring MVC controller
a `@RequestParam`-annotated parameter of type `MultipartFile` in a Spring MVC controller
handler method.
See the {sc-spring-boot-autoconfigure}/web/MultipartAutoConfiguration.{sc-ext}[`MultipartAutoConfiguration`] s
@ -769,7 +769,7 @@ configuration in your hands.
[[howto-customize-view-resolvers]]
=== Customize ViewResolvers
A `ViewResolver` is a core component of Spring MVC, translating view names in
`@Controller` to actual `View` implementations. Note that `ViewResolvers` are mainly
`@Controller` to actual `View` implementations. Note that `ViewResolvers` are mainly
used in UI applications, rather than REST-style services (a `View` is not used to render
a `@ResponseBody`). There are many implementations of `ViewResolver` to choose from, and
Spring on its own is not opinionated about which ones you should use. Spring Boot, on the
@ -833,7 +833,7 @@ Spring Boot has no mandatory logging dependence, except for the `commons-logging
which there are many implementations to choose from. To use http://logback.qos.ch[Logback]
you need to include it, and some bindings for `commons-logging` on the classpath. The
simplest way to do that is through the starter poms which all depend on
`spring-boot-starter-logging`. For a web application you only need
`spring-boot-starter-logging`. For a web application you only need
`spring-boot-starter-web` since it depends transitively on the logging starter.
For example, using Maven:
@ -894,7 +894,7 @@ requires some jiggling with excludes, e.g. in Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
@ -925,57 +925,58 @@ action.
[[howto-configure-a-datasource]]
=== Configure a DataSource
To override the default settings just define a `@Bean` of your own of type `DataSource`.
To override the default settings just define a `@Bean` of your own of type `DataSource`.
Spring Boot provides a utility builder class `DataSourceBuilder` that can be used
to create one of the standard ones (if it is on the classpath), or you can just create
to create one of the standard ones (if it is on the classpath), or you can just create
your own, and bind it to a set of `Environment` properties e.g.
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
@ConfigurationProperties(prefix="datasource.mine")
public DataSource dataSource() {
return new FancyDataSource();
}
@ConfigurationProperties(prefix="datasource.mine")
public DataSource dataSource() {
return new FancyDataSource();
}
----
[source,properties,indent=0]
----
datasource.mine.jdbcUrl=jdbc:h2:mem:mydb
datasource.mine.user=sa
datasource.mine.poolSize=30
datasource.mine.poolSize=30
----
See '<<spring-boot-features.adoc#boot-features-configure-datasource>>' in the
``Spring Boot features'' section and the
{sc-spring-boot-autoconfigure}/jdbc/DataSourceAutoConfiguration.{sc-ext}[`DataSourceAutoConfiguration`]
class for more details.
[[howto-two-datasources]]
=== Configure Two DataSources
Creating more than one data source works the same as creating the first one.
You might want to mark one of them as `@Primary` if you are using the default
auto-configuration for JDBC or JPA (then that one will be picked up by any
`@Autowired` injections).
Creating more than one data source works the same as creating the first one. You might
want to mark one of them as `@Primary` if you are using the default auto-configuration for
JDBC or JPA (then that one will be picked up by any `@Autowired` injections).
[source,java,indent=0,subs="verbatim,quotes,attributes"]
----
@Bean
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return new FancyDataSource();
}
@Primary
@ConfigurationProperties(prefix="datasource.primary")
public DataSource primaryDataSource() {
return new FancyDataSource();
}
@Bean
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return new FancyDataSource();
}
@ConfigurationProperties(prefix="datasource.secondary")
public DataSource secondaryDataSource() {
return new FancyDataSource();
}
----
[[howto-use-spring-data-repositories]]
=== Use Spring Data repositories
Spring Data can create implementations for you of `@Repository` interfaces of various
@ -1030,7 +1031,7 @@ configuration properties. The most common options to set are:
----
(Because of relaxed data binding hyphens or underscores should work equally well as
property keys.) The `ddl-auto` setting is a special case in that it has different
property keys.) The `ddl-auto` setting is a special case in that it has different
defaults depending on whether you are using an embedded database (`create-drop`) or not
(`none`). In addition all properties in `spring.jpa.properties.*` are passed through as
normal JPA properties (with the prefix stripped) when the local `EntityManagerFactory` is
@ -1041,22 +1042,24 @@ and {sc-spring-boot-autoconfigure}/orm/jpa/JpaBaseConfiguration.{sc-ext}[`JpaBas
for more details.
[[howto-use-custom-entity-manager]]
=== Use a custom EntityManagerFactory
To take full control of the configuration of the `EntityManagerFactory`, you need to add
a `@Bean` named "entityManagerFactory". Spring Boot auto-configuration switches off its entity manager
based on the presence of a bean of that type.
a `@Bean` named "entityManagerFactory". Spring Boot auto-configuration switches off its
entity manager based on the presence of a bean of that type.
[[howto-use-two-entity-managers]]
=== Use Two EntityManagers
Even if the default `EntityManagerFactory` works fine, you will need
to define a new one because otherwise the presence of the second bean
of that type will switch off the default. To make it easy to do that
you can use the convenient `EntityManagerBuilder` provided by Spring
Boot, or if you prefer you can just use the
Even if the default `EntityManagerFactory` works fine, you will need to define a new one
because otherwise the presence of the second bean of that type will switch off the
default. To make it easy to do that you can use the convenient `EntityManagerBuilder`
provided by Spring Boot, or if you prefer you can just use the
`LocalContainerEntityManagerFactoryBean` directly from Spring ORM.
Example:
[source,java,indent=0,subs="verbatim,quotes,attributes"]
@ -1069,8 +1072,8 @@ Example:
return builder
.dataSource(customerDataSource())
.packages(Customer.class)
.persistenceUnit("customers")
.build();
.persistenceUnit("customers")
.build();
}
@Bean
@ -1079,19 +1082,19 @@ Example:
return builder
.dataSource(orderDataSource())
.packages(Order.class)
.persistenceUnit("orders")
.build();
.persistenceUnit("orders")
.build();
}
----
The configuration above almost works on its own. To complete the
picture you need to configure `TransactionManagers` for the two
`EntityManagers` as well. One of them could be picked up by the
default `JpaTransactionManager` in Spring Boot if you mark it as
`@Primary`. The other would have to be explicitly injected into a new
instance. Or you might be able to use a JTA transaction manager
spanning both.
The configuration above almost works on its own. To complete the picture you need to
configure `TransactionManagers` for the two `EntityManagers` as well. One of them could
be picked up by the default `JpaTransactionManager` in Spring Boot if you mark it as
`@Primary`. The other would have to be explicitly injected into a new instance. Or you
might be able to use a JTA transaction manager spanning both.
[[howto-use-traditional-persistence-xml]]
=== Use a traditional persistence.xml
@ -1312,7 +1315,7 @@ use this in a webapp is to inject it into a void method in a
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("barry").password("password").roles("USER"); // ... etc.
.withUser("barry").password("password").roles("USER"); // ... etc.
}
// ... other stuff for application security
@ -1330,7 +1333,7 @@ is a useful template to follow.
[[howto-enable-https]]
=== Enable HTTPS when running behind a proxy server
Ensuring that all your main endpoints are only available over HTTPS is an important
chore for any application. If you are using Tomcat as a servlet container, then
chore for any application. If you are using Tomcat as a servlet container, then
Spring Boot will add Tomcat's own `RemoteIpValve` automatically if it detects some
environment settings, and you should be able to rely on the `HttpServletRequest` to
report whether it is secure or not (even downstream of a proxy server that handles the
@ -1573,7 +1576,7 @@ For a non-web application it should be easy (throw away the code that creates yo
`ApplicationContext` and replace it with calls to `SpringApplication` or
`SpringApplicationBuilder`). Spring MVC web applications are generally amenable to first
creating a deployable war application, and then migrating it later to an executable war
and/or jar. Useful reading is in the http://spring.io/guides/gs/convert-jar-to-war/[Getting
and/or jar. Useful reading is in the http://spring.io/guides/gs/convert-jar-to-war/[Getting
Started Guide on Converting a jar to a war].
Create a deployable war by extending `SpringBootServletInitializer` (e.g. in a class

View File

@ -44,7 +44,7 @@ dependencies {
compile("org.springframework.boot:spring-boot-starter-security")
compile("org.springframework.boot:spring-boot-starter-web")
compile("com.h2database:h2")
testCompile("org.springframework.boot:spring-boot-starter-test")
insecure configurations.runtime

View File

@ -110,7 +110,7 @@ public class RepackageMojo extends AbstractDependencyFilterMojo {
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (project.getPackaging().equals("pom")) {
if (this.project.getPackaging().equals("pom")) {
getLog().debug("repackage goal could not be applied to pom project.");
return;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2012-2014 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.boot.maven;
import org.codehaus.plexus.util.cli.CommandLineUtils;
/**
* Parse and expose arguments specified as {@link RunMojo} parameters.
*
* @author Stephane Nicoll
* @since 1.1.0
*/
class RunArguments {
private static final String[] NO_ARGS = {};
private final String[] args;
public RunArguments(String arguments) {
this.args = parseArgs(arguments);
}
private String[] parseArgs(String arguments) {
if (arguments == null || arguments.trim().isEmpty()) {
return NO_ARGS;
}
try {
arguments = arguments.replace('\n', ' ').replace('\t', ' ');
return CommandLineUtils.translateCommandline(arguments);
}
catch (Exception ex) {
throw new IllegalArgumentException("Failed to parse arguments [" + arguments
+ "]", ex);
}
}
public String[] asArray() {
return this.args;
}
}

View File

@ -39,8 +39,6 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactFeatureFilter;
import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.springframework.boot.loader.tools.FileUtils;
import org.springframework.boot.loader.tools.JavaExecutable;
import org.springframework.boot.loader.tools.MainClassFinder;
@ -91,9 +89,8 @@ public class RunMojo extends AbstractDependencyFilterMojo {
private Boolean noverify;
/**
* JVM arguments that should be associated with the forked process used
* to run the application. On command line, make sure to wrap multiple
* values between quotes.
* JVM arguments that should be associated with the forked process used to run the
* application. On command line, make sure to wrap multiple values between quotes.
* @since 1.1
*/
@Parameter(property = "run.jvmArguments")
@ -176,15 +173,23 @@ public class RunMojo extends AbstractDependencyFilterMojo {
}
}
private void addJvmArgs(List<String> args) {
String[] jvmArgs = parseArgs(this.jvmArguments);
Collections.addAll(args, jvmArgs);
logArguments("JVM argument(s): ", jvmArgs);
private void addAgents(List<String> args) {
findAgent();
if (this.agent != null) {
getLog().info("Attaching agents: " + Arrays.asList(this.agent));
for (File agent : this.agent) {
args.add("-javaagent:" + agent);
}
}
if (this.noverify) {
args.add("-noverify");
}
}
private void addArgs(List<String> args) {
Collections.addAll(args, this.arguments);
logArguments("Application argument(s): ", this.arguments);
private void addJvmArgs(List<String> args) {
RunArguments jvmArguments = new RunArguments(this.jvmArguments);
Collections.addAll(args, jvmArguments.asArray());
logArguments("JVM argument(s): ", jvmArguments.asArray());
}
private void addClasspath(List<String> args) throws MojoExecutionException {
@ -203,17 +208,9 @@ public class RunMojo extends AbstractDependencyFilterMojo {
}
}
private void addAgents(List<String> args) {
findAgent();
if (this.agent != null) {
getLog().info("Attaching agents: " + Arrays.asList(this.agent));
for (File agent : this.agent) {
args.add("-javaagent:" + agent);
}
}
if (this.noverify) {
args.add("-noverify");
}
private void addArgs(List<String> args) {
Collections.addAll(args, this.arguments);
logArguments("Application argument(s): ", this.arguments);
}
private final String getStartClass() throws MojoExecutionException {
@ -292,28 +289,6 @@ public class RunMojo extends AbstractDependencyFilterMojo {
getLog().debug(sb.toString().trim());
}
/**
* Parse the arguments parameters and return individual arguments.
*
* @param arguments the arguments line to parse
* @return the individual arguments
*/
static String[] parseArgs(String arguments) {
if (arguments == null || arguments.trim().isEmpty()) {
return new String[]{};
}
String args = arguments.replace('\n', ' ');
args = args.replace('\t', ' ');
try {
return CommandLineUtils.translateCommandline(args);
}
catch (Exception e) {
throw new IllegalArgumentException("Failed to parse arguments [" + arguments + "]", e);
}
}
private static class TestArtifactFilter extends AbstractArtifactFeatureFilter {
public TestArtifactFilter() {
super("", Artifact.SCOPE_TEST);

View File

@ -16,41 +16,44 @@
package org.springframework.boot.maven;
import static org.junit.Assert.*;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
*
* Tests for {@link RunArguments}.
*
* @author Stephane Nicoll
*/
public class RunMojoTests {
public class RunArgumentsTests {
@Test
public void parseNull() {
String[] args = RunMojo.parseArgs(null);
String[] args = parseArgs(null);
assertNotNull(args);
assertEquals(0, args.length);
}
@Test
public void parseEmpty() {
String[] args = RunMojo.parseArgs(" ");
String[] args = parseArgs(" ");
assertNotNull(args);
assertEquals(0, args.length);
}
@Test
public void parseDebugFlags() {
String[] args = RunMojo.parseArgs("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005");
String[] args = parseArgs("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005");
assertEquals(2, args.length);
assertEquals("-Xdebug", args[0]);
assertEquals("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005", args[1]);
assertEquals("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005",
args[1]);
}
@Test
public void parseWithExtraSpaces() {
String[] args = RunMojo.parseArgs(" -Dfoo=bar -Dfoo2=bar2 ");
String[] args = parseArgs(" -Dfoo=bar -Dfoo2=bar2 ");
assertEquals(2, args.length);
assertEquals("-Dfoo=bar", args[0]);
assertEquals("-Dfoo2=bar2", args[1]);
@ -58,8 +61,7 @@ public class RunMojoTests {
@Test
public void parseWithNewLinesAndTabs() {
String[] args = RunMojo.parseArgs(" -Dfoo=bar \n" +
"\t\t -Dfoo2=bar2 ");
String[] args = parseArgs(" -Dfoo=bar \n" + "\t\t -Dfoo2=bar2 ");
assertEquals(2, args.length);
assertEquals("-Dfoo=bar", args[0]);
assertEquals("-Dfoo2=bar2", args[1]);
@ -67,9 +69,13 @@ public class RunMojoTests {
@Test
public void quoteHandledProperly() {
String[] args = RunMojo.parseArgs("-Dvalue=\"My Value\" ");
String[] args = parseArgs("-Dvalue=\"My Value\" ");
assertEquals(1, args.length);
assertEquals("-Dvalue=My Value", args[0]);
}
private String[] parseArgs(String args) {
return new RunArguments(args).asArray();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2013 the original author or authors.
* Copyright 2012-2014 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.
@ -31,10 +31,11 @@ import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;
/**
* Utility class to memoize <code>@Bean</code> definition meta data during initialization
* Utility class to memorize <code>@Bean</code> definition meta data during initialization
* of the bean factory.
*
* @author Dave Syer
* @since 1.1.0
*/
public class ConfigurationBeanFactoryMetaData implements BeanFactoryPostProcessor {