I try to build jpms embedded tomcat server .
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>compile</scope>
</dependency>
<!-- Tomcat -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>10.1.24</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper</artifactId>
<version>10.1.24</version>
</dependency>
</dependencies>
and this is module-info.java:
module my_custom_module {
requires org.slf4j;
requires jakarta.servlet;
requires org.apache.tomcat.jasper;
requires org.apache.tomcat.catalina;
}
project compile and run without any problem :
java --module-path target/lib/ -m my_custom_module/a.b.c.module.tomcat.MainClass
this is my code:
import org.apache.catalina.Context;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;
public class HttpContainer {
public static final HttpContainer instance = new HttpContainer();
private static final Logger logger = LoggerFactory.getLogger(HttpContainer.class);
private static final String contextPath = "/api";
private static final String host = System.getenv("HTTP_SERVER_HOST");
private static final String port = System.getenv("HTTP_SERVER_PORT");
private static final String appBase = "/tmp/tomcat";
private static Tomcat tomcat;
private HttpContainer() {
createAppBaseDirectory();
TomcatURLStreamHandlerFactory.disable();
tomcat = new Tomcat();
tomcat.setHostname(Optional.ofNullable(host).orElse("0.0.0.0"));
tomcat.setPort(Integer.parseInt(Optional.ofNullable(port).orElse("8080")));
tomcat.setBaseDir(appBase);
Context context = tomcat.addWebapp(contextPath, appBase);
tomcat.addServlet(contextPath, "hello", new HelloServlet());
context.addServletMappingDecoded("/hello", "hello");
}
public void start() {
try {
tomcat.getConnector();
tomcat.start();
logger.info("Tomcat server started");
tomcat.getServer().await();
} catch (Exception e) {
logger.error("Tomcat error", e);
}
}
public void stop() {
try (Stream<Path> pathStream = Files.walk(Path.of(appBase))) {
pathStream.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(java.io.File::delete);
tomcat.stop();
logger.info("Tomcat server stopped");
} catch (Exception e) {
logger.error("Tomcat error", e);
}
}
private void createAppBaseDirectory() {
try {
Path appBasePath = Path.of(appBase);
if (!Files.exists(appBasePath)) {
Files.createDirectory(appBasePath);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
my problem:
when i send http request , server result this error :
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
May 24, 2024 1:59:21 PM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-nio-8080"]
May 24, 2024 1:59:21 PM org.apache.catalina.core.StandardService startInternal
INFO: Starting service [Tomcat]
May 24, 2024 1:59:21 PM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet engine: [Apache Tomcat/10.1.24]
May 24, 2024 1:59:21 PM org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
INFO: No global web.xml found
May 24, 2024 1:59:22 PM org.apache.jasper.servlet.TldScanner scanJars
INFO: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs
were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
May 24, 2024 1:59:22 PM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-nio-8080"]
May 24, 2024 1:59:24 PM org.apache.catalina.core.StandardHostValve invoke
SEVERE: Exception Processing [/api/hello]
java.lang.IllegalAccessError: class jakarta.security.auth.message.config.AuthConfigFactory (in module jakarta.security.auth.message) cannot access class org.apac
he.catalina.authenticator.jaspic.AuthConfigFactoryImpl (in module org.apache.tomcat.catalina) because module jakarta.security.auth.message does not read module o
rg.apache.tomcat.catalina
at jakarta.security.auth.message@3.0/jakarta.security.auth.message.config.AuthConfigFactory.lambda$getFactory$0(AuthConfigFactory.java:82)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:571)
at jakarta.security.auth.message@3.0/jakarta.security.auth.message.config.AuthConfigFactory.getFactory(AuthConfigFactory.java:76)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.authenticator.AuthenticatorBase.findJaspicProvider(AuthenticatorBase.java:1268)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.authenticator.AuthenticatorBase.getJaspicProvider(AuthenticatorBase.java:1261)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:473)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.tomcat.catalina@10.1.24/org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
at org.apache.tomcat.coyote@10.1.24/org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389)
at org.apache.tomcat.coyote@10.1.24/org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.tomcat.coyote@10.1.24/org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
at org.apache.tomcat.coyote@10.1.24/org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.coyote@10.1.24/org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util@10.1.24/org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
at org.apache.tomcat.util@10.1.24/org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util@10.1.24/org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:1583)
how to fix this problem ?
Fixed ! simple problem : Thanks to this question
only replace :
Context context = tomcat.addWebapp(contextPath, appBase);
to
Context context = tomcat.addContext(contextPath, baseDir);