运行带有依赖项的jar时Undertow应用程序无法启动

时间:2019-03-06 20:22:36

标签: java kotlin undertow

我正在与Kotlin一起练习,并且想要运行一个轻量级的Rest应用程序。我在Java的Jersey,Jackson和Weld CDI方面拥有Undertow的经验。

我写了启动Web容器的最低要求,它在IntelliJ中运行良好。 好的,当我尝试使用java -jar app-with-dependencies.jar运行jar-with-dependencies时,我会出错。

主类:

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

1 个答案:

答案 0 :(得分:0)

我没有使用Undertow,但是我在Jetty上运行的servlet设置中使用了Weld SE,似乎遇到了与您相同的问题。我很幸运在beans.xml的bean发现扫描中排除了kotlin软件包:

<?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,该Java调用了kotlin.coroutines.CoroutineContext.plus主体中某个名为kotlin.coroutines.CoroutineContext$plus$1的lambda具有封闭类kotlin.coroutines.CoroutineContext$DefaultImpls,该类比lambda类名长6个字符,从而在尝试对具有隐藏类名长度的lambda名称进行子串化以获取lambda的简单名称时导致IndexOutOfBoundsException 。这可能被视为Kotlin命名/键入lambda的方式中的错误。至少与反射有关。

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

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是内联的。因此,如果您可以避免在接口函数体中使用未内联的lambda,则可能会没事。而且,您始终可以将引起问题的接口放在其自己的程序包中,如果不打算注入接口,则可以将其排除在扫描范围之外。希望这个问题不会广泛传播。

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

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