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
94c35ae1
Commit
94c35ae1
authored
Jul 23, 2019
by
Stephane Nicoll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Polish "Make Actuator dedicated ConversionService configurable"
See gh-16449
parent
2aea4375
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
70 additions
and
133 deletions
+70
-133
EndpointAutoConfiguration.java
...ate/autoconfigure/endpoint/EndpointAutoConfiguration.java
+20
-53
EndpointAutoConfigurationTests.java
...utoconfigure/endpoint/EndpointAutoConfigurationTests.java
+42
-67
EndpointConverter.java
...k/boot/actuate/endpoint/annotation/EndpointConverter.java
+6
-11
production-ready-features.adoc
...oot-docs/src/main/asciidoc/production-ready-features.adoc
+2
-2
No files found.
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.java
View file @
94c35ae1
...
...
@@ -16,21 +16,18 @@
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
endpoint
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.ListableBeanFactory
;
import
org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils
;
import
org.springframework.beans.factory.ObjectProvider
;
import
org.springframework.boot.actuate.endpoint.annotation.Endpoint
;
import
org.springframework.boot.actuate.endpoint.annotation.EndpointConverter
;
import
org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper
;
import
org.springframework.boot.actuate.endpoint.invoke.convert.ConversionServiceParameterValueMapper
;
import
org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor
;
import
org.springframework.boot.autoconfigure.EnableAutoConfiguration
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
;
import
org.springframework.boot.convert.ApplicationConversionService
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.convert.ConversionService
;
...
...
@@ -53,9 +50,23 @@ public class EndpointAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public
ParameterValueMapper
endpointOperationParameterMapper
(
ApplicationContext
applicationContext
)
{
return
new
ConversionServiceParameterValueMapper
(
new
Factory
(
applicationContext
.
getAutowireCapableBeanFactory
()).
create
());
@EndpointConverter
ObjectProvider
<
Converter
<?,
?>>
converters
,
@EndpointConverter
ObjectProvider
<
GenericConverter
>
genericConverters
)
{
ConversionService
conversionService
=
createConversionService
(
converters
.
orderedStream
().
collect
(
Collectors
.
toList
()),
genericConverters
.
orderedStream
().
collect
(
Collectors
.
toList
()));
return
new
ConversionServiceParameterValueMapper
(
conversionService
);
}
private
ConversionService
createConversionService
(
List
<
Converter
<?,
?>>
converters
,
List
<
GenericConverter
>
genericConverters
)
{
if
(
genericConverters
.
isEmpty
()
&&
converters
.
isEmpty
())
{
return
ApplicationConversionService
.
getSharedInstance
();
}
ApplicationConversionService
conversionService
=
new
ApplicationConversionService
();
converters
.
forEach
(
conversionService:
:
addConverter
);
genericConverters
.
forEach
(
conversionService:
:
addConverter
);
return
conversionService
;
}
@Bean
...
...
@@ -64,48 +75,4 @@ public class EndpointAutoConfiguration {
return
new
CachingOperationInvokerAdvisor
(
new
EndpointIdTimeToLivePropertyFunction
(
environment
));
}
private
static
class
Factory
{
@SuppressWarnings
(
"rawtypes"
)
private
final
List
<
Converter
>
converters
;
private
final
List
<
GenericConverter
>
genericConverters
;
Factory
(
BeanFactory
beanFactory
)
{
this
.
converters
=
beans
(
beanFactory
,
Converter
.
class
,
EndpointConverter
.
VALUE
);
this
.
genericConverters
=
beans
(
beanFactory
,
GenericConverter
.
class
,
EndpointConverter
.
VALUE
);
}
private
<
T
>
List
<
T
>
beans
(
BeanFactory
beanFactory
,
Class
<
T
>
type
,
String
qualifier
)
{
if
(
beanFactory
instanceof
ListableBeanFactory
)
{
return
beans
(
type
,
qualifier
,
(
ListableBeanFactory
)
beanFactory
);
}
return
Collections
.
emptyList
();
}
private
<
T
>
List
<
T
>
beans
(
Class
<
T
>
type
,
String
qualifier
,
ListableBeanFactory
beanFactory
)
{
return
new
ArrayList
<>(
BeanFactoryAnnotationUtils
.
qualifiedBeansOfType
(
beanFactory
,
type
,
qualifier
).
values
());
}
public
ConversionService
create
()
{
if
(
this
.
converters
.
isEmpty
()
&&
this
.
genericConverters
.
isEmpty
())
{
return
ApplicationConversionService
.
getSharedInstance
();
}
ApplicationConversionService
conversionService
=
new
ApplicationConversionService
();
for
(
Converter
<?,
?>
converter
:
this
.
converters
)
{
conversionService
.
addConverter
(
converter
);
}
for
(
GenericConverter
genericConverter
:
this
.
genericConverters
)
{
conversionService
.
addConverter
(
genericConverter
);
}
return
conversionService
;
}
}
}
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfigurationTests.java
View file @
94c35ae1
/*
* Copyright 2012-201
8
the original author or authors.
* Copyright 2012-201
9
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.
...
...
@@ -19,13 +19,14 @@ package org.springframework.boot.actuate.autoconfigure.endpoint;
import
java.util.Collections
;
import
java.util.Set
;
import
org.junit.Test
;
import
org.junit.
jupiter.api.
Test
;
import
org.springframework.boot.actuate.endpoint.annotation.EndpointConverter
;
import
org.springframework.boot.actuate.endpoint.invoke.OperationParameter
;
import
org.springframework.boot.actuate.endpoint.invoke.ParameterMappingException
;
import
org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper
;
import
org.springframework.boot.autoconfigure.AutoConfigurations
;
import
org.springframework.boot.test.context.runner.
Web
ApplicationContextRunner
;
import
org.springframework.boot.test.context.runner.ApplicationContextRunner
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.convert.ConverterNotFoundException
;
...
...
@@ -42,72 +43,55 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
*
* @author Chao Chang
*/
public
class
EndpointAutoConfigurationTests
{
class
EndpointAutoConfigurationTests
{
private
static
final
AutoConfigurations
CONFIGURATIONS
=
AutoConfigurations
.
of
(
EndpointAutoConfiguration
.
class
);
private
WebApplicationContextRunner
contextRunner
=
new
WebApplicationContextRunner
()
.
withConfiguration
(
CONFIGURATIONS
);
private
final
ApplicationContextRunner
contextRunner
=
new
ApplicationContextRunner
()
.
withConfiguration
(
AutoConfigurations
.
of
(
EndpointAutoConfiguration
.
class
));
@Test
public
void
mapShouldUseConfigurationConverter
()
{
this
.
contextRunner
.
withUserConfiguration
(
ConverterConfiguration
.
class
)
.
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
Object
paramValue
=
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
assertThat
(
paramValue
).
isInstanceOf
(
Person
.
class
);
Person
person
=
(
Person
)
paramValue
;
assertThat
(
person
.
firstName
).
isEqualTo
(
"John"
);
assertThat
(
person
.
lastName
).
isEqualTo
(
"Smith"
);
});
void
mapShouldUseConfigurationConverter
()
{
this
.
contextRunner
.
withUserConfiguration
(
ConverterConfiguration
.
class
).
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
Object
paramValue
=
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
assertThat
(
paramValue
).
isInstanceOf
(
Person
.
class
);
Person
person
=
(
Person
)
paramValue
;
assertThat
(
person
.
firstName
).
isEqualTo
(
"John"
);
assertThat
(
person
.
lastName
).
isEqualTo
(
"Smith"
);
});
}
@Test
public
void
mapWhenConfigurationConverterIsNotQualifiedShouldNotConvert
()
{
void
mapWhenConfigurationConverterIsNotQualifiedShouldNotConvert
()
{
assertThatExceptionOfType
(
ParameterMappingException
.
class
).
isThrownBy
(()
->
{
this
.
contextRunner
.
withUserConfiguration
(
NonQualifiedConverterConfiguration
.
class
)
.
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
});
this
.
contextRunner
.
withUserConfiguration
(
NonQualifiedConverterConfiguration
.
class
).
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
});
}).
withCauseInstanceOf
(
ConverterNotFoundException
.
class
);
}
@Test
public
void
mapShouldUseGenericConfigurationConverter
()
{
this
.
contextRunner
.
withUserConfiguration
(
GenericConverterConfiguration
.
class
)
.
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
Object
paramValue
=
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
assertThat
(
paramValue
).
isInstanceOf
(
Person
.
class
);
Person
person
=
(
Person
)
paramValue
;
assertThat
(
person
.
firstName
).
isEqualTo
(
"John"
);
assertThat
(
person
.
lastName
).
isEqualTo
(
"Smith"
);
});
void
mapShouldUseGenericConfigurationConverter
()
{
this
.
contextRunner
.
withUserConfiguration
(
GenericConverterConfiguration
.
class
).
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
Object
paramValue
=
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
assertThat
(
paramValue
).
isInstanceOf
(
Person
.
class
);
Person
person
=
(
Person
)
paramValue
;
assertThat
(
person
.
firstName
).
isEqualTo
(
"John"
);
assertThat
(
person
.
lastName
).
isEqualTo
(
"Smith"
);
});
}
@Test
public
void
mapWhenGenericConfigurationConverterIsNotQualifiedShouldNotConvert
()
{
void
mapWhenGenericConfigurationConverterIsNotQualifiedShouldNotConvert
()
{
assertThatExceptionOfType
(
ParameterMappingException
.
class
).
isThrownBy
(()
->
{
this
.
contextRunner
.
withUserConfiguration
(
NonQualifiedGenericConverterConfiguration
.
class
)
.
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
});
this
.
contextRunner
.
withUserConfiguration
(
NonQualifiedGenericConverterConfiguration
.
class
).
run
((
context
)
->
{
ParameterValueMapper
parameterValueMapper
=
context
.
getBean
(
ParameterValueMapper
.
class
);
parameterValueMapper
.
mapParameterValue
(
new
TestOperationParameter
(
Person
.
class
),
"John Smith"
);
});
}).
withCauseInstanceOf
(
ConverterNotFoundException
.
class
);
...
...
@@ -131,8 +115,7 @@ public class EndpointAutoConfigurationTests {
}
@Override
public
Object
convert
(
Object
source
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
)
{
public
Object
convert
(
Object
source
,
TypeDescriptor
sourceType
,
TypeDescriptor
targetType
)
{
String
[]
content
=
StringUtils
.
split
((
String
)
source
,
" "
);
return
new
Person
(
content
[
0
],
content
[
1
]);
}
...
...
@@ -144,7 +127,7 @@ public class EndpointAutoConfigurationTests {
@Bean
@EndpointConverter
public
Converter
<
String
,
Person
>
personConverter
()
{
Converter
<
String
,
Person
>
personConverter
()
{
return
new
PersonConverter
();
}
...
...
@@ -154,7 +137,7 @@ public class EndpointAutoConfigurationTests {
static
class
NonQualifiedConverterConfiguration
{
@Bean
public
Converter
<
String
,
Person
>
personConverter
()
{
Converter
<
String
,
Person
>
personConverter
()
{
return
new
PersonConverter
();
}
...
...
@@ -165,7 +148,7 @@ public class EndpointAutoConfigurationTests {
@Bean
@EndpointConverter
public
GenericConverter
genericPersonConverter
()
{
GenericConverter
genericPersonConverter
()
{
return
new
GenericPersonConverter
();
}
...
...
@@ -175,7 +158,7 @@ public class EndpointAutoConfigurationTests {
static
class
NonQualifiedGenericConverterConfiguration
{
@Bean
public
GenericConverter
genericPersonConverter
()
{
GenericConverter
genericPersonConverter
()
{
return
new
GenericPersonConverter
();
}
...
...
@@ -192,14 +175,6 @@ public class EndpointAutoConfigurationTests {
this
.
lastName
=
lastName
;
}
public
String
getFirstName
()
{
return
this
.
firstName
;
}
public
String
getLastName
()
{
return
this
.
lastName
;
}
}
private
static
class
TestOperationParameter
implements
OperationParameter
{
...
...
spring-boot-project/spring-boot-actuator
-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint
/EndpointConverter.java
→
spring-boot-project/spring-boot-actuator
/src/main/java/org/springframework/boot/actuate/endpoint/annotation
/EndpointConverter.java
View file @
94c35ae1
/*
* Copyright 2012-201
8
the original author or authors.
* Copyright 2012-201
9
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.
...
...
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
actuate
.
autoconfigure
.
endpoint
;
package
org
.
springframework
.
boot
.
actuate
.
endpoint
.
annotation
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
...
...
@@ -23,22 +23,17 @@ import java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.boot.actuate.endpoint.annotation.Endpoint
;
/**
* Qualifier for beans that are needed to
be converters for {@link Endpoint}
.
* Qualifier for beans that are needed to
convert {@link Endpoint} input parameters
.
*
* @author Chao Chang
* @since 2.2.0
*/
@Qualifier
(
EndpointConverter
.
VALUE
)
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Target
({
ElementType
.
FIELD
,
ElementType
.
METHOD
,
ElementType
.
PARAMETER
,
ElementType
.
TYPE
,
ElementType
.
ANNOTATION_TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Qualifier
public
@interface
EndpointConverter
{
/**
* Concrete value for the {@link Qualifier @Qualifier}.
*/
String
VALUE
=
"org.springframework.boot.actuate.autoconfigure.endpoint.EndpointConverter"
;
}
spring-boot-project/spring-boot-docs/src/main/asciidoc/production-ready-features.adoc
View file @
94c35ae1
...
...
@@ -558,8 +558,8 @@ automatically if you are using Spring Boot's Gradle plugin or if you are using M
The parameters passed to endpoint operation methods are, if necessary, automatically
converted to the required type. Before calling an operation method, the input received via
JMX or an HTTP request is converted to the required types using an instance of
`ApplicationConversionService`
.
`ApplicationConversionService`
as well as any `Converter` or `GenericConverter` beans
qualified with `@EndpointConverter`.
[[production-ready-endpoints-custom-web]]
...
...
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