首页 > 解决方案 > 运行具有依赖项的 jar 时,Undertow 应用程序未启动

问题描述

我正在使用 Kotlin 练习并希望运行一个轻量级的 Rest 应用程序。我在 Java 中使用 Jersey、Jackson 和 Weld CDI 使用 Undertow 的经验。

我编写了启动 Web 容器的最低要求,它在 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

构建 pom 的片段:

 <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 文件时我的应用程序没有启动?

标签: javakotlinundertow

解决方案


我没有使用 Undertow,但我在 Jetty 上运行的 servlet 设置中使用 Weld SE,并且遇到了与您相同的问题,看起来像。我在我的 bean 发现扫描中排除了 kotlin-packages 有一些运气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起源于 JavaClass.getSimpleBinaryName在 的主体中调用了一些 lambda kotlin.coroutines.CoroutineContext.plus,命名kotlin.coroutines.CoroutineContext$plus$1显然具有kotlin.coroutines.CoroutineContext$DefaultImpls比 lambda 类名长 6 个字符的封闭类,导致IndexOutOfBoundsException尝试子串 lambda name 与封闭类名称的长度来获取 lambda 的简单名称。这可能被视为 Kotlin 命名/类型 lambda 的方式中的错误。至少在反射方面。

我还尝试通过创建此接口来复制问题:

interface Foo {

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

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

它会导致同样的问题(有或没有operatorbefore fun)。Foo但是,创建一个类并实施,可以使fooBar问题消失。不知道为什么。

例如let在身体中使用Foo.plus并没有引起任何问题。可能是因为let是内联的。因此,如果您可以避免在接口函数体中使用未内联的 lambda,您可能会没事。如果你不打算注入它,你总是可以将导致问题的接口放在它自己的包中,并将其排除在扫描之外。希望这个问题不会普遍存在。

希望这会有所帮助,尽管不是特定于 Undertow 的答案!

编辑:您可以将@JvmDefaulthttps://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-jvm-default/index.html)注释添加到接口中的已实现函数以创建默认方法(Java 8 功能)兼容的字节码,从而消除了上述问题。请注意,您必须指定-Xjvm-default=enableor-Xjvm-default=compatibility编译器参数。本文提供了更多@JvmDefault信息:https ://realjenius.com/2018/06/29/jvm-default/ 。


推荐阅读