作为jar文件运行时,将String作为JSON响应返回失败,并显示500状态代码

时间:2014-03-12 05:31:46

标签: java rest jar jersey shadow

我创建的胖jar在IDE(IntelliJ)中运行时正确地从文件返回json。但是,我作为一个罐子执行它有问题。这是一个带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'
            }
        }
    }

这在我的控制器中。

@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然后运行它时,我得到以下错误:

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

ERROR [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但无法使其工作。

-Amith

修复:让gradle shadow插件正常工作,现在无需任何调整即可使用

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'
}

1 个答案:

答案 0 :(得分:0)

如果您在web.xml中设置此项,则表示您不会收到错误消息。如果映射基本类型,这就是我为克服这个问题所做的。

我认为基本问题是默认的MessageWriter使用jaxb注释(@XmlRootElement)来处理对象,因为像String,Number,Double,Integer等基类没有这些,你必须使用默认的pojo mapper将处理使用jackson的ObjectMapper类。您可以使用的其他选项是将String包装在另一个要返回的对象中,或者实现一个实现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;
}