Skip to content

Commit defde9b

Browse files
committed
Move server-specific knowledge out of general child context creation
Issue: 44200
1 parent 6d87bac commit defde9b

20 files changed

+650
-396
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ dependencies {
6666
optional("io.r2dbc:r2dbc-pool")
6767
optional("io.r2dbc:r2dbc-proxy")
6868
optional("io.r2dbc:r2dbc-spi")
69+
optional("io.undertow:undertow-servlet")
6970
optional("jakarta.jms:jakarta.jms-api")
7071
optional("jakarta.persistence:jakarta.persistence-api")
7172
optional("jakarta.servlet:jakarta.servlet-api")

spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/web/reactive/ReactiveManagementChildContextConfiguration.java

-137
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,19 @@
1616

1717
package org.springframework.boot.actuate.autoconfigure.web.reactive;
1818

19-
import java.io.File;
2019
import java.util.Collections;
2120
import java.util.Map;
2221

23-
import org.apache.catalina.Valve;
24-
import org.apache.catalina.valves.AccessLogValve;
25-
import org.eclipse.jetty.server.CustomRequestLog;
26-
import org.eclipse.jetty.server.RequestLog;
27-
import org.eclipse.jetty.server.RequestLogWriter;
28-
import org.eclipse.jetty.server.Server;
29-
3022
import org.springframework.beans.factory.ListableBeanFactory;
3123
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
3224
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
3325
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
3426
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementWebServerFactoryCustomizer;
35-
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3627
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
3728
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
38-
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
39-
import org.springframework.boot.web.embedded.tomcat.TomcatReactiveWebServerFactory;
40-
import org.springframework.boot.web.embedded.undertow.UndertowReactiveWebServerFactory;
4129
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
42-
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
4330
import org.springframework.context.ApplicationContext;
4431
import org.springframework.context.annotation.Bean;
45-
import org.springframework.core.Ordered;
4632
import org.springframework.http.server.reactive.ContextPathCompositeHandler;
4733
import org.springframework.http.server.reactive.HttpHandler;
4834
import org.springframework.util.StringUtils;
@@ -80,127 +66,4 @@ public HttpHandler httpHandler(ApplicationContext applicationContext, Management
8066
return httpHandler;
8167
}
8268

83-
@Bean
84-
@ConditionalOnClass(name = "io.undertow.Undertow")
85-
UndertowAccessLogCustomizer undertowManagementAccessLogCustomizer(ManagementServerProperties properties) {
86-
return new UndertowAccessLogCustomizer(properties);
87-
}
88-
89-
@Bean
90-
@ConditionalOnClass(name = "org.apache.catalina.valves.AccessLogValve")
91-
TomcatAccessLogCustomizer tomcatManagementAccessLogCustomizer(ManagementServerProperties properties) {
92-
return new TomcatAccessLogCustomizer(properties);
93-
}
94-
95-
@Bean
96-
@ConditionalOnClass(name = "org.eclipse.jetty.server.Server")
97-
JettyAccessLogCustomizer jettyManagementAccessLogCustomizer(ManagementServerProperties properties) {
98-
return new JettyAccessLogCustomizer(properties);
99-
}
100-
101-
abstract static class AccessLogCustomizer implements Ordered {
102-
103-
private final String prefix;
104-
105-
AccessLogCustomizer(String prefix) {
106-
this.prefix = prefix;
107-
}
108-
109-
protected String customizePrefix(String existingPrefix) {
110-
if (this.prefix == null) {
111-
return existingPrefix;
112-
}
113-
if (existingPrefix == null) {
114-
return this.prefix;
115-
}
116-
if (existingPrefix.startsWith(this.prefix)) {
117-
return existingPrefix;
118-
}
119-
return this.prefix + existingPrefix;
120-
}
121-
122-
@Override
123-
public int getOrder() {
124-
return 1;
125-
}
126-
127-
}
128-
129-
static class TomcatAccessLogCustomizer extends AccessLogCustomizer
130-
implements WebServerFactoryCustomizer<TomcatReactiveWebServerFactory> {
131-
132-
TomcatAccessLogCustomizer(ManagementServerProperties properties) {
133-
super(properties.getTomcat().getAccesslog().getPrefix());
134-
}
135-
136-
@Override
137-
public void customize(TomcatReactiveWebServerFactory factory) {
138-
AccessLogValve accessLogValve = findAccessLogValve(factory);
139-
if (accessLogValve == null) {
140-
return;
141-
}
142-
accessLogValve.setPrefix(customizePrefix(accessLogValve.getPrefix()));
143-
}
144-
145-
private AccessLogValve findAccessLogValve(TomcatReactiveWebServerFactory factory) {
146-
for (Valve engineValve : factory.getEngineValves()) {
147-
if (engineValve instanceof AccessLogValve accessLogValve) {
148-
return accessLogValve;
149-
}
150-
}
151-
return null;
152-
}
153-
154-
}
155-
156-
static class UndertowAccessLogCustomizer extends AccessLogCustomizer
157-
implements WebServerFactoryCustomizer<UndertowReactiveWebServerFactory> {
158-
159-
UndertowAccessLogCustomizer(ManagementServerProperties properties) {
160-
super(properties.getUndertow().getAccesslog().getPrefix());
161-
}
162-
163-
@Override
164-
public void customize(UndertowReactiveWebServerFactory factory) {
165-
factory.setAccessLogPrefix(customizePrefix(factory.getAccessLogPrefix()));
166-
}
167-
168-
}
169-
170-
static class JettyAccessLogCustomizer extends AccessLogCustomizer
171-
implements WebServerFactoryCustomizer<JettyReactiveWebServerFactory> {
172-
173-
JettyAccessLogCustomizer(ManagementServerProperties properties) {
174-
super(properties.getJetty().getAccesslog().getPrefix());
175-
}
176-
177-
@Override
178-
public void customize(JettyReactiveWebServerFactory factory) {
179-
factory.addServerCustomizers(this::customizeServer);
180-
}
181-
182-
private void customizeServer(Server server) {
183-
RequestLog requestLog = server.getRequestLog();
184-
if (requestLog instanceof CustomRequestLog customRequestLog) {
185-
customizeRequestLog(customRequestLog);
186-
}
187-
}
188-
189-
private void customizeRequestLog(CustomRequestLog requestLog) {
190-
if (requestLog.getWriter() instanceof RequestLogWriter requestLogWriter) {
191-
customizeRequestLogWriter(requestLogWriter);
192-
}
193-
}
194-
195-
private void customizeRequestLogWriter(RequestLogWriter writer) {
196-
String filename = writer.getFileName();
197-
if (StringUtils.hasLength(filename)) {
198-
File file = new File(filename);
199-
file = new File(file.getParentFile(), customizePrefix(file.getName()));
200-
writer.setFilename(file.getPath());
201-
}
202-
}
203-
204-
}
205-
20669
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.web.server;
18+
19+
import org.springframework.boot.web.server.WebServerFactory;
20+
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
21+
import org.springframework.core.Ordered;
22+
23+
/**
24+
* Base class for a {@link WebServerFactoryCustomizer} that customizes the web server's
25+
* access log.
26+
*
27+
* @param <T> the {@link WebServerFactory} type that can be customized
28+
* @author Andy Wilkinson
29+
* @since 4.0.0
30+
*/
31+
public abstract class AccessLogCustomizer<T extends WebServerFactory>
32+
implements WebServerFactoryCustomizer<T>, Ordered {
33+
34+
private final String prefix;
35+
36+
protected AccessLogCustomizer(String prefix) {
37+
this.prefix = prefix;
38+
}
39+
40+
protected String customizePrefix(String existingPrefix) {
41+
if (this.prefix == null) {
42+
return existingPrefix;
43+
}
44+
if (existingPrefix == null) {
45+
return this.prefix;
46+
}
47+
if (existingPrefix.startsWith(this.prefix)) {
48+
return existingPrefix;
49+
}
50+
return this.prefix + existingPrefix;
51+
}
52+
53+
@Override
54+
public int getOrder() {
55+
return 1;
56+
}
57+
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.web.server.jetty;
18+
19+
import java.io.File;
20+
21+
import org.eclipse.jetty.server.CustomRequestLog;
22+
import org.eclipse.jetty.server.RequestLog;
23+
import org.eclipse.jetty.server.RequestLogWriter;
24+
import org.eclipse.jetty.server.Server;
25+
26+
import org.springframework.boot.actuate.autoconfigure.web.server.AccessLogCustomizer;
27+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
28+
import org.springframework.boot.web.embedded.jetty.ConfigurableJettyWebServerFactory;
29+
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
30+
import org.springframework.util.StringUtils;
31+
32+
/**
33+
* {@link AccessLogCustomizer} for Jetty.
34+
*
35+
* @author Andy Wilkinson
36+
*/
37+
class JettyAccessLogCustomizer extends AccessLogCustomizer<ConfigurableJettyWebServerFactory>
38+
implements WebServerFactoryCustomizer<ConfigurableJettyWebServerFactory> {
39+
40+
JettyAccessLogCustomizer(ManagementServerProperties properties) {
41+
super(properties.getJetty().getAccesslog().getPrefix());
42+
}
43+
44+
@Override
45+
public void customize(ConfigurableJettyWebServerFactory factory) {
46+
factory.addServerCustomizers(this::customizeServer);
47+
}
48+
49+
private void customizeServer(Server server) {
50+
RequestLog requestLog = server.getRequestLog();
51+
if (requestLog instanceof CustomRequestLog customRequestLog) {
52+
customizeRequestLog(customRequestLog);
53+
}
54+
}
55+
56+
private void customizeRequestLog(CustomRequestLog requestLog) {
57+
if (requestLog.getWriter() instanceof RequestLogWriter requestLogWriter) {
58+
customizeRequestLogWriter(requestLogWriter);
59+
}
60+
}
61+
62+
private void customizeRequestLogWriter(RequestLogWriter writer) {
63+
String filename = writer.getFileName();
64+
if (StringUtils.hasLength(filename)) {
65+
File file = new File(filename);
66+
file = new File(file.getParentFile(), customizePrefix(file.getName()));
67+
writer.setFilename(file.getPath());
68+
}
69+
}
70+
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.web.server.jetty;
18+
19+
import org.eclipse.jetty.server.Server;
20+
21+
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
22+
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
23+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
27+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
28+
import org.springframework.context.annotation.Bean;
29+
30+
/**
31+
* {@link ManagementContextConfiguration @ManagementContextConfiguration} for Jetty-based
32+
* reactive web endpoint infrastructure when a separate management context running on a
33+
* different port is required.
34+
*
35+
* @author Andy Wilkinson
36+
*/
37+
@ConditionalOnClass(Server.class)
38+
@ConditionalOnWebApplication(type = Type.REACTIVE)
39+
@EnableConfigurationProperties(ManagementServerProperties.class)
40+
@ManagementContextConfiguration(value = ManagementContextType.CHILD, proxyBeanMethods = false)
41+
class JettyReactiveManagementChildContextConfiguration {
42+
43+
@Bean
44+
JettyAccessLogCustomizer jettyManagementAccessLogCustomizer(ManagementServerProperties properties) {
45+
return new JettyAccessLogCustomizer(properties);
46+
}
47+
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2012-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.actuate.autoconfigure.web.server.jetty;
18+
19+
import org.eclipse.jetty.server.Server;
20+
21+
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
22+
import org.springframework.boot.actuate.autoconfigure.web.ManagementContextType;
23+
import org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties;
24+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
26+
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
27+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
28+
import org.springframework.context.annotation.Bean;
29+
30+
/**
31+
* {@link ManagementContextConfiguration @ManagementContextConfiguration} for Jetty-based
32+
* servlet web endpoint infrastructure when a separate management context running on a
33+
* different port is required.
34+
*
35+
* @author Andy Wilkinson
36+
*/
37+
@ConditionalOnClass(Server.class)
38+
@ConditionalOnWebApplication(type = Type.SERVLET)
39+
@EnableConfigurationProperties(ManagementServerProperties.class)
40+
@ManagementContextConfiguration(value = ManagementContextType.CHILD, proxyBeanMethods = false)
41+
class JettyServletManagementChildContextConfiguration {
42+
43+
@Bean
44+
JettyAccessLogCustomizer jettyManagementAccessLogCustomizer(ManagementServerProperties properties) {
45+
return new JettyAccessLogCustomizer(properties);
46+
}
47+
48+
}

0 commit comments

Comments
 (0)