野蝇和球衣 MultiPartFeature.class

wildfly and jerseys MultiPartFeature.class

我想从 tomcat 迁移到 Wildfly 10.1,因此我创建了一个 Web 应用程序来测试 Wildfly 上的 Jersey rest Web 服务。

当我 运行 项目时,它根据 MultiPartFeature.class

显示错误

这是我的ApplicationConfigure.java

@ApplicationPath("api")
public class ApplicationConfigure extends ResourceConfig {


    public ApplicationConfigure() {

        register(JacksonJaxbJsonProvider.class);
        register(JacksonFeature.class);
        register(MultiPartFeature.class);

        packages(true, "com.example.controllers");

    }

}

这是错误(WildFly 日志):

11:18:13,855 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 69) MSC000001: Failed to start service jboss.undertow.deployment.default-server.default-host./wildfly-webapplcation: org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./wildfly-webapplcation: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.run(UndertowDeploymentService.java:85)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1437)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1368)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1290)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.register(ResteasyProviderFactory.java:2438)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.register(ResteasyProviderFactory.java:99)
    at org.jboss.resteasy.util.FeatureContextDelegate.register(FeatureContextDelegate.java:37)
    at org.jboss.resteasy.util.FeatureContextDelegate.register(FeatureContextDelegate.java:12)
    at org.glassfish.jersey.media.multipart.MultiPartFeature.configure(MultiPartFeature.java:65)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1739)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1368)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1290)
    at org.jboss.resteasy.spi.ResteasyDeployment.registration(ResteasyDeployment.java:368)
    at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:250)
    at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:113)
    at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:36)
    at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
    at org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:78)
    at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:103)
    at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:250)
    at io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:133)
    at io.undertow.servlet.core.DeploymentManagerImpl.call(DeploymentManagerImpl.java:546)
    at io.undertow.servlet.core.DeploymentManagerImpl.call(DeploymentManagerImpl.java:517)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call(ServletRequestContextThreadSetupAction.java:42)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction.call(ContextClassLoaderSetupAction.java:43)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:559)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:101)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.run(UndertowDeploymentService.java:82)
    ... 6 more
Caused by: java.lang.IllegalArgumentException: RESTEASY003900: Unable to find a public constructor for provider class org.glassfish.jersey.media.multipart.internal.MultiPartReaderServerSide
    at org.jboss.resteasy.spi.ResteasyProviderFactory.createConstructorInjector(ResteasyProviderFactory.java:2255)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.createProviderInstance(ResteasyProviderFactory.java:2244)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.addMessageBodyReader(ResteasyProviderFactory.java:806)
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1432)
    ... 37 more

netbeans 日志:

Deploying /usr/local/wildfly-10.1.0.Final/standalone/deployments/wildfly-webapplcation-1.0.war
"{
    \"WFLYCTL0080: Failed services\" => {\"jboss.undertow.deployment.default-server.default-host./wildfly-webapplcation\" => \"org.jboss.msc.service.StartException in service jboss.undertow.deployment.default-server.default-host./wildfly-webapplcation: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    Caused by: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    Caused by: java.lang.IllegalArgumentException: RESTEASY003900: Unable to find a public constructor for provider class org.glassfish.jersey.media.multipart.internal.MultiPartReaderServerSide\"},
    \"WFLYCTL0412: Required services that are not installed:\" => [\"jboss.undertow.deployment.default-server.default-host./wildfly-webapplcation\"],
    \"WFLYCTL0180: Services with missing/unavailable dependencies\" => undefined
}"

当我删除 MultiPartFeature.class 时,它部署得很好。

顺便说一句,此应用程序在 Tomee 上运行良好。

我该怎么办?我的上传需要此功能 api

作为应用服务器,Wildfly 提供了自己的 JAX-RS 规范实现。这里使用的框架是 RESTEasy 而不是 Jersey。

那么如何从你的日志中看出:

