bretthoerner / dropwizard-scala

Scala helpers for Dropwizard.
86 stars 26 forks source link

HttpRequestContext is a missing dependency #7

Closed dehora closed 11 years ago

dehora commented 11 years ago

Using 0.6.2 or 0.6.2-1, HttpRequestContext is not available to resources - HttpServletRequest, HttpContext and UriInfo are available.

ERROR [2013-07-08 21:52:32,197] com.sun.jersey.spi.inject.Errors: The following errors and warnings have been detected with resource and/or provider classes:
  SEVERE: Missing dependency for method public javax.ws.rs.core.Response com.cayova.centauri.proxy.resources.ProxyCacheResource.queryCache(java.lang.String,javax.servlet.http.HttpServletRequest,javax.ws.rs.core.UriInfo,com.sun.jersey.api.core.HttpContext,com.sun.jersey.api.core.HttpRequestContext) at parameter at index 4
WARN  [2013-07-08 21:52:32,203] /: unavailable
! com.sun.jersey.spi.inject.Errors$ErrorMessagesException: null
! at com.sun.jersey.spi.inject.Errors.processErrorMessages(Errors.java:170) ~[jersey-core-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.inject.Errors.postProcess(Errors.java:136) ~[jersey-core-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:199) ~[jersey-core-1.17.1.jar:1.17.1]
! at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:770) ~[jersey-server-1.17.1.jar:1.17.1]
! at com.sun.jersey.server.impl.application.WebApplicationImpl.initiate(WebApplicationImpl.java:765) ~[jersey-server-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.container.servlet.ServletContainer.initiate(ServletContainer.java:489) ~[jersey-servlet-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.container.servlet.ServletContainer$InternalWebComponent.initiate(ServletContainer.java:319) ~[jersey-servlet-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.container.servlet.WebComponent.load(WebComponent.java:605) ~[jersey-servlet-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.container.servlet.WebComponent.init(WebComponent.java:210) ~[jersey-servlet-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:374) ~[jersey-servlet-1.17.1.jar:1.17.1]
! at com.sun.jersey.spi.container.servlet.ServletContainer.init(ServletContainer.java:557) ~[jersey-servlet-1.17.1.jar:1.17.1]
! at javax.servlet.GenericServlet.init(GenericServlet.java:244) ~[javax.servlet-3.0.0.v201112011016.jar:na]
! at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:519) [jetty-servlet-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.servlet.ServletHolder.doStart(ServletHolder.java:331) [jetty-servlet-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:742) [jetty-servlet-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:265) [jetty-servlet-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:710) [jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95) [jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95) [jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:229) [jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:95) [jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.server.Server.doStart(Server.java:280) [jetty-server-8.1.10.v20130312.jar:8.1.10.v20130312]
! at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:64) [jetty-util-8.1.10.v20130312.jar:8.1.10.v20130312]
! at com.yammer.dropwizard.cli.ServerCommand.run(ServerCommand.java:48) [dropwizard-core-0.6.2.jar:na]
! at com.yammer.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:39) [dropwizard-core-0.6.2.jar:na]
! at com.yammer.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:58) [dropwizard-core-0.6.2.jar:na]
! at com.yammer.dropwizard.cli.Cli.run(Cli.java:53) [dropwizard-core-0.6.2.jar:na]
! at com.yammer.dropwizard.Service.run(Service.java:61) [dropwizard-core-0.6.2.jar:0.6.2-1]
! at com.yammer.dropwizard.ScalaService.main(ScalaService.scala:7) [dropwizard-scala_2.9.1-0.6.2-1.jar:0.6.2-1]
! at com.cayova.centauri.proxy.service.ServiceMain.main(ServiceMain.scala) [proxy-server/:na]
INFO  [2013-07-08 21:52:32,219] org.eclipse.jetty.server.AbstractConnector: Started InstrumentedBlockingChannelConnector@0.0.0.0:8080
INFO  [2013-07-08 21:52:32,224] org.eclipse.jetty.server.AbstractConnector: Started SocketConnector@0.0.0.0:8081

Example signature

def queryCache(@QueryParam("q") queryURI: String,
    @Context servletRequest: HttpServletRequest, //ok
    @Context uriInfo: UriInfo, //ok
    @Context requestContext: HttpContext, //ok
    @Context requestHttpContext: HttpRequestContext //error
    ): Response  
nbauernfeind commented 11 years ago

Thanks for the bug report. I'll look into this tonight.

nbauernfeind commented 11 years ago

This is not a dropwizard-scala issue. Same issue occurs if you use java dropwizard or jersey all by itself.

com.sun.jersey.server.impl.model.parameter.HttpContextInjectableProvider is where @Context related things are injected from, and demonstrates how you can 1) make a modification and suggest it directly to jersey or 2) create your own provider.

First, note that injecting an instance of javax.ws.rs.core.Request works properly (but, obviously, loses the fact that it's an HttpRequestContext. So you could ask for the Request and do an instance of / scala match on the type:

def sampleRequest(@Context request: Request): Response = { ... }

Or if you really want to avoid type checking the Request object you can create your own provider. The simplest implementation would look like this:

private final class HttpRequestContextInjectable extends AbstractHttpContextInjectable[HttpRequestContext] {
  def getValue(c: HttpContext): HttpRequestContext = c.getRequest
}

class HttpRequestContextProvider extends InjectableProvider[Context, Type] {
  private val _httpRequestContextInjectable = new HttpRequestContextInjectable

  def getScope: ComponentScope = ComponentScope.PerRequest

  def getInjectable(ic: ComponentContext, a: Context, c: Type): Injectable[_] = if (c == classOf[HttpRequestContext]) _httpRequestContextInjectable else null
}

object SampleService extends ScalaService[Configuration] {
  def initialize(bootstrap: Bootstrap[Configuration]) {
    bootstrap.addBundle(new ScalaBundle)
  }

  def run(cfg: Configuration, env: Environment) {
    env.getJerseyResourceConfig.getClasses.add(classOf[HttpRequestContextProvider])
  }
}

Ultimately if you think this belongs in jersey then you need to just add another line to this method and send them a pull request:

    public HttpContextInjectableProvider() {        
        injectables = new HashMap<Type, Injectable>();

        HttpContextRequestInjectable re = new HttpContextRequestInjectable();
        injectables.put(HttpHeaders.class, re);
        injectables.put(Request.class, re);
        injectables.put(SecurityContext.class, re);
        // Make a pull request to add the following line:
        injectables.put(RequestHttpContext.class, re);

        injectables.put(HttpContext.class, new HttpContextInjectable());

        injectables.put(UriInfo.class, new UriInfoInjectable());
        injectables.put(ExtendedUriInfo.class, new UriInfoInjectable());
    }