Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
cf485ce1
Commit
cf485ce1
authored
Nov 15, 2017
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1.5.x'
parents
d3daded6
85dc89e1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
158 additions
and
29 deletions
+158
-29
ConfigurationPropertiesReportEndpoint.java
...ext/properties/ConfigurationPropertiesReportEndpoint.java
+51
-16
ConfigurationPropertiesReportEndpointSerializationTests.java
...figurationPropertiesReportEndpointSerializationTests.java
+107
-13
No files found.
spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java
View file @
cf485ce1
...
@@ -24,10 +24,12 @@ import java.util.List;
...
@@ -24,10 +24,12 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Map
;
import
com.fasterxml.jackson.annotation.JsonInclude.Include
;
import
com.fasterxml.jackson.annotation.JsonInclude.Include
;
import
com.fasterxml.jackson.core.JsonGenerator
;
import
com.fasterxml.jackson.databind.BeanDescription
;
import
com.fasterxml.jackson.databind.BeanDescription
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.SerializationConfig
;
import
com.fasterxml.jackson.databind.SerializationConfig
;
import
com.fasterxml.jackson.databind.SerializationFeature
;
import
com.fasterxml.jackson.databind.SerializationFeature
;
import
com.fasterxml.jackson.databind.SerializerProvider
;
import
com.fasterxml.jackson.databind.introspect.Annotated
;
import
com.fasterxml.jackson.databind.introspect.Annotated
;
import
com.fasterxml.jackson.databind.introspect.AnnotatedMethod
;
import
com.fasterxml.jackson.databind.introspect.AnnotatedMethod
;
import
com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
;
import
com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
;
...
@@ -38,6 +40,8 @@ import com.fasterxml.jackson.databind.ser.PropertyWriter;
...
@@ -38,6 +40,8 @@ import com.fasterxml.jackson.databind.ser.PropertyWriter;
import
com.fasterxml.jackson.databind.ser.SerializerFactory
;
import
com.fasterxml.jackson.databind.ser.SerializerFactory
;
import
com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter
;
import
com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter
;
import
com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider
;
import
com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.BeansException
;
import
org.springframework.boot.actuate.endpoint.Sanitizer
;
import
org.springframework.boot.actuate.endpoint.Sanitizer
;
...
@@ -68,7 +72,7 @@ import org.springframework.util.StringUtils;
...
@@ -68,7 +72,7 @@ import org.springframework.util.StringUtils;
@Endpoint
(
id
=
"configprops"
)
@Endpoint
(
id
=
"configprops"
)
public
class
ConfigurationPropertiesReportEndpoint
implements
ApplicationContextAware
{
public
class
ConfigurationPropertiesReportEndpoint
implements
ApplicationContextAware
{
private
static
final
String
C
GLIB_FILTER_ID
=
"cglib
Filter"
;
private
static
final
String
C
ONFIGURATION_PROPERTIES_FILTER_ID
=
"configurationProperties
Filter"
;
private
final
Sanitizer
sanitizer
=
new
Sanitizer
();
private
final
Sanitizer
sanitizer
=
new
Sanitizer
();
...
@@ -167,7 +171,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
...
@@ -167,7 +171,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
protected
void
configureObjectMapper
(
ObjectMapper
mapper
)
{
protected
void
configureObjectMapper
(
ObjectMapper
mapper
)
{
mapper
.
configure
(
SerializationFeature
.
FAIL_ON_EMPTY_BEANS
,
false
);
mapper
.
configure
(
SerializationFeature
.
FAIL_ON_EMPTY_BEANS
,
false
);
mapper
.
setSerializationInclusion
(
Include
.
NON_NULL
);
mapper
.
setSerializationInclusion
(
Include
.
NON_NULL
);
applyC
glibFilters
(
mapper
);
applyC
onfigurationPropertiesFilter
(
mapper
);
applySerializationModifier
(
mapper
);
applySerializationModifier
(
mapper
);
}
}
...
@@ -181,15 +185,11 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
...
@@ -181,15 +185,11 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
mapper
.
setSerializerFactory
(
factory
);
mapper
.
setSerializerFactory
(
factory
);
}
}
/**
private
void
applyConfigurationPropertiesFilter
(
ObjectMapper
mapper
)
{
* Configure PropertyFilter to make sure Jackson doesn't process CGLIB generated bean
mapper
.
setAnnotationIntrospector
(
* properties.
new
ConfigurationPropertiesAnnotationIntrospector
());
* @param mapper the object mapper
mapper
.
setFilterProvider
(
new
SimpleFilterProvider
()
*/
.
setDefaultFilter
(
new
ConfigurationPropertiesPropertyFilter
()));
private
void
applyCglibFilters
(
ObjectMapper
mapper
)
{
mapper
.
setAnnotationIntrospector
(
new
CglibAnnotationIntrospector
());
mapper
.
setFilterProvider
(
new
SimpleFilterProvider
().
addFilter
(
CGLIB_FILTER_ID
,
new
CglibBeanPropertyFilter
()));
}
}
/**
/**
...
@@ -268,14 +268,14 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
...
@@ -268,14 +268,14 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
* properties.
* properties.
*/
*/
@SuppressWarnings
(
"serial"
)
@SuppressWarnings
(
"serial"
)
private
static
class
C
glib
AnnotationIntrospector
private
static
class
C
onfigurationProperties
AnnotationIntrospector
extends
JacksonAnnotationIntrospector
{
extends
JacksonAnnotationIntrospector
{
@Override
@Override
public
Object
findFilterId
(
Annotated
a
)
{
public
Object
findFilterId
(
Annotated
a
)
{
Object
id
=
super
.
findFilterId
(
a
);
Object
id
=
super
.
findFilterId
(
a
);
if
(
id
==
null
)
{
if
(
id
==
null
)
{
id
=
C
GLIB
_FILTER_ID
;
id
=
C
ONFIGURATION_PROPERTIES
_FILTER_ID
;
}
}
return
id
;
return
id
;
}
}
...
@@ -283,10 +283,20 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
...
@@ -283,10 +283,20 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
}
}
/**
/**
* {@link SimpleBeanPropertyFilter} to filter out all bean properties whose names
* {@link SimpleBeanPropertyFilter} for serialization of
* start with '$$'.
* {@link ConfigurationProperties} beans. The filter hides:
*
* <ul>
* <li>Properties that have a name starting with '$$'.
* <li>Properties that are self-referential.
* <li>Properties that throw an exception when retrieving their value.
* </ul>
*/
*/
private
static
class
CglibBeanPropertyFilter
extends
SimpleBeanPropertyFilter
{
private
static
class
ConfigurationPropertiesPropertyFilter
extends
SimpleBeanPropertyFilter
{
private
static
final
Log
logger
=
LogFactory
.
getLog
(
ConfigurationPropertiesPropertyFilter
.
class
);
@Override
@Override
protected
boolean
include
(
BeanPropertyWriter
writer
)
{
protected
boolean
include
(
BeanPropertyWriter
writer
)
{
...
@@ -302,6 +312,31 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
...
@@ -302,6 +312,31 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return
!
name
.
startsWith
(
"$$"
);
return
!
name
.
startsWith
(
"$$"
);
}
}
@Override
public
void
serializeAsField
(
Object
pojo
,
JsonGenerator
jgen
,
SerializerProvider
provider
,
PropertyWriter
writer
)
throws
Exception
{
if
(
writer
instanceof
BeanPropertyWriter
)
{
try
{
if
(
pojo
==
((
BeanPropertyWriter
)
writer
).
get
(
pojo
))
{
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
"Skipping '"
+
writer
.
getFullName
()
+
"' on '"
+
pojo
.
getClass
().
getName
()
+
"' as it is self-referential"
);
}
return
;
}
}
catch
(
Exception
ex
)
{
if
(
logger
.
isDebugEnabled
())
{
logger
.
debug
(
"Skipping '"
+
writer
.
getFullName
()
+
"' on '"
+
pojo
.
getClass
().
getName
()
+
"' as an exception "
+
"was thrown when retrieving its value"
,
ex
);
}
return
;
}
}
super
.
serializeAsField
(
pojo
,
jgen
,
provider
,
writer
);
}
}
}
/**
/**
...
...
spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpointSerializationTests.java
View file @
cf485ce1
...
@@ -22,6 +22,8 @@ import java.util.HashMap;
...
@@ -22,6 +22,8 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
com.zaxxer.hikari.HikariDataSource
;
import
org.junit.Ignore
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor
;
import
org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint.ConfigurationPropertiesBeanDescriptor
;
...
@@ -87,9 +89,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -87,9 +89,10 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
}
}
@Test
@Test
public
void
testCycle
()
throws
Exception
{
@SuppressWarnings
(
"unchecked"
)
public
void
testSelfReferentialProperty
()
throws
Exception
{
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
.
withUserConfiguration
(
Cycle
Config
.
class
)
.
withUserConfiguration
(
SelfReferential
Config
.
class
)
.
withPropertyValues
(
"foo.name:foo"
);
.
withPropertyValues
(
"foo.name:foo"
);
contextRunner
.
run
((
context
)
->
{
contextRunner
.
run
((
context
)
->
{
ConfigurationPropertiesReportEndpoint
endpoint
=
context
ConfigurationPropertiesReportEndpoint
endpoint
=
context
...
@@ -97,12 +100,34 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -97,12 +100,34 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
ConfigurationPropertiesDescriptor
properties
=
endpoint
ConfigurationPropertiesDescriptor
properties
=
endpoint
.
configurationProperties
();
.
configurationProperties
();
ConfigurationPropertiesBeanDescriptor
foo
=
properties
.
getBeans
().
get
(
"foo"
);
ConfigurationPropertiesBeanDescriptor
foo
=
properties
.
getBeans
().
get
(
"foo"
);
assertThat
(
foo
).
isNotNull
();
assertThat
(
foo
.
getPrefix
()).
isEqualTo
(
"foo"
);
assertThat
(
foo
.
getPrefix
()).
isEqualTo
(
"foo"
);
Map
<
String
,
Object
>
map
=
foo
.
getProperties
();
Map
<
String
,
Object
>
map
=
foo
.
getProperties
();
assertThat
(
map
).
isNotNull
();
assertThat
(
map
).
isNotNull
();
assertThat
(
map
).
hasSize
(
1
);
assertThat
(
map
).
containsOnlyKeys
(
"bar"
,
"name"
);
assertThat
(
map
.
get
(
"error"
)).
isEqualTo
(
"Cannot serialize 'foo'"
);
assertThat
(
map
).
containsEntry
(
"name"
,
"foo"
);
Map
<
String
,
Object
>
bar
=
(
Map
<
String
,
Object
>)
map
.
get
(
"bar"
);
assertThat
(
bar
).
containsOnlyKeys
(
"name"
);
assertThat
(
bar
).
containsEntry
(
"name"
,
"123456"
);
});
}
@Test
@Ignore
(
"gh-11037"
)
public
void
testCycle
()
{
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
.
withUserConfiguration
(
CycleConfig
.
class
);
contextRunner
.
run
((
context
)
->
{
ConfigurationPropertiesReportEndpoint
endpoint
=
context
.
getBean
(
ConfigurationPropertiesReportEndpoint
.
class
);
ConfigurationPropertiesDescriptor
properties
=
endpoint
.
configurationProperties
();
ConfigurationPropertiesBeanDescriptor
cycle
=
properties
.
getBeans
()
.
get
(
"cycle"
);
assertThat
(
cycle
.
getPrefix
()).
isEqualTo
(
"cycle"
);
Map
<
String
,
Object
>
map
=
cycle
.
getProperties
();
assertThat
(
map
).
isNotNull
();
assertThat
(
map
).
containsOnlyKeys
(
"error"
);
assertThat
(
map
).
containsEntry
(
"error"
,
"Cannot serialize 'cycle'"
);
});
});
}
}
...
@@ -191,7 +216,6 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -191,7 +216,6 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
@Test
@Test
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
public
void
testInitializedMapAndList
()
throws
Exception
{
public
void
testInitializedMapAndList
()
throws
Exception
{
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
.
withUserConfiguration
(
InitializedMapAndListPropertiesConfig
.
class
)
.
withUserConfiguration
(
InitializedMapAndListPropertiesConfig
.
class
)
...
@@ -213,6 +237,22 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -213,6 +237,22 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
});
});
}
}
@Test
public
void
hikariDataSourceConfigurationPropertiesBeanCanBeSerialized
()
{
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
.
withUserConfiguration
(
HikariDataSourceConfig
.
class
);
contextRunner
.
run
((
context
)
->
{
ConfigurationPropertiesReportEndpoint
endpoint
=
context
.
getBean
(
ConfigurationPropertiesReportEndpoint
.
class
);
ConfigurationPropertiesDescriptor
properties
=
endpoint
.
configurationProperties
();
ConfigurationPropertiesBeanDescriptor
hikariDataSource
=
properties
.
getBeans
()
.
get
(
"hikariDataSource"
);
Map
<
String
,
Object
>
nestedProperties
=
hikariDataSource
.
getProperties
();
assertThat
(
nestedProperties
).
doesNotContainKey
(
"error"
);
});
}
@Configuration
@Configuration
@EnableConfigurationProperties
@EnableConfigurationProperties
public
static
class
Base
{
public
static
class
Base
{
...
@@ -238,12 +278,12 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -238,12 +278,12 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
@Configuration
@Configuration
@Import
(
Base
.
class
)
@Import
(
Base
.
class
)
public
static
class
Cycle
Config
{
public
static
class
SelfReferential
Config
{
@Bean
@Bean
@ConfigurationProperties
(
prefix
=
"foo"
)
@ConfigurationProperties
(
prefix
=
"foo"
)
public
Cycle
foo
()
{
public
SelfReferential
foo
()
{
return
new
Cycle
();
return
new
SelfReferential
();
}
}
}
}
...
@@ -254,8 +294,8 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -254,8 +294,8 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
@Bean
@Bean
@ConfigurationProperties
(
prefix
=
"bar"
)
@ConfigurationProperties
(
prefix
=
"bar"
)
public
Cycle
foo
()
{
public
SelfReferential
foo
()
{
return
new
Cycle
();
return
new
SelfReferential
();
}
}
}
}
...
@@ -363,11 +403,11 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -363,11 +403,11 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
}
}
public
static
class
Cycle
extends
Foo
{
public
static
class
SelfReferential
extends
Foo
{
private
Foo
self
;
private
Foo
self
;
public
Cycle
()
{
public
SelfReferential
()
{
this
.
self
=
this
;
this
.
self
=
this
;
}
}
...
@@ -439,4 +479,58 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
...
@@ -439,4 +479,58 @@ public class ConfigurationPropertiesReportEndpointSerializationTests {
}
}
static
class
Cycle
{
private
final
Alpha
alpha
=
new
Alpha
(
this
);
public
Alpha
getAlpha
()
{
return
this
.
alpha
;
}
static
class
Alpha
{
private
final
Cycle
cycle
;
Alpha
(
Cycle
cycle
)
{
this
.
cycle
=
cycle
;
}
public
Cycle
getCycle
()
{
return
this
.
cycle
;
}
}
}
@Configuration
@Import
(
Base
.
class
)
static
class
CycleConfig
{
@Bean
// gh-11037
// @ConfigurationProperties(prefix = "cycle")
public
Cycle
cycle
()
{
return
new
Cycle
();
}
}
@Configuration
@EnableConfigurationProperties
static
class
HikariDataSourceConfig
{
@Bean
public
ConfigurationPropertiesReportEndpoint
endpoint
()
{
return
new
ConfigurationPropertiesReportEndpoint
();
}
@Bean
@ConfigurationProperties
(
prefix
=
"test.datasource"
)
public
HikariDataSource
hikariDataSource
()
{
return
new
HikariDataSource
();
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment