Приложение Undertow не запускается при запуске jar с зависимостями - PullRequest
1 голос
/ 06 марта 2019

Я тренируюсь с Kotlin и хочу запустить легкое приложение Rest. У меня есть опыт работы с Undertow с Джерси, Джексоном и Weld CDI на Java.

Я написал минимум для запуска веб-контейнера, и он прекрасно работает в IntelliJ. Хотя, когда я пытаюсь запустить jar-with-dependencies с java -jar app-with-dependencies.jar, я получаю ошибки.

Основной класс:

package nl.orhun.samplerestapp

import io.undertow.Handlers
import io.undertow.Undertow
import io.undertow.servlet.Servlets
import io.undertow.servlet.Servlets.servlet
import nl.orhun.samplerestapp.config.JerseyConfig
import org.glassfish.jersey.servlet.ServletContainer
import org.jboss.weld.environment.servlet.Listener

fun main() {
    val servletBuilder = Servlets.deployment()

    servletBuilder.setClassLoader(ClassLoader.getSystemClassLoader())
            .setContextPath("/app")
            .setDeploymentName("app.war")
            .addListener(Servlets.listener(Listener::class.java))
            .addServlets(
                    servlet("jerseyServlet", ServletContainer::class.java)
                            .setLoadOnStartup(1)
                            .addInitParam("javax.ws.rs.Application", JerseyConfig::class.java.name)
                            .addMapping("/rest/*")
            )

    val manager = Servlets.defaultContainer().addDeployment(servletBuilder)
    manager.deploy()

    val path = Handlers.path(Handlers.redirect("/app"))
            .addPrefixPath("/app", manager.start())

    val server = Undertow.builder()
            .addHttpListener(8090, "localhost")
            .setHandler(path)
            .build()
    server.start()
}

Ошибка:

$ java -jar target/nl.orhun.samplerestapi-1.0-SNAPSHOT-jar-with-dependencies.jar
Mar 06, 2019 9:04:48 PM org.jboss.weld.environment.servlet.Listener contextInitialized
INFO: WELD-ENV-001007: Initialize Weld using ServletContextListener
Mar 06, 2019 9:04:48 PM org.jboss.weld.bootstrap.WeldStartup <clinit>
INFO: WELD-000900: 2.4.8 (Final)
Mar 06, 2019 9:04:48 PM org.jboss.weld.bootstrap.WeldStartup startContainer
INFO: WELD-000101: Transactional services not available. Injection of @Inject UserTransaction not available. Transactional observers will be invoked synchronously.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from org.glassfish.hk2.osgiresourcelocator.ServiceLoaderImpl because of underlying class loading error: Type org.osgi.framework.BundleListener not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from org.jboss.logging.JBossLogManagerLogger because of underlying class loading error: Type org.jboss.logmanager.Level not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from org.jboss.weld.injection.spi.helpers.ForwardingJpaInjectionServices because of underlying class loading error: Type javax.persistence.EntityManager not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from io.undertow.servlet.osgi.Activator because of underlying class loading error: Type org.osgi.framework.BundleActivator not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from org.jboss.weld.jsf.FacesUrlTransformer because of underlying class loading error: Type javax.faces.context.FacesContext not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from org.glassfish.jersey.internal.OsgiRegistry$OsgiServiceFinder because of underlying class loading error: Type org.osgi.framework.SynchronousBundleListener not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
INFO: WELD-000119: Not generating any bean definitions from org.glassfish.jersey.server.internal.scanning.PackageNamesScanner$1 because of underlying class loading error: Type org.osgi.framework.SynchronousBundleListener not found.  If this is unexpected, enable DEBUG logging to see the full error.
Mar 06, 2019 9:04:49 PM org.jboss.weld.bootstrap.MissingDependenciesRegistry handleResourceLoadingException
<.... truncated...>
Exception in thread "main" java.lang.RuntimeException: org.jboss.weld.exceptions.DeploymentException: Malformed class name
        at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:252)
        at nl.orhun.samplerestapp.MainKt.main(Main.kt:26)
        at nl.orhun.samplerestapp.MainKt.main(Main.kt)
Caused by: org.jboss.weld.exceptions.DeploymentException: Malformed class name
        at org.jboss.weld.executor.AbstractExecutorServices.checkForExceptions(AbstractExecutorServices.java:66)
        at org.jboss.weld.executor.AbstractExecutorServices.invokeAllAndCheckForExceptions(AbstractExecutorServices.java:43)
        at org.jboss.weld.executor.AbstractExecutorServices.invokeAllAndCheckForExceptions(AbstractExecutorServices.java:51)
        at org.jboss.weld.bootstrap.ConcurrentBeanDeployer.addClasses(ConcurrentBeanDeployer.java:58)
        at org.jboss.weld.bootstrap.BeanDeployment.createClasses(BeanDeployment.java:224)
        at org.jboss.weld.bootstrap.WeldStartup.startInitialization(WeldStartup.java:398)
        at org.jboss.weld.bootstrap.WeldBootstrap.startInitialization(WeldBootstrap.java:76)
        at org.jboss.weld.environment.servlet.WeldServletLifecycle.initialize(WeldServletLifecycle.java:191)
        at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:125)
        at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:187)
        at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:216)
        at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:185)
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:250)
        ... 2 more
Caused by: java.lang.InternalError: Malformed class name
        at java.lang.Class.getSimpleBinaryName(Unknown Source)
        at java.lang.Class.isMemberClass(Unknown Source)
        at org.jboss.weld.util.reflection.Reflections.getNesting(Reflections.java:138)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedConstructor.initParameters(BackedAnnotatedConstructor.java:50)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedConstructor.initParameters(BackedAnnotatedConstructor.java:28)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedCallable.<init>(BackedAnnotatedCallable.java:34)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedConstructor.<init>(BackedAnnotatedConstructor.java:38)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedConstructor.of(BackedAnnotatedConstructor.java:32)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType$BackedAnnotatedConstructors.computeValue(BackedAnnotatedType.java:168)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType$BackedAnnotatedConstructors.computeValue(BackedAnnotatedType.java:161)
        at org.jboss.weld.util.LazyValueHolder.get(LazyValueHolder.java:58)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType$EagerlyInitializedLazyValueHolder.<init>(BackedAnnotatedType.java:157)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType$BackedAnnotatedConstructors.<init>(BackedAnnotatedType.java:161)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType$BackedAnnotatedConstructors.<init>(BackedAnnotatedType.java:161)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType.<init>(BackedAnnotatedType.java:62)
        at org.jboss.weld.annotated.slim.backed.BackedAnnotatedType.of(BackedAnnotatedType.java:46)
        at org.jboss.weld.resources.ClassTransformer$TransformClassToBackedAnnotatedType.apply(ClassTransformer.java:80)
        at org.jboss.weld.resources.ClassTransformer$TransformClassToBackedAnnotatedType.apply(ClassTransformer.java:77)
        at org.jboss.weld.util.cache.ReentrantMapBackedComputingCache$1.apply(ReentrantMapBackedComputingCache.java:55)
        at org.jboss.weld.util.cache.ReentrantMapBackedComputingCache$1.apply(ReentrantMapBackedComputingCache.java:51)
        at org.jboss.weld.util.cache.ReentrantMapBackedComputingCache.getValue(ReentrantMapBackedComputingCache.java:64)
        at org.jboss.weld.util.cache.ReentrantMapBackedComputingCache.getCastValue(ReentrantMapBackedComputingCache.java:80)
        at org.jboss.weld.resources.ClassTransformer.getBackedAnnotatedType(ClassTransformer.java:175)
        at org.jboss.weld.resources.ClassTransformer.getBackedAnnotatedType(ClassTransformer.java:192)
        at org.jboss.weld.bootstrap.AnnotatedTypeLoader.loadAnnotatedType(AnnotatedTypeLoader.java:83)
        at org.jboss.weld.bootstrap.AnnotatedTypeLoader.loadAnnotatedType(AnnotatedTypeLoader.java:62)
        at org.jboss.weld.bootstrap.BeanDeployer.addClass(BeanDeployer.java:94)
        at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$1.doWork(ConcurrentBeanDeployer.java:61)
        at org.jboss.weld.bootstrap.ConcurrentBeanDeployer$1.doWork(ConcurrentBeanDeployer.java:58)
        at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62)
        at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55)
        at java.util.concurrent.FutureTask.run(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -6
        at java.lang.String.substring(Unknown Source)
        ... 35 more

Сборка сегмента пом:

 <build>
        <plugins>
            <plugin>
                <artifactId>kotlin-maven-plugin</artifactId>
                <groupId>org.jetbrains.kotlin</groupId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
                                <sourceDir>${project.basedir}/src/main/java</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <sourceDirs>
                                <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                                <sourceDir>${project.basedir}/src/test/java</sourceDir>
                            </sourceDirs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>nl.orhun.samplerestapp.MainKt</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
                        <phase>package</phase> <!-- bind to the packaging phase -->
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Я думаю, что это как-то связано с тем, как я создаю файл jar, но я не уверен.

Почему мое приложение не запускается при запуске файла JAR?

1 Ответ

0 голосов
/ 06 июня 2019

Я не использую Undertow, но я использую Weld SE в настройке сервлета на Jetty и столкнулся с той же проблемой, что и вы, похоже. Мне посчастливилось исключить kotlin-пакеты из сканирования обнаружения бина в моем beans.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
       bean-discovery-mode="all"
       version="1.1">
    <scan>
        ...
        <exclude name="kotlin.**" />
        <exclude name="kotlinx.**" />
    </scan>
</beans>

Я попытался отладить проблему, и для меня java.lang.InternalError: Malformed class name произошел от Java Class.getSimpleBinaryName, вызванного на некоторой лямбде в теле kotlin.coroutines.CoroutineContext.plus, названном kotlin.coroutines.CoroutineContext$plus$1, который, очевидно, имеет включающий класс kotlin.coroutines.CoroutineContext$DefaultImpls, который на 6 символов длиннее, чем имя класса лямбда, вызывая IndexOutOfBoundsException при попытке подстановки лямбда-имени в длину с именем включающего класса, чтобы получить простое имя лямбда-выражения. Это можно рассматривать как ошибку в том, как Котлин называет / печатает лямбды. Наименьший по отношению к отражению.

Я также попытался воспроизвести проблему, создав этот интерфейс:

interface Foo {

    fun fooBar(operation: (Foo) -> Foo): Foo

    fun plus(foo: Foo): Foo = fooBar { f -> f.plus(f) }
}

И это вызывает ту же проблему (с или без operator до fun). Создание Foo класса и реализация fooBar устраняет проблему. Не знаю почему.

Использование, например, let в теле Foo.plus не вызвало никаких проблем. Вероятно, потому что let встроено. Так что, если вы можете избежать использования не встроенных лямбд в телах интерфейсных функций, вы можете быть в порядке. И вы всегда можете поместить интерфейс, вызывающий проблемы, в отдельный пакет и исключить его из сканирования, если вы не собираетесь его внедрять. Надеюсь, эта проблема не получила широкого распространения.

Надеюсь, это помогло, несмотря на то, что он не был ответом для Undertow!

РЕДАКТИРОВАТЬ: Вы можете добавить аннотацию @JvmDefault (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-default/index.html)) к реализованной функции в интерфейсе для создания байт-кода, совместимого с методом по умолчанию (функция Java 8), и, следовательно, устранить проблему описано выше. Обратите внимание, что затем вам нужно указать аргумент компилятора -Xjvm-default=enable или -Xjvm-default=compatibility. В этой статье больше информации о @JvmDefault будет рассказано: https://realjenius.com/2018/06/29/jvm-default/.

...