Ошибка Tomcat JPMS jakarta.security.auth.message

Я пытаюсь создать встроенный сервер Tomcat jpms.

    <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>

и это модуль-info.java:

module my_custom_module {
    requires org.slf4j;
    requires jakarta.servlet;
    requires org.apache.tomcat.jasper;
    requires org.apache.tomcat.catalina;
}

проект компилируется и запускается без проблем:

java --module-path target/lib/ -m my_custom_module/a.b.c.module.tomcat.MainClass   

это мой код:

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);
        }
    }
}

моя проблема:
когда я отправляю http-запрос, сервер выдает эту ошибку:

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 [email protected]/jakarta.security.auth.message.config.AuthConfigFactory.lambda$getFactory$0(AuthConfigFactory.java:82)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:571)
        at [email protected]/jakarta.security.auth.message.config.AuthConfigFactory.getFactory(AuthConfigFactory.java:76)
        at [email protected]/org.apache.catalina.authenticator.AuthenticatorBase.findJaspicProvider(AuthenticatorBase.java:1268)
        at [email protected]/org.apache.catalina.authenticator.AuthenticatorBase.getJaspicProvider(AuthenticatorBase.java:1261)
        at [email protected]/org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:473)
        at [email protected]/org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
        at [email protected]/org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
        at [email protected]/org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
        at [email protected]/org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
        at [email protected]/org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389)
        at [email protected]/org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
        at [email protected]/org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:896)
        at [email protected]/org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
        at [email protected]/org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
        at [email protected]/org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
        at [email protected]/org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
        at [email protected]/org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
        at java.base/java.lang.Thread.run(Thread.java:1583)

как исправить эту проблему?

Что такое «автономный сервер JPMS Tomcat»?

aled 24.05.2024 13:23

ой, извините, я имею в виду встроенный сервер Tomcat. Вопрос обновлен

mah454 24.05.2024 13:46

Что-то не так с ботом SO, слишком много отрицательных голосов по реальным проблемам, а голоса требуют более подробной информации. При этом не спрашивая в комментариях и не оставляя предложений для ОП.

Naman 24.05.2024 20:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
57
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В качестве временного решения вы можете добавить аргумент виртуальной машины в свои конфигурации, как указано в сообщении об исключении:

java.lang.IllegalAccessError: class jakarta.security.auth.message.config.AuthConfigFactory (in module jakarta.security.auth.message) 
cannot access class org.apache.catalina.authenticator.jaspic.AuthConfigFactoryImpl (in module org.apache.tomcat.catalina) 
because module jakarta.security.auth.message does not read module org.apache.tomcat.catalina

Это будет означать что-то вроде промежуточного решения:

--add-reads jakarta.security.auth.message=org.apache.tomcat.catalina

Хотя в идеале такой доступ не должен требоваться, а аргументы предназначены для целей совместимости.

это решение работает, спасибо, но есть ли какое-нибудь решение сделать это программно? я не могу использовать это решение в своем проекте!

mah454 24.05.2024 20:44

@ mah454 Не совсем уверен в процессе сборки tomcat, но в основном объявления их модулей должны обеспечивать как requires jakarta.security.auth.message, так и provides jakarta.security.auth.message.config.AuthConfigFactory with org.apache.catalina.authenticator.jaspic.AuthConfigFactoryIm‌​pl. Таким образом, это будет означать изменение в tomcat указанного объявления модуля.

Naman 28.05.2024 05:39
Ответ принят как подходящий

Зафиксированный ! простая проблема: Благодаря этому вопросу

только заменить:

Context context = tomcat.addWebapp(contextPath, appBase);

к

Context context = tomcat.addContext(contextPath, baseDir);

Другие вопросы по теме