mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-17 12:09:16 +00:00
Replace TomcatStarter to break servlet dependency
Replace `TomcatStarter` with a `DeferredStartupExceptions` interface to break the direct dependency on `Servlet`. Closes gh-44325
This commit is contained in:
+31
-5
@@ -34,6 +34,7 @@ import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.web.server.MimeMappings;
|
||||
import org.springframework.boot.web.server.WebServerException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -46,7 +47,7 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public class TomcatEmbeddedContext extends StandardContext {
|
||||
|
||||
private @Nullable TomcatStarter starter;
|
||||
private DeferredStartupExceptions deferredStartupExceptions = DeferredStartupExceptions.NONE;
|
||||
|
||||
private @Nullable MimeMappings mimeMappings;
|
||||
|
||||
@@ -116,12 +117,17 @@ public class TomcatEmbeddedContext extends StandardContext {
|
||||
}
|
||||
}
|
||||
|
||||
public void setStarter(@Nullable TomcatStarter starter) {
|
||||
this.starter = starter;
|
||||
/**
|
||||
* Set the a strategy used to capture and rethrow deferred startup exceptions.
|
||||
* @param deferredStartupExceptions the strategy to use
|
||||
*/
|
||||
public void setDeferredStartupExceptions(DeferredStartupExceptions deferredStartupExceptions) {
|
||||
Assert.notNull(deferredStartupExceptions, "'deferredStartupExceptions' must not be null");
|
||||
this.deferredStartupExceptions = deferredStartupExceptions;
|
||||
}
|
||||
|
||||
@Nullable TomcatStarter getStarter() {
|
||||
return this.starter;
|
||||
DeferredStartupExceptions getDeferredStartupExceptions() {
|
||||
return this.deferredStartupExceptions;
|
||||
}
|
||||
|
||||
public void setMimeMappings(MimeMappings mimeMappings) {
|
||||
@@ -146,4 +152,24 @@ public class TomcatEmbeddedContext extends StandardContext {
|
||||
return (this.mimeMappings != null) ? this.mimeMappings.get(extension) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strategy interface that can be used to rethrow deferred startup exceptions.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface DeferredStartupExceptions {
|
||||
|
||||
/**
|
||||
* {@link DeferredStartupExceptions} that does nothing.
|
||||
*/
|
||||
DeferredStartupExceptions NONE = () -> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Rethrow deferred startup exceptions if there are any.
|
||||
* @throws Exception the deferred startup exception
|
||||
*/
|
||||
void rethrow() throws Exception;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-7
@@ -200,13 +200,7 @@ public class TomcatWebServer implements WebServer {
|
||||
Container[] children = this.tomcat.getHost().findChildren();
|
||||
for (Container container : children) {
|
||||
if (container instanceof TomcatEmbeddedContext embeddedContext) {
|
||||
TomcatStarter tomcatStarter = embeddedContext.getStarter();
|
||||
if (tomcatStarter != null) {
|
||||
Exception exception = tomcatStarter.getStartUpException();
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
embeddedContext.getDeferredStartupExceptions().rethrow();
|
||||
}
|
||||
if (!LifecycleState.STARTED.equals(container.getState())) {
|
||||
throw new IllegalStateException(container + " failed to start");
|
||||
|
||||
+11
-7
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.tomcat;
|
||||
package org.springframework.boot.tomcat.servlet;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.boot.tomcat.TomcatEmbeddedContext;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
|
||||
/**
|
||||
@@ -33,17 +34,17 @@ import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class TomcatStarter implements ServletContainerInitializer {
|
||||
class DeferredServletContainerInitializers
|
||||
implements ServletContainerInitializer, TomcatEmbeddedContext.DeferredStartupExceptions {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TomcatStarter.class);
|
||||
private static final Log logger = LogFactory.getLog(DeferredServletContainerInitializers.class);
|
||||
|
||||
private final Iterable<ServletContextInitializer> initializers;
|
||||
|
||||
private volatile @Nullable Exception startUpException;
|
||||
|
||||
public TomcatStarter(Iterable<ServletContextInitializer> initializers) {
|
||||
DeferredServletContainerInitializers(Iterable<ServletContextInitializer> initializers) {
|
||||
this.initializers = initializers;
|
||||
}
|
||||
|
||||
@@ -65,8 +66,11 @@ public class TomcatStarter implements ServletContainerInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable Exception getStartUpException() {
|
||||
return this.startUpException;
|
||||
@Override
|
||||
public void rethrow() throws Exception {
|
||||
if (this.startUpException != null) {
|
||||
throw this.startUpException;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -70,7 +70,6 @@ import org.springframework.boot.tomcat.DisableReferenceClearingContextCustomizer
|
||||
import org.springframework.boot.tomcat.TomcatContextCustomizer;
|
||||
import org.springframework.boot.tomcat.TomcatEmbeddedContext;
|
||||
import org.springframework.boot.tomcat.TomcatEmbeddedWebappClassLoader;
|
||||
import org.springframework.boot.tomcat.TomcatStarter;
|
||||
import org.springframework.boot.tomcat.TomcatWebServer;
|
||||
import org.springframework.boot.tomcat.TomcatWebServerFactory;
|
||||
import org.springframework.boot.web.error.ErrorPage;
|
||||
@@ -289,12 +288,13 @@ public class TomcatServletWebServerFactory extends TomcatWebServerFactory
|
||||
* @param initializers initializers to apply
|
||||
*/
|
||||
protected void configureContext(Context context, Iterable<ServletContextInitializer> initializers) {
|
||||
TomcatStarter starter = new TomcatStarter(initializers);
|
||||
DeferredServletContainerInitializers deferredInitializers = new DeferredServletContainerInitializers(
|
||||
initializers);
|
||||
if (context instanceof TomcatEmbeddedContext embeddedContext) {
|
||||
embeddedContext.setStarter(starter);
|
||||
embeddedContext.setDeferredStartupExceptions(deferredInitializers);
|
||||
embeddedContext.setFailCtxIfServletStartFails(true);
|
||||
}
|
||||
context.addServletContainerInitializer(starter, NO_CLASSES);
|
||||
context.addServletContainerInitializer(deferredInitializers, NO_CLASSES);
|
||||
for (LifecycleListener lifecycleListener : this.getContextLifecycleListeners()) {
|
||||
context.addLifecycleListener(lifecycleListener);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user