Enable virtual threads on Tomcat
Closes gh-35704
This commit is contained in:
@@ -28,6 +28,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.JettyWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.NettyWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.UndertowWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryCustomizer;
|
||||
@@ -76,7 +77,8 @@ public class ReactiveManagementChildContextConfiguration {
|
||||
|
||||
ReactiveManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) {
|
||||
super(beanFactory, ReactiveWebServerFactoryCustomizer.class, TomcatWebServerFactoryCustomizer.class,
|
||||
TomcatReactiveWebServerFactoryCustomizer.class, JettyWebServerFactoryCustomizer.class,
|
||||
TomcatReactiveWebServerFactoryCustomizer.class,
|
||||
TomcatVirtualThreadsWebServerFactoryCustomizer.class, JettyWebServerFactoryCustomizer.class,
|
||||
UndertowWebServerFactoryCustomizer.class, NettyWebServerFactoryCustomizer.class);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplicat
|
||||
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.JettyWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.TomcatVirtualThreadsWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.TomcatWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.embedded.UndertowWebServerFactoryCustomizer;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryCustomizer;
|
||||
@@ -122,8 +123,9 @@ class ServletManagementChildContextConfiguration {
|
||||
|
||||
ServletManagementWebServerFactoryCustomizer(ListableBeanFactory beanFactory) {
|
||||
super(beanFactory, ServletWebServerFactoryCustomizer.class, TomcatServletWebServerFactoryCustomizer.class,
|
||||
TomcatWebServerFactoryCustomizer.class, JettyWebServerFactoryCustomizer.class,
|
||||
UndertowServletWebServerFactoryCustomizer.class, UndertowWebServerFactoryCustomizer.class);
|
||||
TomcatWebServerFactoryCustomizer.class, TomcatVirtualThreadsWebServerFactoryCustomizer.class,
|
||||
JettyWebServerFactoryCustomizer.class, UndertowServletWebServerFactoryCustomizer.class,
|
||||
UndertowWebServerFactoryCustomizer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWarDeployment;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnVirtualThreads;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@@ -62,6 +63,12 @@ public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {
|
||||
return new TomcatWebServerFactoryCustomizer(environment, serverProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnVirtualThreads
|
||||
TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() {
|
||||
return new TomcatVirtualThreadsWebServerFactoryCustomizer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.web.embedded;
|
||||
|
||||
import org.apache.coyote.ProtocolHandler;
|
||||
import org.apache.tomcat.util.threads.VirtualThreadExecutor;
|
||||
|
||||
import org.springframework.boot.web.embedded.tomcat.ConfigurableTomcatWebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
/**
|
||||
* Activates {@link VirtualThreadExecutor} on {@link ProtocolHandler Tomcat's protocol
|
||||
* handler}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public class TomcatVirtualThreadsWebServerFactoryCustomizer
|
||||
implements WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered {
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableTomcatWebServerFactory factory) {
|
||||
factory.addProtocolHandlerCustomizers(
|
||||
(protocolHandler) -> protocolHandler.setExecutor(new VirtualThreadExecutor("tomcat-handler-")));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return TomcatWebServerFactoryCustomizer.order + 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,6 +67,8 @@ import org.springframework.util.unit.DataSize;
|
||||
public class TomcatWebServerFactoryCustomizer
|
||||
implements WebServerFactoryCustomizer<ConfigurableTomcatWebServerFactory>, Ordered {
|
||||
|
||||
static final int order = 0;
|
||||
|
||||
private final Environment environment;
|
||||
|
||||
private final ServerProperties serverProperties;
|
||||
@@ -78,7 +80,7 @@ public class TomcatWebServerFactoryCustomizer
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2012-2023 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.web.embedded;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.apache.tomcat.util.threads.VirtualThreadExecutor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link TomcatVirtualThreadsWebServerFactoryCustomizer}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class TomcatVirtualThreadsWebServerFactoryCustomizerTests {
|
||||
|
||||
private final TomcatVirtualThreadsWebServerFactoryCustomizer customizer = new TomcatVirtualThreadsWebServerFactoryCustomizer();
|
||||
|
||||
@Test
|
||||
@EnabledForJreRange(min = JRE.JAVA_21)
|
||||
void shouldSetVirtualThreadExecutor() {
|
||||
withWebServer((webServer) -> assertThat(webServer.getTomcat().getConnector().getProtocolHandler().getExecutor())
|
||||
.isInstanceOf(VirtualThreadExecutor.class));
|
||||
}
|
||||
|
||||
private TomcatWebServer getWebServer() {
|
||||
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
|
||||
this.customizer.customize(factory);
|
||||
return (TomcatWebServer) factory.getWebServer();
|
||||
}
|
||||
|
||||
private void withWebServer(Consumer<TomcatWebServer> callback) {
|
||||
TomcatWebServer webServer = getWebServer();
|
||||
webServer.start();
|
||||
try {
|
||||
callback.accept(webServer);
|
||||
}
|
||||
finally {
|
||||
webServer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user