Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
521 additions
and
437 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
package com.yammer.dropwizard | ||
|
||
import collection.JavaConversions._ | ||
import lifecycle.Managed | ||
import com.sun.jersey.api.core.ResourceConfig._ | ||
import com.codahale.logula.Logging | ||
import com.yammer.metrics.core.HealthCheck | ||
import javax.servlet.{Servlet, Filter} | ||
import com.sun.jersey.core.reflection.MethodList | ||
import javax.ws.rs.{Path, HttpMethod} | ||
import org.eclipse.jetty.servlet.{ServletHolder, FilterHolder} | ||
|
||
class Environment extends Logging { | ||
private[dropwizard] var resources = Set.empty[Object] | ||
private[dropwizard] var healthChecks = Set.empty[HealthCheck] | ||
private[dropwizard] var providers = Set.empty[Object] | ||
private[dropwizard] var managedObjects = IndexedSeq.empty[Managed] | ||
private[dropwizard] var filters = Map.empty[String, FilterHolder] | ||
private[dropwizard] var servlets = Map.empty[String, ServletHolder] | ||
|
||
def addResource(resource: Object) { | ||
if (!isRootResourceClass(resource.getClass)) { | ||
throw new IllegalArgumentException(resource.getClass.getCanonicalName + | ||
" is not a @Path-annotated resource class") | ||
} | ||
|
||
if (annotatedMethods(resource).isEmpty) { | ||
throw new IllegalArgumentException(resource.getClass.getCanonicalName + | ||
" has no @GET/@POST/etc-annotated methods") | ||
} | ||
|
||
resources += resource | ||
} | ||
|
||
def addProvider(provider: Object) { | ||
if (!isProviderClass(provider.getClass)) { | ||
throw new IllegalArgumentException(provider.getClass.getCanonicalName + | ||
" is not a @Provider-annotated provider class") | ||
} | ||
providers += provider | ||
} | ||
|
||
def addHealthCheck(healthCheck: HealthCheck) { | ||
healthChecks += healthCheck | ||
} | ||
|
||
def manage(managedObject: Managed) { | ||
managedObjects ++= IndexedSeq(managedObject) | ||
} | ||
|
||
def addFilter[T <: Filter](filter: T, | ||
pathSpec: String, | ||
params: Map[String, String] = Map.empty) { | ||
val holder = new FilterHolder(filter) | ||
holder.setInitParameters(params) | ||
filters += pathSpec -> holder | ||
} | ||
|
||
def addFilterClass[T <: Filter](klass: Class[T], | ||
pathSpec: String, | ||
params: Map[String, String] = Map.empty) { | ||
val holder = new FilterHolder(klass) | ||
holder.setInitParameters(params) | ||
filters += pathSpec -> holder | ||
} | ||
|
||
def addServlet[T <: Servlet](servlet: T, | ||
pathSpec: String, | ||
params: Map[String, String] = Map.empty, | ||
initOrder: Int = 0) { | ||
val holder = new ServletHolder(servlet) | ||
holder.setInitParameters(params) | ||
holder.setInitOrder(initOrder) | ||
servlets += pathSpec -> holder | ||
} | ||
|
||
def addServletClass[T <: Servlet](klass: Class[T], | ||
pathSpec: String, | ||
params: Map[String, String] = Map.empty, | ||
initOrder: Int = 0) { | ||
val holder = new ServletHolder(klass) | ||
holder.setInitParameters(params) | ||
holder.setInitOrder(initOrder) | ||
servlets += pathSpec -> holder | ||
} | ||
|
||
private[dropwizard] def validate() { | ||
def logResources() { | ||
def httpMethods(resource: Object) = annotatedMethods(resource).map { | ||
_.getMetaMethodAnnotations(classOf[HttpMethod]).map { _.value() } | ||
}.flatten.toIndexedSeq.sorted | ||
|
||
def paths(resource: Object) = | ||
resource.getClass.getAnnotation(classOf[Path]).value() :: Nil | ||
|
||
val out = new StringBuilder("\n\n") | ||
for (resource <- resources; | ||
path <- paths(resource); | ||
method <- httpMethods(resource)) { | ||
out.append(" %s %s (%s)\n".format(method, path, resource.getClass.getCanonicalName)) | ||
} | ||
log.info(out.toString()) | ||
} | ||
|
||
log.debug("resources = %s", resources.mkString("{", ", ", "}")) | ||
log.debug("providers = %s", providers.mkString("{", ", ", "}")) | ||
log.debug("health checks = %s", healthChecks.mkString("{", ", ", "}")) | ||
log.debug("managed objects = %s", managedObjects.mkString("{", ", ", "}")) | ||
|
||
logResources() | ||
|
||
if (healthChecks.isEmpty) { | ||
log.warn(""" | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
! THIS SERVICE HAS NO HEALTHCHECKS. THIS MEANS YOU WILL NEVER KNOW IF IT ! | ||
! DIES IN PRODUCTION, WHICH MEANS YOU WILL NEVER KNOW IF YOU'RE LETTING ! | ||
! YOUR USERS DOWN. YOU SHOULD ADD A HEALTHCHECK FOR EACH DEPENDENCY OF ! | ||
! YOUR SERVICE WHICH FULLY (BUT LIGHTLY) TESTS YOUR SERVICE'S ABILITY TO ! | ||
! USE THAT SERVICE. THINK OF IT AS A CONTINUOUS INTEGRATION TEST. ! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | ||
""") | ||
} | ||
} | ||
|
||
private def annotatedMethods(resource: Object) = | ||
new MethodList(resource.getClass, true).hasMetaAnnotation(classOf[HttpMethod]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.yammer.dropwizard | ||
|
||
import com.sun.jersey.api.core.DefaultResourceConfig | ||
import com.codahale.logula.Logging | ||
import providers.LoggingExceptionMapper | ||
import com.codahale.jersey.inject.ScalaCollectionsQueryParamInjectableProvider | ||
import com.codahale.jersey.providers.{JValueProvider, JsonCaseClassProvider} | ||
|
||
class JerseyConfig(env: Environment) extends DefaultResourceConfig with Logging { | ||
( | ||
Set( | ||
new LoggingExceptionMapper, | ||
new JsonCaseClassProvider, | ||
new ScalaCollectionsQueryParamInjectableProvider, | ||
new JValueProvider | ||
) ++ env.resources ++ env.providers | ||
).foreach(getSingletons.add) | ||
|
||
override def validate() { | ||
env.validate() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.