Caused by: java.lang.RuntimeException: RESTEASY003940: Unable to instantiate MessageBodyReader
    at org.jboss.resteasy.spi.ResteasyProviderFactory.registerProvider(ResteasyProviderFactory.java:1437)

RESTEasy 引擎正在尝试启动 Jersey 的功能但未能成功。 JAX-RS 实现中没有那么多统一,因此它们经常不兼容。

您有两种可能的解决方案

  1. 从 Jersey 切换到 RESTEasy。还有multipart support有点不一样

  2. 关闭 Wildfly 对应用程序的 RESTEasy 扫描并在内部启动 Jersey 服务器。互联网上有很多关于它的文章。不确定哪种方法适用于您的版本。

我解决了这个问题,并设法通过手动调用来强制我的应用程序使用球衣 JerseyClientBuilder().build() 而不是 ClientBuilder().build().

球衣客户端似乎是默认客户端,因此如果您定义了另一个客户端,它将是 ClientBuilder().build() 选择的客户端。

我在服务器和客户端级别将 Jersey 库版本从 1.x 升级到 2.x 时遇到了这个问题。

1.服务器等级变化:

在我的 web.xml 中添加了以下条目以从 class 路径库中消除 resteasy 扫描。

    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>resteasy.scan.providers</param-name>
        <param-value>false</param-value>
    </context-param>
    <context-param>
        <param-name>resteasy.scan.resources</param-name>
        <param-value>false</param-value>
    </context-param>

在我的 servlet 部分添加了以下提供程序

    <servlet>
         ....
         ....
        <init-param>
          <param-name>jersey.config.server.provider.classnames</param-name>
          <param-value>
            com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider,
            org.glassfish.jersey.media.multipart.MultiPartFeature
          </param-value>
        </init-param>      
        ....
        ....
    </servlet>

2。客户端级别变化:

在升级期间,我只是将与客户端相关的 class 包从 com.sun.jersey.api.client 更改为 org.glassfish.jersey.client 并且假设所有 glassfish jersey 的默认提供程序都将在客户端期间注册实例化,而不是 org.jboss.resteasy.spi.ResteasyProviderFactory 被初始化,主要原因是,我使用 Client client = Client.create(); 创建客户端。此外,在问题出现后,将上述客户端创建更改为以下代码片段,这导致我遇到了问题

Cannot find a deserializer for non-concrete Map type [map type; class javax.ws.rs.core.MultivaluedMap, [simple type, class java.lang.String] -> [collection type; class java.util.List, contains [simple type, class java.lang.Object]]] .

Client client = ClientBuilder.newClient();
WebTarget webResource = client.target(url);
ClientResponse response = webResource.path(path).request("application/json")
                                 .header("Content-Type", "application/json;charset=UTF-8")
                                 .put(Entity.json(json), ClientResponse.class);

if (response.getStatus() < 200 || response.getStatus() > 299) {
    throw new CustomException("HTTP Status: " + response.getStatus());
}
String responseInString = response.readEntity(String.class);

Json 解析问题是因为 org.glassfish.jersey.client.JerseyInvocation#translate 方法,其中实体读取发生在消息实体输入流中,作为使用 [=21] 的指定 Java 类型的实例=] 对于 javax.ws.rs.core.Response` 以外的类型。

最后完全采用Jersey家族客户端classes解决了上述问题。

工作客户:

JerseyClient client = JerseyClientBuilder.createClient()
                                      .register(JacksonFeature.withoutExceptionMappers());
JerseyWebTarget webResource = client.target(url);
Response response = webResource.path(path).request("application/json")
                                .header("Content-Type", "application/json;charset=UTF-8")
                                .put(Entity.json(json), Response.class);

if (response.getStatus() < 200 || response.getStatus() > 299) {
    throw new CustomException("HTTP Status: " + response.getStatus());
}
String responseInString = response.readEntity(String.class);