我正在与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文件时我的应用程序无法启动?
答案 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特有的答案!
编辑:您可以将@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/提供了更多启示。