diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfiguration.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfiguration.java index 4f2f6edffa5..4cebd0a5996 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfiguration.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfiguration.java @@ -57,6 +57,7 @@ import org.springframework.web.util.UrlPathHelper; public class MetricFilterAutoConfiguration { private static final int UNDEFINED_HTTP_STATUS = 999; + private static final String UNKNOWN_PATH_SUFFIX = "/unmapped"; @Autowired @@ -90,10 +91,10 @@ public class MetricFilterAutoConfiguration { finally { stopWatch.stop(); int status = getStatus(response); - if (request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE) != null) { - suffix = request - .getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE) - .toString().replaceAll("[{}]", "-"); + Object bestMatchingPattern = request + .getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + if (bestMatchingPattern != null) { + suffix = bestMatchingPattern.toString().replaceAll("[{}]", "-"); } else if (HttpStatus.valueOf(status).is4xxClientError()) { suffix = UNKNOWN_PATH_SUFFIX; diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DataSourceHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DataSourceHealthIndicator.java index 54fe1dab902..498556e2831 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DataSourceHealthIndicator.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/DataSourceHealthIndicator.java @@ -21,6 +21,7 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.HashMap; +import java.util.List; import java.util.Map; import javax.sql.DataSource; @@ -52,8 +53,8 @@ public class DataSourceHealthIndicator extends AbstractHealthIndicator { private static Map queries = new HashMap(); static { - queries.put("HSQL Database Engine", - "SELECT COUNT(*) FROM INFORMATION_SCHEMA.SYSTEM_USERS"); + queries.put("HSQL Database Engine", "SELECT COUNT(*) FROM " + + "INFORMATION_SCHEMA.SYSTEM_USERS"); queries.put("Oracle", "SELECT 'Hello' from DUAL"); queries.put("Apache Derby", "SELECT 1 FROM SYSIBM.SYSDUMMY1"); } @@ -93,23 +94,11 @@ public class DataSourceHealthIndicator extends AbstractHealthIndicator { String query = detectQuery(product); if (StringUtils.hasText(query)) { try { - builder.withDetail("hello", DataAccessUtils - .requiredSingleResult(this.jdbcTemplate.query(query, - new RowMapper() { - - @Override - public Object mapRow(ResultSet rs, int rowNum) - throws SQLException { - ResultSetMetaData rsmd = rs.getMetaData(); - int nrOfColumns = rsmd.getColumnCount(); - if (nrOfColumns != 1) { - throw new IncorrectResultSetColumnCountException( - 1, nrOfColumns); - } - return JdbcUtils.getResultSetValue(rs, 1); - } - - }))); + // Avoid calling getObject as it breaks MySQL on Java 7 + List results = this.jdbcTemplate.query(query, + new SingleColumnRowMapper()); + Object result = DataAccessUtils.requiredSingleResult(results); + builder.withDetail("hello", result); } catch (Exception ex) { builder.down(ex); @@ -147,4 +136,21 @@ public class DataSourceHealthIndicator extends AbstractHealthIndicator { this.query = query; } + /** + * {@link RowMapper} that expects and returns results from a single column. + */ + private static class SingleColumnRowMapper implements RowMapper { + + @Override + public Object mapRow(ResultSet rs, int rowNum) throws SQLException { + ResultSetMetaData metaData = rs.getMetaData(); + int columns = metaData.getColumnCount(); + if (columns != 1) { + throw new IncorrectResultSetColumnCountException(1, columns); + } + return JdbcUtils.getResultSetValue(rs, 1); + } + + } + } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java index 5f2ec79bba0..919a5bbed59 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/autoconfigure/MetricFilterAutoConfigurationTests.java @@ -169,4 +169,4 @@ class MetricFilterTestController { public String testKnownPathWith404Response(@PathVariable String someVariable) { return someVariable; } -} \ No newline at end of file +} diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java index b890dc22040..c122c6ca4a7 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/command/jar/JarCommand.java @@ -191,7 +191,7 @@ public class JarCommand extends OptionParsingCommand { manifest.getMainAttributes().putValue("Start-Class", PackagedSpringApplicationLauncher.class.getName()); manifest.getMainAttributes().putValue( - PackagedSpringApplicationLauncher.SOURCE_MANIFEST_ENTRY, + PackagedSpringApplicationLauncher.SOURCE_ENTRY, commaDelimitedClassNames(compiledClasses)); writer.writeManifest(manifest); } diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java index d314392694e..0c9950d0bcb 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/compiler/DependencyCustomizer.java @@ -257,7 +257,8 @@ public class DependencyCustomizer { } /** - * @return the dependencyResolutionContext + * Returns the {@link DependencyResolutionContext}. + * @return the dependency resolution context */ public DependencyResolutionContext getDependencyResolutionContext() { return this.dependencyResolutionContext; diff --git a/spring-boot-cli/src/main/java/org/springframework/boot/cli/jar/PackagedSpringApplicationLauncher.java b/spring-boot-cli/src/main/java/org/springframework/boot/cli/jar/PackagedSpringApplicationLauncher.java index abd8295f9cd..c78ccfe528c 100644 --- a/spring-boot-cli/src/main/java/org/springframework/boot/cli/jar/PackagedSpringApplicationLauncher.java +++ b/spring-boot-cli/src/main/java/org/springframework/boot/cli/jar/PackagedSpringApplicationLauncher.java @@ -20,6 +20,7 @@ import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; +import java.util.jar.Attributes; import java.util.jar.Manifest; /** @@ -30,9 +31,9 @@ import java.util.jar.Manifest; */ public class PackagedSpringApplicationLauncher { - public static final String SOURCE_MANIFEST_ENTRY = "Spring-Application-Source-Classes"; + public static final String SOURCE_ENTRY = "Spring-Application-Source-Classes"; - public static final String MAIN_CLASS_MANIFEST_ENTRY = "Start-Class"; + public static final String START_CLASS_ENTRY = "Start-Class"; private static final String SPRING_APPLICATION_CLASS = "org.springframework.boot.SpringApplication"; @@ -45,21 +46,25 @@ public class PackagedSpringApplicationLauncher { } private Object[] getSources(URLClassLoader classLoader) throws Exception { - for (Enumeration urls = classLoader.findResources("META-INF/MANIFEST.MF"); urls - .hasMoreElements();) { + Enumeration urls = classLoader.findResources("META-INF/MANIFEST.MF"); + while (urls.hasMoreElements()) { URL url = urls.nextElement(); Manifest manifest = new Manifest(url.openStream()); - if (getClass().getName().equals( - manifest.getMainAttributes().getValue(MAIN_CLASS_MANIFEST_ENTRY))) { - String attribute = manifest.getMainAttributes().getValue( - SOURCE_MANIFEST_ENTRY); - return loadClasses(classLoader, attribute.split(",")); + if (isCliPackaged(manifest)) { + String sources = manifest.getMainAttributes().getValue(SOURCE_ENTRY); + return loadClasses(classLoader, sources.split(",")); } } - throw new IllegalStateException("Cannot locate " + SOURCE_MANIFEST_ENTRY + throw new IllegalStateException("Cannot locate " + SOURCE_ENTRY + " in MANIFEST.MF"); } + private boolean isCliPackaged(Manifest manifest) { + Attributes attributes = manifest.getMainAttributes(); + String startClass = attributes.getValue(START_CLASS_ENTRY); + return getClass().getName().equals(startClass); + } + private Class[] loadClasses(ClassLoader classLoader, String[] names) throws ClassNotFoundException { Class[] classes = new Class[names.length]; diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java index 5dba4c28396..146ef0ae6e5 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/Repackager.java @@ -139,11 +139,10 @@ public class Repackager { private boolean alreadyRepackaged() throws IOException { JarFile jarFile = new JarFile(this.source); - try { Manifest manifest = jarFile.getManifest(); - return manifest != null - && manifest.getMainAttributes().getValue(BOOT_VERSION_ATTRIBUTE) != null; + return (manifest != null && manifest.getMainAttributes().getValue( + BOOT_VERSION_ATTRIBUTE) != null); } finally { jarFile.close(); @@ -226,7 +225,7 @@ public class Repackager { String launcherClassName = this.layout.getLauncherClassName(); if (launcherClassName != null) { manifest.getMainAttributes() - .putValue(MAIN_CLASS_ATTRIBUTE, launcherClassName); + .putValue(MAIN_CLASS_ATTRIBUTE, launcherClassName); if (startClass == null) { throw new IllegalStateException("Unable to find main class"); } diff --git a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java index 36465b2a0dd..7c2bba853db 100644 --- a/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java +++ b/spring-boot/src/main/java/org/springframework/boot/bind/RelaxedDataBinder.java @@ -28,7 +28,6 @@ import org.springframework.beans.BeanWrapperImpl; import org.springframework.beans.InvalidPropertyException; import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.PropertyValue; -import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; import org.springframework.util.StringUtils; import org.springframework.validation.DataBinder; @@ -48,8 +47,6 @@ public class RelaxedDataBinder extends DataBinder { private boolean ignoreNestedProperties; - private ConversionService relaxedConversionService; - /** * Create a new {@link RelaxedDataBinder} instance. * @param target the target into which properties are bound @@ -79,19 +76,12 @@ public class RelaxedDataBinder extends DataBinder { this.ignoreNestedProperties = ignoreNestedProperties; } - @Override - public void setConversionService(ConversionService conversionService) { - super.setConversionService(conversionService); - this.relaxedConversionService = new RelaxedConversionService(getConversionService()); - } - @Override public void initBeanPropertyAccess() { super.initBeanPropertyAccess(); - this.relaxedConversionService = (this.relaxedConversionService != null - ? this.relaxedConversionService : new RelaxedConversionService(getConversionService())); // Hook in the RelaxedConversionService - getInternalBindingResult().initConversion(relaxedConversionService); + getInternalBindingResult().initConversion( + new RelaxedConversionService(getConversionService())); } @Override @@ -120,13 +110,13 @@ public class RelaxedDataBinder extends DataBinder { propertyValues = addMapPrefix(propertyValues); } - BeanWrapper targetWrapper = new BeanWrapperImpl(target); - targetWrapper.setConversionService(this.relaxedConversionService); - targetWrapper.setAutoGrowNestedPaths(true); + BeanWrapper wrapper = new BeanWrapperImpl(target); + wrapper.setConversionService(new RelaxedConversionService(getConversionService())); + wrapper.setAutoGrowNestedPaths(true); List list = propertyValues.getPropertyValueList(); for (int i = 0; i < list.size(); i++) { - modifyProperty(propertyValues, targetWrapper, list.get(i), i); + modifyProperty(propertyValues, wrapper, list.get(i), i); } return propertyValues; }