@Path注解:dropwizard中的抽象资源

@Path annotation: abstract resource in dropwizard

我想为我的应用程序构建抽象资源 class:

abstract class MyAbstractResource<A> {
    MyAbstractDao dao;

    public MyAbstractResource(MyAbstractDao dao) {
        this.dao = dao;
    }

    @Path("/")
    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Timed
    public A create(A account) {
        return dao.create(account);
    }

    @Path("/{id}")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    @Timed
    public A update(A account) {
        return dao.change(account);
    }

    @Path("/{id}")
    @DELETE
    @Produces(MediaType.APPLICATION_JSON)
    @Timed
    public void delete(@PathParam("id") Long id) {
        dao.delete(id);
    }

    @Path("/{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Timed
    public A get(@PathParam("id") Long id) {
        return dao.findById(id);
    }

    @Path("/")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Timed
    public List<A> getAll() {
        return dao.findAll();
    }
}

和类似的实现:

@Path("/account")
class AccountResource extends MyAbstractResource<AccountDaoImpl> {
    private static final Logger LOG = LoggerFactory.getLogger(AccountResource.class)
}

,但我遇到了无法覆盖或添加@Path-annotation 的问题:

Exception in thread "main" javax.servlet.ServletException: org.glassfish.jersey.servlet.ServletContainer-164d01ba@41f867a3==org.glassfish.jersey.servlet.ServletContainer,1,false
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:633)
at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:395)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:871)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:298)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:741)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
at com.codahale.metrics.jetty9.InstrumentedHandler.doStart(InstrumentedHandler.java:102)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
at org.eclipse.jetty.server.handler.RequestLogHandler.doStart(RequestLogHandler.java:140)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
at org.eclipse.jetty.server.handler.StatisticsHandler.doStart(StatisticsHandler.java:232)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
at org.eclipse.jetty.server.Server.start(Server.java:387)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:114)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:61)
at org.eclipse.jetty.server.Server.doStart(Server.java:354)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at io.dropwizard.cli.ServerCommand.run(ServerCommand.java:43)
at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:43)
at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:76)
at io.dropwizard.cli.Cli.run(Cli.java:70)
at io.dropwizard.Application.run(Application.java:73)
at io.dropwizard.Application$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:122)
at com.fappilla.web.FappillaWebService.main(MyWebService.groovy:24)
Caused by: java.lang.IllegalArgumentException: duplicate key: public java.util.List com.fappilla.web.resources.AbstractFappillaResource.getAll()
at jersey.repackaged.com.google.common.base.Preconditions.checkArgument(Preconditions.java:119)
at jersey.repackaged.com.google.common.collect.RegularImmutableMap.<init>(RegularImmutableMap.java:67)
at jersey.repackaged.com.google.common.collect.ImmutableMap$Builder.fromEntryList(ImmutableMap.java:249)
at jersey.repackaged.com.google.common.collect.ImmutableMap$Builder.build(ImmutableMap.java:235)
at com.codahale.metrics.jersey2.InstrumentedResourceMethodApplicationListener.onEvent(InstrumentedResourceMethodApplicationListener.java:178)
at org.glassfish.jersey.server.internal.monitoring.CompositeApplicationEventListener.onEvent(CompositeApplicationEventListener.java:74)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:561)
at org.glassfish.jersey.server.ApplicationHandler.access0(ApplicationHandler.java:166)
at org.glassfish.jersey.server.ApplicationHandler.run(ApplicationHandler.java:327)
at org.glassfish.jersey.internal.Errors.call(Errors.java:289)
at org.glassfish.jersey.internal.Errors.call(Errors.java:286)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:324)
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:336)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:170)
at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:358)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:612)
... 40 more

据我了解,@Path-annotation 不是@Inherited。问题是:在这种情况下,我如何才能为多个 DAO 和资源实现一次方法?有什么解决方法吗?

PS:我在项目中使用groovy,但是上面写了java代码,让更多人给我提意见,所以java和groovy欢迎回答。

好的,问题出在“@Timed”注释。删除它解决了问题。

以防其他人遇到此问题,另一种解决方案是将 InstrumentedResourceMethodApplicationListener.javahttps://gist.github.com/mtakaki/746dba30edfefc0ffbd5 复制到您的 class 路径 - 它会被 class 拾取从 metrics jar 加载官方 class。

有关详细信息,请参阅:

我已经验证这解决了在 Dropwizard 0.9.1 上使用 @Timed 注释的 superclass 资源的问题。