New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebFlux app can't start if management.server.port is customized #2980
WebFlux app can't start if management.server.port is customized #2980
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2980 +/- ##
============================================
+ Coverage 73.22% 73.23% +0.01%
- Complexity 12280 12292 +12
============================================
Files 1060 1060
Lines 47681 47695 +14
Branches 6021 6027 +6
============================================
+ Hits 34914 34930 +16
+ Misses 9715 9714 -1
+ Partials 3052 3051 -1 Continue to review full report at Codecov.
|
|
||
private boolean isManagementPortEqualsToServerPort() { | ||
final Integer managementPort = environment.getProperty("management.server.port", Integer.class); | ||
if (managementPort != null && managementPort < 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about calling ensureValidPort(managementPort)
so that an exception is raised if it's under 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, how about returning early if managementPort
is null
?
@@ -131,6 +140,11 @@ public ArmeriaReactiveWebServerFactory(ConfigurableListableBeanFactory beanFacto | |||
|
|||
@Override | |||
public WebServer getWebServer(HttpHandler httpHandler) { | |||
final int port = ensureValidPort(getPort()); | |||
if (armeriaWebServer != null && needsToReuseWebServer(port)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If armeriaWebServer
is not null and the port is different, it seems like the previously configured settings to armeriaWebServer
are gone. Isn't it right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previously configured settings remains.
I'll add some tests to check this.
updated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for fixing this.
final ArmeriaWebServer armeriaWebServer = new ArmeriaWebServer(server, protocol, address, port, | ||
beanFactory); | ||
if (!isManagementPortEqualsToServerPort()) { | ||
// Since this method will be called twice, need to reuse ArmeriaWebServer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about leaving a comment?
The management port is set to the Server in ArmeriaSpringActuatorAutoConfiguration.
Updated the comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent work, @matsumana
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! @matsumana
"65536", | ||
}) | ||
void isManagementPortEqualsToServerPortThrows(String managementPort) { | ||
assertThrows(IllegalArgumentException.class, () -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use assertThatThrownBy(...)
.path(0) | ||
.textValue()) | ||
.isEqualTo("/hello/foo"); | ||
} catch (JsonProcessingException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just throws the exception?
@matsumana Let me merge once @ikhoon's comments are addressed. |
updated! |
Thanks a lot, @matsumana |
Thank you guys! |
…#2980) If users customize WebFlux app's `management.server.port` setting as follows, the app can't start. ```yaml # e.g. management: server: port: 18080 ``` Because if `management.server.port` is not equal to `server.port`, [DifferentManagementContextConfiguration](https://github.com/spring-projects/spring-boot/blob/v2.3.2.RELEASE/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration.java#L115-L116) will be enabled then `ArmeriaReactiveWebServerFactory#getWebServer(HttpHandler)` will be called twice. The process flow is the following. 1st call of `ArmeriaReactiveWebServerFactory#getWebServer(HttpHandler)`: - https://github.com/spring-projects/spring-framework/blob/v5.2.8.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L554 - https://github.com/spring-projects/spring-framework/blob/v5.2.8.RELEASE/spring-context/src/main/java/org/springframework/context/support/AbstractApplicationContext.java#L895 - https://github.com/spring-projects/spring-framework/blob/v5.2.8.RELEASE/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java#L122 - https://github.com/spring-projects/spring-framework/blob/v5.2.8.RELEASE/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java#L158 - https://github.com/spring-projects/spring-framework/blob/v5.2.8.RELEASE/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java#L360 - https://github.com/spring-projects/spring-framework/blob/v5.2.8.RELEASE/spring-context/src/main/java/org/springframework/context/support/DefaultLifecycleProcessor.java#L182 - https://github.com/spring-projects/spring-boot/blob/v2.3.2.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerStartStopLifecycle.java#L40 - https://github.com/spring-projects/spring-boot/blob/v2.3.2.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerManager.java#L54 - https://github.com/line/armeria/blob/armeria-0.99.9/spring/boot2-webflux-autoconfigure/src/main/java/com/linecorp/armeria/spring/web/ArmeriaWebServer.java#L82 Then, 2nd time ApplicationContext refreshing will be started by `DifferentManagementContextConfiguration#onApplicationEvent(WebServerInitializedEvent)`. - https://github.com/spring-projects/spring-boot/blob/v2.3.2.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/WebServerManager.java#L55-L56 - https://github.com/spring-projects/spring-boot/blob/v2.3.2.RELEASE/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/server/ManagementContextAutoConfiguration.java#L131-L142 I investigated whether I can stop ApplicationContext refreshing by `DifferentManagementContextConfiguration#onApplicationEvent(WebServerInitializedEvent)`. But I couldn't find a way to customize. So I added ArmeriaWebServer field into ArmeriaReactiveWebServerFactory to cache it.
Hi.
If users customize WebFlux app's
management.server.port
setting as follows, the app can't start.Because if
management.server.port
is not equals toserver.port
, DifferentManagementContextConfiguration will be enabled thenArmeriaReactiveWebServerFactory#getWebServer(HttpHandler)
will be called twice.The process flow is the following.
1st call of
ArmeriaReactiveWebServerFactory#getWebServer(HttpHandler)
:Then, 2nd time ApplicationContext refreshing will be started by
DifferentManagementContextConfiguration#onApplicationEvent(WebServerInitializedEvent)
.I investigated whether I can stop ApplicationContext refreshing by
DifferentManagementContextConfiguration#onApplicationEvent(WebServerInitializedEvent)
.But I couldn't find a way to customize.
So I added ArmeriaWebServer field into ArmeriaReactiveWebServerFactory to cache it.