java - 作为 jar 文件运行时返回字符串作为 JSON 响应失败并显示 500 状态代码

标签 java rest jar jersey shadow

我创建的 fat jar 在 IDE(IntelliJ) 中运行时正确返回文件中的 json。但是,我在将其作为 jar 执行时遇到问题。这是一个带有 Guice 的 Dropwizard 应用程序。我的 build.gradle 中有以下内容

jar {
        manifest {
            attributes "Implementation-Title": "Symphony Service"
            attributes "Implementation-Version": '1.0'
            attributes "Main-Class" : 'com.symphony.api.SymphonyService'
        }

        doFirst {
            from (configurations.runtime.resolve().collect {
                    it.isDirectory() ? it : zipTree(it)
            }) {
                exclude 'META-INF/MANIFEST.MF'
                exclude 'META-INF/*.SF'
                exclude 'META-INF/*.DSA'
                exclude 'META-INF/*.RSA'
            }
        }
    }

这在我的 Controller 中。

@GET
@Path("/segments/{segmentid}/result")
@Produces(MediaType.APPLICATION_JSON)
public String result(@PathParam("segmentid") String segmentId) throws IOException {
    String response = null;
    URL url = Resources.getResource("response.json");
    try {
            response = Resources.toString(url, Charsets.UTF_8);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return response;
}

IDE 中一切正常。但是当我将其打包为 jar 然后运行它时,出现以下错误:

错误 [2014-03-12 05:13:44,304] com.sun.jersey.spi.container.ContainerResponse:Java 类 java.lang.String 和 Java 的消息正文编写器类型类 java.lang.String,并且未找到 MIME 媒体类型 application/json

错误 [2014-03-12 05:13:44,305] com.sun.jersey.spi.container.ContainerResponse:与 MIME 媒体类型兼容的已注册消息正文编写器为: / ->

com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider

以下是我的 MessageBodyWriter 的 SPI 文件 -
META-INF/services/javax.ws.rs.ext.MessageBodyWriter:

com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.RenderedImageProvider
com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
com.sun.jersey.atom.rome.impl.provider.entity.AtomFeedProvider
com.sun.jersey.atom.rome.impl.provider.entity.AtomEntryProvider
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$App
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$App
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
com.sun.jersey.json.impl.provider.entity.JSONWithPaddingProvider
com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy
com.sun.jersey.fastinfoset.impl.provider.entity.FastInfosetRootElementProvider
com.sun.jersey.fastinfoset.impl.provider.entity.FastInfosetJAXBElementProvider
com.sun.jersey.fastinfoset.impl.provider.entity.FastInfosetListElementProvider
com.sun.jersey.core.impl.provider.entity.StringProvider
com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
com.sun.jersey.core.impl.provider.entity.FileProvider
com.sun.jersey.core.impl.provider.entity.InputStreamProvider
com.sun.jersey.core.impl.provider.entity.DataSourceProvider
com.sun.jersey.core.impl.provider.entity.RenderedImageProvider
com.sun.jersey.core.impl.provider.entity.MimeMultipartProvider
com.sun.jersey.core.impl.provider.entity.FormProvider
com.sun.jersey.core.impl.provider.entity.FormMultivaluedMapProvider
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$Text
com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
com.sun.jersey.core.impl.provider.entity.ReaderProvider
com.sun.jersey.core.impl.provider.entity.DocumentProvider
com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider

我觉得发生这种情况是因为条目

com.sun.jersey.core.impl.provider.entity.StringProvider

在 META-INF/services/javax.ws.rs.ext.MessageBodyWriter 文件中重复。 当我从该文件中删除重复项后手动创建 jar 时,它可以工作。 我仍然没有找到正确合并文件的方法。尝试了 gradle 的影子插件,但无法使其正常工作。

-艾米斯

已修复:让 gradle 阴影插件正常工作,现在无需任何调整即可工作

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.github.jengelman.gradle.plugins:shadow:0.8'
    }
}
apply plugin: 'shadow'

jar {
    manifest {
        attributes "Implementation-Title": "Symphony Service"
        attributes "Implementation-Version": '1.0'
        attributes "Main-Class" : 'com.experian.symphony.api.SymphonyService'
    }

     /*excludes {
            exclude 'META-INF/MANIFEST.MF'
            exclude 'META-INF/*.SF'
            exclude 'META-INF/*.DSA'
            exclude 'META-INF/*.RSA'
        } */
}

shadow {
    destinationDir = 'build/distributions'
    classifier = '1.0'

    exclude 'META-INF/MANIFEST.MF'
    exclude 'META-INF/*.SF'
    exclude 'META-INF/*.DSA'
    exclude 'META-INF/*.RSA'
}

最佳答案

如果您在 web.xml 中设置此项,则不会出现错误。这就是我为克服映射基本类型问题所做的事情。

我认为基本问题是默认的 MessageWriter 使用 jaxb 注释 (@XmlRootElement) 来处理对象,并且由于 String、Number、Double、Integer 等基本类型没有这些注释,因此您必须使用默认的 pojo将使用 Jackson 的 ObjectMapper 类处理的映射器。您可以使用的其他选项是将字符串包装在另一个要返回的对象中,或者实现一个实现MessageBodyWriter<String>的@Provider。这会将字符串转换为 json。希望这可以帮助。

https://jersey.java.net/documentation/1.18/json.html

Web.xml 配置

       <init-param>
           <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
           <param-value>true</param-value>
       </init-param>

Guice配置

@Override
protected void configureServlets() {
    serve("/rest/v1/*").with(GuiceContainer.class, createJerseyParams());
}


private Map<String, String> createJerseyParams() {
    Map<String, String> params = new HashMap<String, String>();

    params.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
    return params;
}

关于java - 作为 jar 文件运行时返回字符串作为 JSON 响应失败并显示 500 状态代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22342782/

相关文章:

java - 为什么会出现这种情况下拆箱的情况呢?

java - 编译 Jars 并将它们添加到 android 项目中

java - 如何区分 get 和 post call..?

python - Django 从模型或 View 调用 REST API?

Javac 不创建主类引用

java - 如何使第三方 .jar 可用于我的 .jsp 页面?

java - 为 N 名玩家生成一手牌(每手五张牌)

java - 冒泡排序数组列表

java - 避免 java 中的速率限制(IRC)

azure - Azure Blob 存储中的文件 ID [AZURE-BLOB]