Merge pull request #17988 from ktoso/wip-javadsl-handleWith-ktoso

!htp #17965 more consistent and 22-ified javadsl handleWith
This commit is contained in:
Konrad Malawski 2015-07-15 12:22:46 +02:00
commit 77d3e693c5
27 changed files with 339 additions and 272 deletions

View file

@ -32,12 +32,12 @@ public class HighLevelServerExample extends HttpApp {
public Route createRoute() { public Route createRoute() {
// This handler generates responses to `/hello?name=XXX` requests // This handler generates responses to `/hello?name=XXX` requests
Route helloRoute = Route helloRoute =
handleWith(name, handleWith1(name,
// in Java 8 the following becomes simply // in Java 8 the following becomes simply
// (ctx, name) -> ctx.complete("Hello " + name + "!") // (ctx, name) -> ctx.complete("Hello " + name + "!")
new Handler1<String>() { new Handler1<String>() {
@Override @Override
public RouteResult handle(RequestContext ctx, String name) { public RouteResult apply(RequestContext ctx, String name) {
return ctx.complete("Hello " + name + "!"); return ctx.complete("Hello " + name + "!");
} }
}); });

View file

@ -28,7 +28,7 @@ import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
public class HttpServerExampleSpec { public class HttpServerExampleDocTest {
public static void bindingExample() { public static void bindingExample() {
//#binding-example //#binding-example
ActorSystem system = ActorSystem.create(); ActorSystem system = ActorSystem.create();

View file

@ -44,7 +44,7 @@ public class PathDirectiveExampleTest extends JUnitRouteTest {
Handler1<Integer> completeWithUserId = Handler1<Integer> completeWithUserId =
new Handler1<Integer>() { new Handler1<Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer userId) { public RouteResult apply(RequestContext ctx, Integer userId) {
return ctx.complete("Hello user " + userId); return ctx.complete("Hello user " + userId);
} }
}; };

View file

@ -7,9 +7,9 @@ Handlers implement the actual application-defined logic for a certain trace in t
the routing tree will be routes created from handlers. Creating a ``Route`` from a handler is achieved using the the routing tree will be routes created from handlers. Creating a ``Route`` from a handler is achieved using the
``BasicDirectives.handleWith`` overloads. They come in several forms: ``BasicDirectives.handleWith`` overloads. They come in several forms:
* with a single ``Handler`` argument * with a single ``Handler`` argument and a variable number of ``RequestVal<?>`` (may be 0)
* with a number ``n`` of ``RequestVal<T1>`` arguments and a ``HandlerN<T1, .., TN>`` argument * with a number ``n`` of ``RequestVal<T1>`` arguments and a ``HandlerN<T1, .., TN>`` argument
* with a ``Class<?>`` and/or instance and a method name String argument and a variable number of ``RequestVal<?>`` * with a ``Class<?>`` and/or instance and a method name String argument and a variable number of ``RequestVal<?>`` (may be 0)
arguments arguments
Simple Handler Simple Handler
@ -24,7 +24,7 @@ by inspecting the ``RequestContext`` and returning a ``RouteResult``:
Such a handler inspects the ``RequestContext`` it receives and uses the ``RequestContext``'s methods to Such a handler inspects the ``RequestContext`` it receives and uses the ``RequestContext``'s methods to
create a response: create a response:
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java .. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: simple-handler :include: simple-handler
The handler can include any kind of logic but must return a ``RouteResult`` in the end which can only The handler can include any kind of logic but must return a ``RouteResult`` in the end which can only
@ -32,7 +32,7 @@ be created by using one of the ``RequestContext`` methods.
A handler instance can be used once or several times as shown in the full example: A handler instance can be used once or several times as shown in the full example:
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java .. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: simple-handler-example-full :include: simple-handler-example-full
Handlers and Request Values Handlers and Request Values
@ -42,14 +42,14 @@ In many cases, instead of manually inspecting the request, a handler will make u
to extract details from the request. This is possible using one of the other ``handleWith`` overloads that bind to extract details from the request. This is possible using one of the other ``handleWith`` overloads that bind
the values of one or more request values with a ``HandlerN`` instance to produce a ``Route``: the values of one or more request values with a ``HandlerN`` instance to produce a ``Route``:
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java .. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: handler2 :include: handler2
The handler here implements multiplication of two integers. However, it doesn't need to specify where these The handler here implements multiplication of two integers. However, it doesn't need to specify where these
parameters come from. In ``handleWith``, as many request values of the matching type have to be specified as the parameters come from. In ``handleWith``, as many request values of the matching type have to be specified as the
handler needs. This can be seen in the full example: handler needs. This can be seen in the full example:
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java .. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: handler2-example-full :include: handler2-example-full
Here, the handler is again being reused. First, in creating a route that expects URI parameters ``x`` and ``y``. This Here, the handler is again being reused. First, in creating a route that expects URI parameters ``x`` and ``y``. This
@ -59,27 +59,44 @@ route structure, this time representing segments from the URI path.
Handlers in Java 8 Handlers in Java 8
------------------ ------------------
In Java 8 handlers can be provided as function literals. The previous example can then be written like this: Handlers are in fact simply classes which extend ``akka.japi.function.FunctionN`` in order to make reasoning
about the number of handled arguments easier. For example, a :class:`Handler1[String]` is simply a
``Function2[RequestContext, String, RouteResult]``. You can think of handlers as hot-dogs, where each ``T``
type represents a sausage, put between the "buns" which are ``RequestContext`` and ``RouteResult``.
In Java 8 handlers can be provided as function literals or method references. The example from before then looks like this:
.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: handler2-java8-example-full
.. note::
The reason the ``handleWith##`` methods include the number of handled values is because otherwise (if overloading would
be used, for all 22 methods) error messages generated by ``javac`` end up being very long and not readable, i.e.
if one type of a handler does not match the given values, *all* possible candidates would be printed in the error message
(22 of them), instead of just the one arity-matching method, pointing out that the type does not match.
We opted for better error messages as we feel this is more helpful when developing applications,
instead of having one overloaded method which looks nice when everything works, but procudes hard to read error
messages if something does not match up.
.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleSpec.java
:include: handler2-example-full
Providing Handlers by Reflection Providing Handlers by Reflection
-------------------------------- --------------------------------
Using Java before Java 8, writing out handlers as (anonymous) classes can be unwieldy. Therefore, ``handleWith`` Using Java before Java 8, writing out handlers as (anonymous) classes can be unwieldy. Therefore, ``handleReflectively``
overloads are provided that allow writing handler as simple methods and specifying them by name: overloads are provided that allow writing handler as simple methods and specifying them by name:
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java .. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: reflective :include: reflective
The complete calculator example can then be written like this: The complete calculator example can then be written like this:
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java .. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
:include: reflective-example-full :include: reflective-example-full
There are alternative overloads for ``handleWith`` that take a ``Class`` instead of an object instance to refer to There are alternative overloads for ``handleReflectively`` that take a ``Class`` instead of an object instance to refer to
static methods. The referenced method must be publicly accessible. static methods. The referenced method must be publicly accessible.
Deferring Result Creation Deferring Result Creation

View file

@ -7,7 +7,7 @@ The Akka HTTP :ref:`http-low-level-server-side-api-java` provides a ``Flow``- or
an application to respond to incoming HTTP requests by simply mapping requests to responses an application to respond to incoming HTTP requests by simply mapping requests to responses
(excerpt from :ref:`Low-level server side example <http-low-level-server-side-example-java>`): (excerpt from :ref:`Low-level server side example <http-low-level-server-side-example-java>`):
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java .. includecode:: ../../code/docs/http/javadsl/HttpServerExampleDocTest.java
:include: request-handler :include: request-handler
While it'd be perfectly possible to define a complete REST API service purely by inspecting the incoming While it'd be perfectly possible to define a complete REST API service purely by inspecting the incoming

View file

@ -62,7 +62,7 @@ Starting and Stopping
On the most basic level an Akka HTTP server is bound by invoking the ``bind`` method of the `akka.http.javadsl.Http`_ On the most basic level an Akka HTTP server is bound by invoking the ``bind`` method of the `akka.http.javadsl.Http`_
extension: extension:
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java .. includecode:: ../../code/docs/http/javadsl/HttpServerExampleDocTest.java
:include: binding-example :include: binding-example
Arguments to the ``Http().bind`` method specify the interface and port to bind to and register interest in handling Arguments to the ``Http().bind`` method specify the interface and port to bind to and register interest in handling
@ -99,7 +99,7 @@ Requests are handled by calling one of the ``handleWithXXX`` methods with a hand
Here is a complete example: Here is a complete example:
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java .. includecode:: ../../code/docs/http/javadsl/HttpServerExampleDocTest.java
:include: full-server-example :include: full-server-example
In this example, a request is handled by transforming the request stream with a function ``Function<HttpRequest, HttpResponse>`` In this example, a request is handled by transforming the request stream with a function ``Function<HttpRequest, HttpResponse>``

View file

@ -7,25 +7,27 @@ package akka.http.scaladsl
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.{ Collection JCollection } import java.util.{ Collection JCollection }
import javax.net.ssl.{ SSLParameters, SSLContext } import javax.net.ssl.{ SSLContext, SSLParameters }
import com.typesafe.config.Config
import scala.util.Try import akka.actor._
import scala.util.control.NonFatal
import scala.collection.{ JavaConverters, immutable }
import scala.concurrent.{ ExecutionContext, Promise, Future }
import akka.japi
import akka.event.LoggingAdapter import akka.event.LoggingAdapter
import akka.http._
import akka.http.impl.engine.client._
import akka.http.impl.engine.server._
import akka.http.impl.util.StreamUtils
import akka.http.scaladsl.model._
import akka.http.scaladsl.model.headers.Host
import akka.http.scaladsl.util.FastFuture
import akka.japi
import akka.stream.Materializer import akka.stream.Materializer
import akka.stream.io._ import akka.stream.io._
import akka.stream.scaladsl._ import akka.stream.scaladsl._
import akka.http.impl.util.StreamUtils import com.typesafe.config.Config
import akka.http.impl.engine.client._
import akka.http.impl.engine.server._ import scala.collection.immutable
import akka.http.scaladsl.util.FastFuture import scala.concurrent.{ ExecutionContext, Future, Promise }
import akka.http.scaladsl.model.headers.Host import scala.util.Try
import akka.http.scaladsl.model._ import scala.util.control.NonFatal
import akka.http._
import akka.actor._
class HttpExt(config: Config)(implicit system: ActorSystem) extends akka.actor.Extension { class HttpExt(config: Config)(implicit system: ActorSystem) extends akka.actor.Extension {
@ -397,8 +399,9 @@ class HttpExt(config: Config)(implicit system: ActorSystem) extends akka.actor.E
* method call the respective connection pools will be restarted and not contribute to the returned future. * method call the respective connection pools will be restarted and not contribute to the returned future.
*/ */
def shutdownAllConnectionPools(): Future[Unit] = { def shutdownAllConnectionPools(): Future[Unit] = {
import scala.collection.JavaConverters._
import system.dispatcher import system.dispatcher
import scala.collection.JavaConverters._
val gateways = hostPoolCache.values().asScala val gateways = hostPoolCache.values().asScala
system.log.info("Initiating orderly shutdown of all active host connections pools...") system.log.info("Initiating orderly shutdown of all active host connections pools...")
Future.sequence(gateways.map(_.flatMap(_.shutdown()))).map(_ ()) Future.sequence(gateways.map(_.flatMap(_.shutdown()))).map(_ ())
@ -575,7 +578,7 @@ object Http extends ExtensionId[HttpExt] with ExtensionIdProvider {
new HttpExt(system.settings.config getConfig "akka.http")(system) new HttpExt(system.settings.config getConfig "akka.http")(system)
} }
import JavaConverters._ import scala.collection.JavaConverters._
//# https-context-impl //# https-context-impl
case class HttpsContext(sslContext: SSLContext, case class HttpsContext(sslContext: SSLContext,

View file

@ -4,14 +4,14 @@
package akka.http.javadsl.testkit package akka.http.javadsl.testkit
import akka.http.javadsl.server._
import Directives._
import org.junit.rules.ExternalResource
import org.junit.{ Rule, Assert }
import scala.concurrent.duration._
import akka.actor.ActorSystem import akka.actor.ActorSystem
import akka.stream.ActorMaterializer import akka.http.javadsl.server._
import akka.http.scaladsl.model.HttpResponse import akka.http.scaladsl.model.HttpResponse
import akka.stream.ActorMaterializer
import org.junit.rules.ExternalResource
import org.junit.{ Assert, Rule }
import scala.concurrent.duration._
/** /**
* A RouteTest that uses JUnit assertions. * A RouteTest that uses JUnit assertions.
@ -39,8 +39,8 @@ abstract class JUnitRouteTestBase extends RouteTest {
} }
protected def completeWithValueToString[T](value: RequestVal[T]): Route = protected def completeWithValueToString[T](value: RequestVal[T]): Route =
handleWith(value, new Handler1[T] { handleWith1(value, new Handler1[T] {
def handle(ctx: RequestContext, t: T): RouteResult = ctx.complete(t.toString) def apply(ctx: RequestContext, t: T): RouteResult = ctx.complete(t.toString)
}) })
} }
abstract class JUnitRouteTest extends JUnitRouteTestBase { abstract class JUnitRouteTest extends JUnitRouteTestBase {

View file

@ -34,14 +34,14 @@ public class SimpleServerApp8 extends HttpApp {
} }
public void test() { public void test() {
handleWith(xSegment, ySegment, SimpleServerApp8::multiply); handleWith2(xSegment, ySegment, SimpleServerApp8::multiply);
} }
@Override @Override
public Route createRoute() { public Route createRoute() {
Handler addHandler = new Handler() { Handler addHandler = new Handler() {
@Override @Override
public RouteResult handle(RequestContext ctx) { public RouteResult apply(RequestContext ctx) {
int xVal = x.get(ctx); int xVal = x.get(ctx);
int yVal = y.get(ctx); int yVal = y.get(ctx);
int result = xVal + yVal; int result = xVal + yVal;
@ -49,7 +49,7 @@ public class SimpleServerApp8 extends HttpApp {
} }
}; };
Handler2<Integer, Integer> subtractHandler = new Handler2<Integer, Integer>() { Handler2<Integer, Integer> subtractHandler = new Handler2<Integer, Integer>() {
public RouteResult handle(RequestContext ctx, Integer xVal, Integer yVal) { public RouteResult apply(RequestContext ctx, Integer xVal, Integer yVal) {
int result = xVal - yVal; int result = xVal - yVal;
return ctx.complete(String.format("%d - %d = %d", xVal, yVal, result)); return ctx.complete(String.format("%d - %d = %d", xVal, yVal, result));
} }
@ -63,13 +63,13 @@ public class SimpleServerApp8 extends HttpApp {
), ),
// matches paths like this: /add?x=42&y=23 // matches paths like this: /add?x=42&y=23
path("add").route( path("add").route(
handleWith(addHandler, x, y) handleWith(addHandler)
), ),
path("subtract").route( path("subtract").route(
handleWith(x, y, subtractHandler) handleWith2(x, y, subtractHandler)
), ),
path("divide").route( path("divide").route(
handleWith(x, y, handleWith2(x, y,
(ctx, x, y) -> (ctx, x, y) ->
ctx.complete(String.format("%d / %d = %d", x, y, x / y)) ctx.complete(String.format("%d / %d = %d", x, y, x / y))
) )
@ -77,11 +77,11 @@ public class SimpleServerApp8 extends HttpApp {
// matches paths like this: /multiply/{x}/{y} // matches paths like this: /multiply/{x}/{y}
path("multiply", xSegment, ySegment).route( path("multiply", xSegment, ySegment).route(
// bind handler by reflection // bind handler by reflection
handleWith(xSegment, ySegment, SimpleServerApp8::multiply) handleWith2(xSegment, ySegment, SimpleServerApp8::multiply)
), ),
path("multiply-methodref", xSegment, ySegment).route( path("multiply-methodref", xSegment, ySegment).route(
// bind handler by reflection // bind handler by reference to new instance of handler
handleWith(xSegment, ySegment, new Test(123)::constantPlusMultiply) handleWith2(xSegment, ySegment, new Test(123)::constantPlusMultiply)
) )
); );
} }

View file

@ -1,16 +1,14 @@
/* /*
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com> * Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/ */
import akka.http.javadsl.server.HandlerBindingTest; import akka.http.javadsl.server.HandlerBindingTest;
import docs.http.javadsl.server.HandlerExampleSpec;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.junit.runners.Suite; import org.junit.runners.Suite;
@RunWith(Suite.class) @RunWith(Suite.class)
@Suite.SuiteClasses({ @Suite.SuiteClasses({
HandlerBindingTest.class, HandlerBindingTest.class
HandlerExampleSpec.class
}) })
public class AllJavaTests { public class AllJavaTests {
} }

View file

@ -8,7 +8,6 @@ import akka.http.scaladsl.model.HttpRequest;
import org.junit.Test; import org.junit.Test;
import akka.http.javadsl.testkit.*; import akka.http.javadsl.testkit.*;
import akka.http.javadsl.server.values.*; import akka.http.javadsl.server.values.*;
import static akka.http.javadsl.server.Directives.*;
public class HandlerBindingTest extends JUnitRouteTest { public class HandlerBindingTest extends JUnitRouteTest {
Parameter<Integer> aParam = Parameters.intValue("a"); Parameter<Integer> aParam = Parameters.intValue("a");
@ -24,7 +23,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
} }
@Test @Test
public void testHandler1() { public void testHandler1() {
Route route = handleWith(aParam, (ctx, a) -> ctx.complete("Ok " + a)); Route route = handleWith1(aParam, (ctx, a) -> ctx.complete("Ok " + a));
TestResponse response = runRoute(route, HttpRequest.GET("?a=23")); TestResponse response = runRoute(route, HttpRequest.GET("?a=23"));
response.assertStatusCode(200); response.assertStatusCode(200);
response.assertEntity("Ok 23"); response.assertEntity("Ok 23");
@ -32,7 +31,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
@Test @Test
public void testHandler2() { public void testHandler2() {
Route route = Route route =
handleWith( handleWith2(
aParam, aParam,
bParam, bParam,
(ctx, a, b) -> ctx.complete("Sum: " + (a + b))); (ctx, a, b) -> ctx.complete("Sum: " + (a + b)));
@ -43,7 +42,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
@Test @Test
public void testHandler3() { public void testHandler3() {
Route route = Route route =
handleWith( handleWith3(
aParam, aParam,
bParam, bParam,
cParam, cParam,
@ -55,7 +54,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
@Test @Test
public void testHandler4() { public void testHandler4() {
Route route = Route route =
handleWith( handleWith4(
aParam, aParam,
bParam, bParam,
cParam, cParam,
@ -71,7 +70,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
@Test @Test
public void testHandler4MethodRef() { public void testHandler4MethodRef() {
Route route = Route route =
handleWith( handleWith4(
aParam, aParam,
bParam, bParam,
cParam, cParam,

View file

@ -2,8 +2,9 @@
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com> * Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/ */
package docs.http.javadsl; package docs.http.javadsl.server;
import akka.dispatch.Futures;
import akka.http.javadsl.model.HttpRequest; import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.server.*; import akka.http.javadsl.server.*;
import akka.http.javadsl.server.values.Parameters; import akka.http.javadsl.server.values.Parameters;
@ -12,7 +13,7 @@ import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.testkit.TestRoute; import akka.http.javadsl.testkit.TestRoute;
import org.junit.Test; import org.junit.Test;
public class HandlerExampleSpec extends JUnitRouteTest { public class HandlerExampleDocTest extends JUnitRouteTest {
@Test @Test
public void testSimpleHandler() { public void testSimpleHandler() {
//#simple-handler-example-full //#simple-handler-example-full
@ -20,7 +21,7 @@ public class HandlerExampleSpec extends JUnitRouteTest {
//#simple-handler //#simple-handler
Handler handler = new Handler() { Handler handler = new Handler() {
@Override @Override
public RouteResult handle(RequestContext ctx) { public RouteResult apply(RequestContext ctx) {
return ctx.complete("This was a " + ctx.request().method().value() + return ctx.complete("This was a " + ctx.request().method().value() +
" request to "+ctx.request().getUri()); " request to "+ctx.request().getUri());
} }
@ -67,16 +68,16 @@ public class HandlerExampleSpec extends JUnitRouteTest {
RequestVal<Integer> ySegment = PathMatchers.intValue(); RequestVal<Integer> ySegment = PathMatchers.intValue();
//#handler2 //#handler2
Handler2<Integer, Integer> multiply = final Handler2<Integer, Integer> multiply =
new Handler2<Integer, Integer>() { new Handler2<Integer, Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer x, Integer y) { public RouteResult apply(RequestContext ctx, Integer x, Integer y) {
int result = x * y; int result = x * y;
return ctx.complete("x * y = " + result); return ctx.complete("x * y = " + result);
} }
}; };
Route multiplyXAndYParam = handleWith(xParam, yParam, multiply); final Route multiplyXAndYParam = handleWith2(xParam, yParam, multiply);
//#handler2 //#handler2
Route createRoute() { Route createRoute() {
@ -87,7 +88,7 @@ public class HandlerExampleSpec extends JUnitRouteTest {
multiplyXAndYParam multiplyXAndYParam
), ),
path("path-multiply", xSegment, ySegment).route( path("path-multiply", xSegment, ySegment).route(
handleWith(xSegment, ySegment, multiply) handleWith2(xSegment, ySegment, multiply)
) )
) )
) )
@ -107,6 +108,63 @@ public class HandlerExampleSpec extends JUnitRouteTest {
//#handler2-example-full //#handler2-example-full
} }
@Test
public void testCalculatorJava8() {
//#handler2-java8-example-full
class TestHandler extends akka.http.javadsl.server.AllDirectives {
final RequestVal<Integer> xParam = Parameters.intValue("x");
final RequestVal<Integer> yParam = Parameters.intValue("y");
//#handler2-java8
final Handler2<Integer, Integer> multiply =
(ctx, x, y) -> ctx.complete("x * y = " + (x * y));
final Route multiplyXAndYParam = handleWith2(xParam, yParam, multiply);
//#handler2-java8
RouteResult subtract(RequestContext ctx, int x, int y) {
return ctx.complete("x - y = " + (x - y));
}
Route createRoute() {
return route(
get(
pathPrefix("calculator").route(
path("multiply").route(
// use Handler explicitly
multiplyXAndYParam
),
path("add").route(
// create Handler as lambda expression
handleWith2(xParam, yParam,
(ctx, x, y) -> ctx.complete("x + y = " + (x + y)))
),
path("subtract").route(
// create handler by lifting method
handleWith2(xParam, yParam, this::subtract)
)
)
)
);
}
}
// actual testing code
TestRoute r = testRoute(new TestHandler().createRoute());
r.run(HttpRequest.GET("/calculator/multiply?x=12&y=42"))
.assertStatusCode(200)
.assertEntity("x * y = 504");
r.run(HttpRequest.GET("/calculator/add?x=12&y=42"))
.assertStatusCode(200)
.assertEntity("x + y = 54");
r.run(HttpRequest.GET("/calculator/subtract?x=42&y=12"))
.assertStatusCode(200)
.assertEntity("x - y = 30");
//#handler2-java8-example-full
}
@Test @Test
public void testCalculatorReflective() { public void testCalculatorReflective() {
//#reflective-example-full //#reflective-example-full
@ -124,7 +182,7 @@ public class HandlerExampleSpec extends JUnitRouteTest {
return ctx.complete("x * y = " + result); return ctx.complete("x * y = " + result);
} }
Route multiplyXAndYParam = handleWith(this, "multiply", xParam, yParam); Route multiplyXAndYParam = handleReflectively(this, "multiply", xParam, yParam);
//#reflective //#reflective
Route createRoute() { Route createRoute() {
@ -135,7 +193,7 @@ public class HandlerExampleSpec extends JUnitRouteTest {
multiplyXAndYParam multiplyXAndYParam
), ),
path("path-multiply", xSegment, ySegment).route( path("path-multiply", xSegment, ySegment).route(
handleWith(this, "multiply", xSegment, ySegment) handleWith2(xSegment, ySegment, this::multiply)
) )
) )
) )

View file

@ -1,57 +0,0 @@
/*
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package docs.http.javadsl.server;
import akka.http.javadsl.model.HttpRequest;
import akka.http.javadsl.server.*;
import akka.http.javadsl.server.values.Parameters;
import akka.http.javadsl.testkit.JUnitRouteTest;
import akka.http.javadsl.testkit.TestRoute;
import org.junit.Test;
public class HandlerExampleSpec extends JUnitRouteTest {
@Test
public void testCalculator() {
//#handler2-example-full
class TestHandler extends akka.http.javadsl.server.AllDirectives {
RequestVal<Integer> xParam = Parameters.intValue("x");
RequestVal<Integer> yParam = Parameters.intValue("y");
//#handler2
Handler2<Integer, Integer> multiply =
(ctx, x, y) -> ctx.complete("x * y = " + (x * y));
Route multiplyXAndYParam = handleWith(xParam, yParam, multiply);
//#handler2
Route createRoute() {
return route(
get(
pathPrefix("calculator").route(
path("multiply").route(
multiplyXAndYParam
),
path("add").route(
handleWith(xParam, yParam,
(ctx, x, y) -> ctx.complete("x + y = " + (x + y)))
)
)
)
);
}
}
// actual testing code
TestRoute r = testRoute(new TestHandler().createRoute());
r.run(HttpRequest.GET("/calculator/multiply?x=12&y=42"))
.assertStatusCode(200)
.assertEntity("x * y = 504");
r.run(HttpRequest.GET("/calculator/add?x=12&y=42"))
.assertStatusCode(200)
.assertEntity("x + y = 54");
//#handler2-example-full
}
}

View file

@ -26,7 +26,7 @@ public class PetStoreExample {
final RequestVal<Pet> existingPet = RequestVals.lookupInMap(petId, Pet.class, pets); final RequestVal<Pet> existingPet = RequestVals.lookupInMap(petId, Pet.class, pets);
Handler1<Pet> putPetHandler = new Handler1<Pet>() { Handler1<Pet> putPetHandler = new Handler1<Pet>() {
public RouteResult handle(RequestContext ctx, Pet thePet) { public RouteResult apply(RequestContext ctx, Pet thePet) {
pets.put(thePet.getId(), thePet); pets.put(thePet.getId(), thePet);
return ctx.completeAs(Jackson.json(), thePet); return ctx.completeAs(Jackson.json(), thePet);
} }
@ -44,10 +44,10 @@ public class PetStoreExample {
get(extractAndComplete(Jackson.<Pet>json(), existingPet)), get(extractAndComplete(Jackson.<Pet>json(), existingPet)),
// 2. using a handler // 2. using a handler
put(handleWith(petEntity, putPetHandler)), put(handleWith1(petEntity, putPetHandler)),
// 3. calling a method of a controller instance reflectively // 3. calling a method of a controller instance reflectively
delete(handleWith(controller, "deletePet", petId)) delete(handleReflectively(controller, "deletePet", petId))
) )
); );
} }

View file

@ -41,7 +41,7 @@ public class SimpleServerApp extends HttpApp {
public Route createRoute() { public Route createRoute() {
Handler addHandler = new Handler() { Handler addHandler = new Handler() {
@Override @Override
public RouteResult handle(RequestContext ctx) { public RouteResult apply(RequestContext ctx) {
int xVal = x.get(ctx); int xVal = x.get(ctx);
int yVal = y.get(ctx); int yVal = y.get(ctx);
int result = xVal + yVal; int result = xVal + yVal;
@ -49,7 +49,7 @@ public class SimpleServerApp extends HttpApp {
} }
}; };
Handler2<Integer, Integer> subtractHandler = new Handler2<Integer, Integer>() { Handler2<Integer, Integer> subtractHandler = new Handler2<Integer, Integer>() {
public RouteResult handle(RequestContext ctx, Integer xVal, Integer yVal) { public RouteResult apply(RequestContext ctx, Integer xVal, Integer yVal) {
int result = xVal - yVal; int result = xVal - yVal;
return ctx.complete(String.format("%d - %d = %d", xVal, yVal, result)); return ctx.complete(String.format("%d - %d = %d", xVal, yVal, result));
} }
@ -57,7 +57,7 @@ public class SimpleServerApp extends HttpApp {
Handler1<String> helloPostHandler = Handler1<String> helloPostHandler =
new Handler1<String>() { new Handler1<String>() {
@Override @Override
public RouteResult handle(RequestContext ctx, String s) { public RouteResult apply(RequestContext ctx, String s) {
return ctx.complete("Hello " + s + "!"); return ctx.complete("Hello " + s + "!");
} }
}; };
@ -72,20 +72,20 @@ public class SimpleServerApp extends HttpApp {
handleWith(addHandler, x, y) handleWith(addHandler, x, y)
), ),
path("subtract").route( path("subtract").route(
handleWith(x, y, subtractHandler) handleWith2(x, y, subtractHandler)
), ),
// matches paths like this: /multiply/{x}/{y} // matches paths like this: /multiply/{x}/{y}
path("multiply", xSegment, ySegment).route( path("multiply", xSegment, ySegment).route(
// bind handler by reflection // bind handler by reflection
handleWith(SimpleServerApp.class, "multiply", xSegment, ySegment) handleReflectively(SimpleServerApp.class, "multiply", xSegment, ySegment)
), ),
path("multiplyAsync", xSegment, ySegment).route( path("multiplyAsync", xSegment, ySegment).route(
// bind async handler by reflection // bind async handler by reflection
handleWith(SimpleServerApp.class, "multiplyAsync", xSegment, ySegment) handleReflectively(SimpleServerApp.class, "multiplyAsync", xSegment, ySegment)
), ),
post( post(
path("hello").route( path("hello").route(
handleWith(bodyAsName, helloPostHandler) handleWith1(bodyAsName, helloPostHandler)
) )
) )
); );

View file

@ -51,7 +51,7 @@ public class CompleteTest extends JUnitRouteTest {
Handler2<Integer, Integer> slowCalc = new Handler2<Integer, Integer>() { Handler2<Integer, Integer> slowCalc = new Handler2<Integer, Integer>() {
@Override @Override
public RouteResult handle(final RequestContext ctx, final Integer x, final Integer y) { public RouteResult apply(final RequestContext ctx, final Integer x, final Integer y) {
return ctx.completeWith(Futures.future(new Callable<RouteResult>() { return ctx.completeWith(Futures.future(new Callable<RouteResult>() {
@Override @Override
public RouteResult call() throws Exception { public RouteResult call() throws Exception {
@ -62,7 +62,7 @@ public class CompleteTest extends JUnitRouteTest {
} }
}; };
Route route = handleWith(x, y, slowCalc); Route route = handleWith2(x, y, slowCalc);
runRoute(route, HttpRequest.GET("add?x=42&y=23")) runRoute(route, HttpRequest.GET("add?x=42&y=23"))
.assertStatusCode(200) .assertStatusCode(200)
.assertEntity("42 + 23 = 65"); .assertEntity("42 + 23 = 65");

View file

@ -16,7 +16,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
Route route = handleWith( Route route = handleWith(
new Handler() { new Handler() {
@Override @Override
public RouteResult handle(RequestContext ctx) { public RouteResult apply(RequestContext ctx) {
return ctx.complete("Ok"); return ctx.complete("Ok");
} }
} }
@ -32,8 +32,8 @@ public class HandlerBindingTest extends JUnitRouteTest {
Route route = handleWith( Route route = handleWith(
new Handler() { new Handler() {
@Override @Override
public RouteResult handle(RequestContext ctx) { public RouteResult apply(RequestContext ctx) {
return ctx.complete("Ok a:" + a.get(ctx) +" b:" + b.get(ctx)); return ctx.complete("Ok a:" + a.get(ctx) + " b:" + b.get(ctx));
} }
}, a, b }, a, b
); );
@ -47,7 +47,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
Route route = handleWith( Route route = handleWith(
new Handler() { new Handler() {
@Override @Override
public RouteResult handle(RequestContext ctx) { public RouteResult apply(RequestContext ctx) {
return ctx.complete("Ok " + a.get(ctx)); return ctx.complete("Ok " + a.get(ctx));
} }
}, a }, a
@ -60,11 +60,10 @@ public class HandlerBindingTest extends JUnitRouteTest {
public void testHandler1() { public void testHandler1() {
final Parameter<Integer> a = Parameters.intValue("a"); final Parameter<Integer> a = Parameters.intValue("a");
Route route = handleWith( Route route = handleWith1(a,
a,
new Handler1<Integer>() { new Handler1<Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer a) { public RouteResult apply(RequestContext ctx, Integer a) {
return ctx.complete("Ok " + a); return ctx.complete("Ok " + a);
} }
} }
@ -75,12 +74,12 @@ public class HandlerBindingTest extends JUnitRouteTest {
} }
@Test @Test
public void testHandler2() { public void testHandler2() {
Route route = handleWith( Route route = handleWith2(
Parameters.intValue("a"), Parameters.intValue("a"),
Parameters.intValue("b"), Parameters.intValue("b"),
new Handler2<Integer, Integer>() { new Handler2<Integer, Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer a, Integer b) { public RouteResult apply(RequestContext ctx, Integer a, Integer b) {
return ctx.complete("Sum: " + (a + b)); return ctx.complete("Sum: " + (a + b));
} }
} }
@ -91,13 +90,13 @@ public class HandlerBindingTest extends JUnitRouteTest {
} }
@Test @Test
public void testHandler3() { public void testHandler3() {
Route route = handleWith( Route route = handleWith3(
Parameters.intValue("a"), Parameters.intValue("a"),
Parameters.intValue("b"), Parameters.intValue("b"),
Parameters.intValue("c"), Parameters.intValue("c"),
new Handler3<Integer, Integer, Integer>() { new Handler3<Integer, Integer, Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer a, Integer b, Integer c) { public RouteResult apply(RequestContext ctx, Integer a, Integer b, Integer c) {
return ctx.complete("Sum: " + (a + b + c)); return ctx.complete("Sum: " + (a + b + c));
} }
} }
@ -108,14 +107,14 @@ public class HandlerBindingTest extends JUnitRouteTest {
} }
@Test @Test
public void testHandler4() { public void testHandler4() {
Route route = handleWith( Route route = handleWith4(
Parameters.intValue("a"), Parameters.intValue("a"),
Parameters.intValue("b"), Parameters.intValue("b"),
Parameters.intValue("c"), Parameters.intValue("c"),
Parameters.intValue("d"), Parameters.intValue("d"),
new Handler4<Integer, Integer, Integer, Integer>() { new Handler4<Integer, Integer, Integer, Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer a, Integer b, Integer c, Integer d) { public RouteResult apply(RequestContext ctx, Integer a, Integer b, Integer c, Integer d) {
return ctx.complete("Sum: " + (a + b + c + d)); return ctx.complete("Sum: " + (a + b + c + d));
} }
} }
@ -131,7 +130,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
return ctx.complete("Negated: " + (- a)); return ctx.complete("Negated: " + (- a));
} }
} }
Route route = handleWith(new Test(), "negate", Parameters.intValue("a")); Route route = handleReflectively(new Test(), "negate", Parameters.intValue("a"));
runRoute(route, HttpRequest.GET("?a=23")) runRoute(route, HttpRequest.GET("?a=23"))
.assertStatusCode(200) .assertStatusCode(200)
.assertEntity("Negated: -23"); .assertEntity("Negated: -23");
@ -142,7 +141,7 @@ public class HandlerBindingTest extends JUnitRouteTest {
} }
@Test @Test
public void testStaticReflectiveHandler() { public void testStaticReflectiveHandler() {
Route route = handleWith(HandlerBindingTest.class, "squared", Parameters.intValue("a")); Route route = handleReflectively(HandlerBindingTest.class, "squared", Parameters.intValue("a"));
runRoute(route, HttpRequest.GET("?a=23")) runRoute(route, HttpRequest.GET("?a=23"))
.assertStatusCode(200) .assertStatusCode(200)
.assertEntity("Squared: 529"); .assertEntity("Squared: 529");

View file

@ -37,7 +37,7 @@ public class MarshallerTest extends JUnitRouteTest {
Handler1<Integer> nummerHandler = new Handler1<Integer>() { Handler1<Integer> nummerHandler = new Handler1<Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer integer) { public RouteResult apply(RequestContext ctx, Integer integer) {
return ctx.completeAs(numberAsNameMarshaller, integer); return ctx.completeAs(numberAsNameMarshaller, integer);
} }
}; };
@ -46,7 +46,7 @@ public class MarshallerTest extends JUnitRouteTest {
testRoute( testRoute(
get( get(
path("nummer").route( path("nummer").route(
handleWith(n, nummerHandler) handleWith1(n, nummerHandler)
) )
) )
); );
@ -88,7 +88,7 @@ public class MarshallerTest extends JUnitRouteTest {
Handler1<Integer> nummerHandler = new Handler1<Integer>() { Handler1<Integer> nummerHandler = new Handler1<Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer integer) { public RouteResult apply(RequestContext ctx, Integer integer) {
return ctx.completeAs(numberAsJsonListMarshaller, integer); return ctx.completeAs(numberAsJsonListMarshaller, integer);
} }
}; };
@ -97,7 +97,7 @@ public class MarshallerTest extends JUnitRouteTest {
testRoute( testRoute(
get( get(
path("nummer").route( path("nummer").route(
handleWith(n, nummerHandler) handleWith1(n, nummerHandler)
) )
) )
); );
@ -132,7 +132,7 @@ public class MarshallerTest extends JUnitRouteTest {
Handler1<Integer> nummerHandler = new Handler1<Integer>() { Handler1<Integer> nummerHandler = new Handler1<Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer integer) { public RouteResult apply(RequestContext ctx, Integer integer) {
return ctx.completeAs(numberAsJsonListMarshaller, integer); return ctx.completeAs(numberAsJsonListMarshaller, integer);
} }
}; };
@ -141,7 +141,7 @@ public class MarshallerTest extends JUnitRouteTest {
testRoute( testRoute(
get( get(
path("nummer").route( path("nummer").route(
handleWith(n, nummerHandler) handleWith1(n, nummerHandler)
) )
) )
); );
@ -176,7 +176,7 @@ public class MarshallerTest extends JUnitRouteTest {
Handler1<Integer> nummerHandler = new Handler1<Integer>() { Handler1<Integer> nummerHandler = new Handler1<Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer integer) { public RouteResult apply(RequestContext ctx, Integer integer) {
return ctx.completeAs(numberAsJsonListMarshaller, integer); return ctx.completeAs(numberAsJsonListMarshaller, integer);
} }
}; };
@ -185,7 +185,7 @@ public class MarshallerTest extends JUnitRouteTest {
testRoute( testRoute(
get( get(
path("nummer").route( path("nummer").route(
handleWith(n, nummerHandler) handleWith1(n, nummerHandler)
) )
) )
); );

View file

@ -19,7 +19,7 @@ public class ExecutionDirectivesTest extends JUnitRouteTest {
Handler2<Integer, Integer> divide = Handler2<Integer, Integer> divide =
new Handler2<Integer, Integer>() { new Handler2<Integer, Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer a, Integer b) { public RouteResult apply(RequestContext ctx, Integer a, Integer b) {
int result = a / b; int result = a / b;
return ctx.complete("The result is: " + result); return ctx.complete("The result is: " + result);
} }
@ -44,7 +44,7 @@ public class ExecutionDirectivesTest extends JUnitRouteTest {
testRoute( testRoute(
handleExceptions(handleDivByZero, handleExceptions(handleDivByZero,
path("divide").route( path("divide").route(
handleWith(a, b, divide) handleWith2(a, b, divide)
) )
) )
); );

View file

@ -239,9 +239,9 @@ public class PathDirectivesTest extends JUnitRouteTest {
TestRoute route = TestRoute route =
testRoute( testRoute(
path("multiply", x, "with", y).route( path("multiply", x, "with", y).route(
handleWith(x, y, new Handler2<Integer, Integer>() { handleWith2(x, y, new Handler2<Integer, Integer>() {
@Override @Override
public RouteResult handle(RequestContext ctx, Integer x, Integer y) { public RouteResult apply(RequestContext ctx, Integer x, Integer y) {
return ctx.complete(String.format("%d * %d = %d", x, y, x * y)); return ctx.complete(String.format("%d * %d = %d", x, y, x * y));
} }
}) })

View file

@ -29,7 +29,7 @@ public class HttpBasicAuthenticationTest extends JUnitRouteTest {
Handler1<String> helloWorldHandler = Handler1<String> helloWorldHandler =
new Handler1<String>() { new Handler1<String>() {
@Override @Override
public RouteResult handle(RequestContext ctx, String user) { public RouteResult apply(RequestContext ctx, String user) {
return ctx.complete("Hello "+user+"!"); return ctx.complete("Hello "+user+"!");
} }
}; };
@ -38,7 +38,7 @@ public class HttpBasicAuthenticationTest extends JUnitRouteTest {
testRoute( testRoute(
path("secure").route( path("secure").route(
authenticatedUser.route( authenticatedUser.route(
handleWith(authenticatedUser, helloWorldHandler) handleWith1(authenticatedUser, helloWorldHandler)
) )
) )
); );

View file

@ -274,9 +274,9 @@ public class ParametersTest extends JUnitRouteTest {
@Test @Test
public void testParametersAsMapExtraction() { public void testParametersAsMapExtraction() {
TestRoute route = testRoute(handleWith(paramMap, new Handler1<Map<String, String>>(){ TestRoute route = testRoute(handleWith1(paramMap, new Handler1<Map<String, String>>(){
@Override @Override
public RouteResult handle(RequestContext ctx, Map<String, String> paramMap) { public RouteResult apply(RequestContext ctx, Map<String, String> paramMap) {
ArrayList<String> keys = new ArrayList<String>(paramMap.keySet()); ArrayList<String> keys = new ArrayList<String>(paramMap.keySet());
Collections.sort(keys); Collections.sort(keys);
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
@ -305,9 +305,9 @@ public class ParametersTest extends JUnitRouteTest {
} }
@Test @Test
public void testParametersAsMultiMapExtraction() { public void testParametersAsMultiMapExtraction() {
TestRoute route = testRoute(handleWith(paramMultiMap, new Handler1<Map<String, Collection<String>>>(){ TestRoute route = testRoute(handleWith1(paramMultiMap, new Handler1<Map<String, Collection<String>>>(){
@Override @Override
public RouteResult handle(RequestContext ctx, Map<String, Collection<String>> paramMap) { public RouteResult apply(RequestContext ctx, Map<String, Collection<String>> paramMap) {
ArrayList<String> keys = new ArrayList<String>(paramMap.keySet()); ArrayList<String> keys = new ArrayList<String>(paramMap.keySet());
Collections.sort(keys); Collections.sort(keys);
StringBuilder res = new StringBuilder(); StringBuilder res = new StringBuilder();
@ -342,9 +342,9 @@ public class ParametersTest extends JUnitRouteTest {
} }
@Test @Test
public void testParametersAsCollectionExtraction() { public void testParametersAsCollectionExtraction() {
TestRoute route = testRoute(handleWith(paramEntries, new Handler1<Collection<Map.Entry<String, String>>>(){ TestRoute route = testRoute(handleWith1(paramEntries, new Handler1<Collection<Map.Entry<String, String>>>(){
@Override @Override
public RouteResult handle(RequestContext ctx, Collection<Map.Entry<String, String>> paramEntries) { public RouteResult apply(RequestContext ctx, Collection<Map.Entry<String, String>> paramEntries) {
ArrayList<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(paramEntries); ArrayList<Map.Entry<String, String>> entries = new ArrayList<Map.Entry<String, String>>(paramEntries);
Collections.sort(entries, new Comparator<Map.Entry<String, String>>() { Collections.sort(entries, new Comparator<Map.Entry<String, String>>() {
@Override @Override

View file

@ -5,8 +5,6 @@
package akka.http.scaladsl.server package akka.http.scaladsl.server
package directives package directives
import akka.http.scaladsl.model.StatusCodes._
class SchemeDirectivesSpec extends RoutingSpec { class SchemeDirectivesSpec extends RoutingSpec {
"the extractScheme directive" should { "the extractScheme directive" should {
"extract the Uri scheme" in { "extract the Uri scheme" in {

View file

@ -0,0 +1,37 @@
/*
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.http.javadsl.server
import scala.concurrent.Future
[..21#/**
* A route Handler that handles a request (that is encapsulated in a [[RequestContext]])
* and returns a [[RouteResult]] with the response (or the rejection).
*
* A route `Handler1` is a convenience class that extends Function of arity `N+1`,
* since it needs to pass along the [[RequestContext]] as well, yet for readability
* purposes we can see it as "handles 1 route arguments".
*
* Use the methods in [[RequestContext]] to create a [[RouteResult]].
* A handler MUST NOT return `null` as the result.
*/
trait Handler1[[#T1#]] extends akka.japi.function.Function2[RequestContext, [#T1#], RouteResult] {
override def apply(ctx: RequestContext, [#t1: T1#]): RouteResult
}
/**
* A route Handler that handles a request (that is encapsulated in a [[RequestContext]])
* and returns a [[scala.concurrent.Future]] of [[RouteResult]] with the response (or the rejection).
*
* A route `Handler1` is a convenience class that extends Function of arity `N+1`,
* since it needs to pass along the [[RequestContext]] as well, yet for readability
* purposes we can see it as "handles 1 route arguments".
*
* Use the methods in [[RequestContext]] to create a [[RouteResult]].
* A handler MUST NOT return `null` as the result.
*/
trait AsyncHandler1[[#T1#]] extends akka.japi.function.Function2[RequestContext, [#T1#], Future[RouteResult]] {
override def apply(ctx: RequestContext, [#t1: T1#]): Future[RouteResult]
}#
]

View file

@ -0,0 +1,61 @@
/*
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.http.javadsl.server.directives
import akka.http.javadsl.server.Route
import akka.http.javadsl.server.RouteResult
import akka.http.javadsl.server.RequestVal
import akka.http.javadsl.server.RequestContext
import scala.annotation.varargs
import scala.concurrent.Future
abstract class BasicDirectivesBase {
/** INTERNAL API */
private[http] def handle(extractions: RequestVal[_]*)(f: RequestContext ⇒ RouteResult): Route
/**
* Handles the route using the given function.
* The function MUST NOT return `null`.
*
* If the `handler` is accessing request values these must be passed to this method in order for extraction to be performed.
*/
@varargs def handleWith(handler: akka.japi.function.Function[RequestContext, RouteResult], extractions: RequestVal[_]*): Route =
handle(extractions: _*)(ctx => handler(ctx))
/**
* Handles the route using the given function, completing the route once the returned [[scala.concurrent.Future]] completes.
* The function MUST NOT return `null`.
*
* If the `handler` is accessing request values these must be passed to this method in order for extraction to be performed.
*/
@varargs def handleWithAsync(handler: akka.japi.function.Function[RequestContext, Future[RouteResult]], extractions: RequestVal[_]*): Route =
handle(extractions: _*)(ctx => ctx.completeWith(handler(ctx)))
[..21#/**
* Handles the route using the given function. The function MUST NOT return `null`.
*
* For convenience, using Java 8 lambda expressions as the `handler` function is recommended.
* For Java 6 or 7 users the convenience [[akka.http.javadsl.server.Handler1]] class (which itself extends
* [[akka.japi.function.Function2]] should prove to be useful, as it matches naming-wise with the number of
* handled request values.
*/
def handleWith1[[#T1#]]([#v1: RequestVal[T1]#], handler: akka.japi.function.Function2[RequestContext, [#T1#], RouteResult]): Route =
handle([#v1#])(ctx => handler(ctx, [#v1.get(ctx)#]))
/**
* Handles the route using the given function, completing the route once the returned [[scala.concurrent.Future]] completes.
* The function MUST NOT return `null`.
*
* For convenience, using Java 8 lambda expressions as the `handler` function is recommended.
* For Java 6 or 7 users the convenience [[akka.http.javadsl.server.Handler1]] class (which itself extends
* [[akka.japi.function.Function2]] should prove to be useful, as it matches naming-wise with the number of
* handled request values.
*/
def handleWithAsync1[[#T1#]]([#v1: RequestVal[T1]#], handler: akka.japi.function.Function2[RequestContext, [#T1#], Future[RouteResult]]): Route =
handle([#v1#])(ctx => ctx.completeWith(handler(ctx, [#v1.get(ctx)#])))#
]
}

View file

@ -1,46 +1,33 @@
/* /*
* Copyright (C) 2009-2014 Typesafe Inc. <http://www.typesafe.com> * Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
*/ */
package akka.http.javadsl.server package akka.http.javadsl.server
import scala.concurrent.Future
/** /**
* A route Handler that handles a request (that is encapsulated in a [[RequestContext]]) * A route Handler that handles a request (that is encapsulated in a [[RequestContext]])
* and returns a [[RouteResult]] with the response (or the rejection). * and returns a [[RouteResult]] with the response (or the rejection).
* *
* Use the methods in [[RequestContext]] to create a [[RouteResult]]. A handler mustn't * Use the methods in [[RequestContext]] to create a [[RouteResult]].
* return [[null]] as the result. * A handler MUST NOT return `null` as the result.
*
* See also [[Handler1]], [[Handler2]], ..., until [[Handler21]] for handling `N` request values.
*/ */
//#handler //#handler
trait Handler { trait Handler extends akka.japi.function.Function[RequestContext, RouteResult] {
def handle(ctx: RequestContext): RouteResult override def apply(ctx: RequestContext): RouteResult
} }
//#handler //#handler
/** /**
* A route handler with one additional argument. * A route Handler that handles a request (that is encapsulated in a [[RequestContext]])
* and returns a [[scala.concurrent.Future]] of [[RouteResult]] with the response (or the rejection).
*
* Use the methods in [[RequestContext]] to create a [[RouteResult]].
* A handler MUST NOT return `null` as the result.
*/ */
trait Handler1[T1] { trait AsyncHandler extends akka.japi.function.Function[RequestContext, Future[RouteResult]] {
def handle(ctx: RequestContext, t1: T1): RouteResult override def apply(ctx: RequestContext): Future[RouteResult]
} }
/**
* A route handler with two additional arguments.
*/
trait Handler2[T1, T2] {
def handle(ctx: RequestContext, t1: T1, t2: T2): RouteResult
}
/**
* A route handler with three additional arguments.
*/
trait Handler3[T1, T2, T3] {
def handle(ctx: RequestContext, t1: T1, t2: T2, t3: T3): RouteResult
}
/**
* A route handler with four additional arguments.
*/
trait Handler4[T1, T2, T3, T4] {
def handle(ctx: RequestContext, t1: T1, t2: T2, t3: T3, t4: T4): RouteResult
}

View file

@ -4,17 +4,18 @@
package akka.http.javadsl.server.directives package akka.http.javadsl.server.directives
import scala.annotation.varargs import java.lang.reflect.{ Method, ParameterizedType }
import java.lang.reflect.{ ParameterizedType, Method }
import akka.http.javadsl.model.{ Uri, ContentType, StatusCode, HttpResponse } import akka.http.javadsl.model.{ Uri, ContentType, StatusCode, HttpResponse }
import akka.http.javadsl.server._
import akka.http.impl.server.RouteStructure._ import akka.http.impl.server.RouteStructure._
import akka.http.impl.server._ import akka.http.impl.server._
import akka.http.javadsl.model.{ ContentType, HttpResponse, StatusCode }
import akka.http.javadsl.server._
import scala.annotation.varargs
import scala.concurrent.Future import scala.concurrent.Future
abstract class BasicDirectives { abstract class BasicDirectives extends BasicDirectivesBase {
/** /**
* Tries the given route alternatives in sequence until the first one matches. * Tries the given route alternatives in sequence until the first one matches.
*/ */
@ -84,40 +85,6 @@ abstract class BasicDirectives {
def extractHere(extractions: RequestVal[_]*): Directive = def extractHere(extractions: RequestVal[_]*): Directive =
Directives.custom(Extract(extractions.map(_.asInstanceOf[StandaloneExtractionImpl[_ <: AnyRef]]))) Directives.custom(Extract(extractions.map(_.asInstanceOf[StandaloneExtractionImpl[_ <: AnyRef]])))
/**
* A route that handles the request with the given opaque handler. Specify a set of extractions
* that will be used in the handler to make sure they are available.
*/
@varargs
def handleWith[T1](handler: Handler, extractions: RequestVal[_]*): Route =
handle(extractions: _*)(handler.handle(_))
/**
* A route that handles the request given the value of a single [[RequestVal]].
*/
def handleWith[T1](e1: RequestVal[T1], handler: Handler1[T1]): Route =
handle(e1)(ctx handler.handle(ctx, e1.get(ctx)))
/**
* A route that handles the request given the values of the given [[RequestVal]]s.
*/
def handleWith[T1, T2](e1: RequestVal[T1], e2: RequestVal[T2], handler: Handler2[T1, T2]): Route =
handle(e1, e2)(ctx handler.handle(ctx, e1.get(ctx), e2.get(ctx)))
/**
* A route that handles the request given the values of the given [[RequestVal]]s.
*/
def handleWith[T1, T2, T3](
e1: RequestVal[T1], e2: RequestVal[T2], e3: RequestVal[T3], handler: Handler3[T1, T2, T3]): Route =
handle(e1, e2, e3)(ctx handler.handle(ctx, e1.get(ctx), e2.get(ctx), e3.get(ctx)))
/**
* A route that handles the request given the values of the given [[RequestVal]]s.
*/
def handleWith[T1, T2, T3, T4](
e1: RequestVal[T1], e2: RequestVal[T2], e3: RequestVal[T3], e4: RequestVal[T4], handler: Handler4[T1, T2, T3, T4]): Route =
handle(e1, e2, e3, e4)(ctx handler.handle(ctx, e1.get(ctx), e2.get(ctx), e3.get(ctx), e4.get(ctx)))
private[http] def handle(extractions: RequestVal[_]*)(f: RequestContext RouteResult): Route = { private[http] def handle(extractions: RequestVal[_]*)(f: RequestContext RouteResult): Route = {
val route = val route =
new OpaqueRoute() { new OpaqueRoute() {
@ -137,8 +104,8 @@ abstract class BasicDirectives {
* public static RouteResult methodName(RequestContext ctx, T1 t1, T2 t2, ...) * public static RouteResult methodName(RequestContext ctx, T1 t1, T2 t2, ...)
*/ */
@varargs @varargs
def handleWith(instance: AnyRef, methodName: String, extractions: RequestVal[_]*): Route = def handleReflectively(instance: AnyRef, methodName: String, extractions: RequestVal[_]*): Route =
handleWith(instance.getClass, instance, methodName, extractions: _*) handleReflectively(instance.getClass, instance, methodName, extractions: _*)
/** /**
* Handles the route by reflectively calling the static method specified by `clazz`, and `methodName`. * Handles the route by reflectively calling the static method specified by `clazz`, and `methodName`.
@ -149,8 +116,8 @@ abstract class BasicDirectives {
* public static RouteResult methodName(RequestContext ctx, T1 t1, T2 t2, ...) * public static RouteResult methodName(RequestContext ctx, T1 t1, T2 t2, ...)
*/ */
@varargs @varargs
def handleWith(clazz: Class[_], methodName: String, extractions: RequestVal[_]*): Route = def handleReflectively(clazz: Class[_], methodName: String, extractions: RequestVal[_]*): Route =
handleWith(clazz, null, methodName, extractions: _*) handleReflectively(clazz, null, methodName, extractions: _*)
/** /**
* Handles the route by calling the method specified by `clazz`, `instance`, and `methodName`. Additionally, the value * Handles the route by calling the method specified by `clazz`, `instance`, and `methodName`. Additionally, the value
@ -161,7 +128,7 @@ abstract class BasicDirectives {
* public static RouteResult methodName(RequestContext ctx, T1 t1, T2 t2, ...) * public static RouteResult methodName(RequestContext ctx, T1 t1, T2 t2, ...)
*/ */
@varargs @varargs
def handleWith(clazz: Class[_], instance: AnyRef, methodName: String, extractions: RequestVal[_]*): Route = { def handleReflectively(clazz: Class[_], instance: AnyRef, methodName: String, extractions: RequestVal[_]*): Route = {
def chooseOverload(methods: Seq[Method]): (RequestContext, Seq[Any]) RouteResult = { def chooseOverload(methods: Seq[Method]): (RequestContext, Seq[Any]) RouteResult = {
val extractionTypes = extractions.map(_.resultClass).toList val extractionTypes = extractions.map(_.resultClass).toList
val RequestContextClass = classOf[RequestContext] val RequestContextClass = classOf[RequestContext]