无法使Jersey JAX-RS资源与Proguard混淆的REST服务一起使用

jsp*_*att 3 jersey proguard

请原谅这篇文章的篇幅.我试图获取其中的所有有用信息,并预测人们可能会遇到的问题.

我有一系列与Jersey一起实现并在Jetty中运行的RESTful Web服务. 使用jar文件的未混淆版本,一切正常.但是当我与Proguard混淆时,我收到了500错误消息

The ResourceConfig instance does not contain any root resource classes.
Run Code Online (Sandbox Code Playgroud)

作为我的软件包的一部分,我有一个非常简单的ping服务,所以我可以测试连接和基本的Jersey配置.

我用jersey启动jetty的代码如下所示:

ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter("com.sun.jersey.config.property.packages", "com.sw.pr.hq");
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
            "com.sun.jersey.api.core.PackagesResourceConfig");
ServletContextHandler sch = new ServletContextHandler(server, "/pr");
sch.addServlet(sh, "/");
Run Code Online (Sandbox Code Playgroud)

当我尝试从浏览器中点击我的ping URL时,调试日志显示以下行:

Jan 13, 2011 9:33:35 AM com.sun.jersey.api.core.PackagesResourceConfig init
[java] INFO: Scanning for root resource and provider classes in the packages:
[java]   com.sw.pr.hq
Run Code Online (Sandbox Code Playgroud)

因此我认为jetty已正确配置并正常运行.就像我说的,这个应用程序的未混淆版本工作正常.

我尝试ping时出现的堆栈跟踪显示在此帖子的底部,但最令人不安的是:

[java] SEVERE: The ResourceConfig instance does not contain any root resource classes.
[java] 2011-01-13 09:33:35.585:WARN:/pr:unavailable
Run Code Online (Sandbox Code Playgroud)

我的proguard配置看起来像这样(为简洁起见删除了注释).请注意,当我执行jar -tvf obfuscated.jar调用时,我在那里看到类com.sw.pr.HQServerResource.class文件.

-dontskipnonpubliclibraryclasses
-renamesourcefileattribute SourceFile
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-overloadaggressively
-repackageclasses com.sw.rtm
-adaptresourcefilenames    **.properties,**.png,**.css
-adaptresourcefilecontents **.properties,META-INF/MANIFEST.MF
-keep public class * {
    public *;
}
-keepclassmembernames class * {
    java.lang.Class class$(java.lang.String);
    java.lang.Class class$(java.lang.String, boolean);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
Run Code Online (Sandbox Code Playgroud)

我的ping资源类如下所示:

@Path("/")
public class HQServerResource {
    @GET
    @Produces(MediaType.APPLICATION_XML)
    @Path("/ping")
    public PingResponse pingGet(@Context HttpServletRequest httpRequest) {
        LOGGER.debug("pingGet()");
        return getPingResponse(httpRequest);
    }
}
Run Code Online (Sandbox Code Playgroud)

由于我不熟悉Proguard,现在我将进入我的推测阶段.

我认为我的问题可以归结为Proguard在我的类文件中混合我的@Path注释.但是我的proguard配置文件中有指令(-keepattributes Annotation).因此我现在迷路了.

任何指导将不胜感激.

堆栈跟踪:

[java] com.sun.jersey.api.container.ContainerException:ResourceConfig实例不包含任何根资源类.[java] at com.sun.jersey.server.impl.application.RootResourceUriRules.(RootResourceUriRules.java:103)[java] at com.sun.jersey.server.impl.application.WebApplicationImpl._initiate(WebApplicationImpl.java:1182 )[java] at com.sun.jersey.server.impl.application.WebApplicationImpl.access $ 600(WebApplicationImpl.java:161)[java] at com.sun.jersey.server.impl.application.WebApplicationImpl $ 12.f(WebApplicationImpl .java:698)[java] at com.sun.jersey.server.impl.application.WebApplicationImpl $ 12.f(WebApplicationImpl.java:695)[java] at com.sun.jersey.spi.inject.Errors.processWithErrors( Errors.java:197)[java] at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:695)[java] at com.sun.jersey.server.impl.application.WebApplicationImpl.在com.sun.jersey.spi.container.servlet的com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:438)[java]中启动(WebApplicationImpl.java:690)[java]. ServletContainer $ InternalWebComponent.ini tiate(ServletContainer.java:287)[java] com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:587)[java] at com.sun.jersey.spi.container.servlet. WebComponent.init(WebComponent.java:213)[java] at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:342)[java] at com.sun.jersey.spi.container. servlet.ServletContainer.init(ServletContainer.java:516)[java] at javax.servlet.GenericServlet.init(GenericServlet.java:211)[java] org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java: 431)[java] atg.eclipse.jetty.servlet.ServletHolder.getServlet(ServletHolder.java:330)[java] at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:510)

jsp*_*att 9

我相信我已经找到了我遇到的问题.问题是,默认情况下,proguard不包含模糊jar文件中的目录条目.

所以我混淆的jar文件内容看起来像这样.

com/sw/pr/hq/HQServerResource.class
com/sw/pr/hq/a.class
com/sw/pr/hq/a.class
Run Code Online (Sandbox Code Playgroud)

注意,没有目录条目.

当我将-keepdirectories指令添加到我的proguard文件时,我的混淆jar文件看起来像这样.

com/
com/sw/
com/sw/pr/
com/sw/pr/hq/
com/sw/pr/hq/HQServerResource.class
com/sw/pr/hq/a.class
com/sw/pr/hq/a.class
Run Code Online (Sandbox Code Playgroud)

完成后,Servlet可以遍历目录,查找我的@Path注释资源.

一个血腥的指令,痛苦的日子.