Merge pull request #17988 from ktoso/wip-javadsl-handleWith-ktoso
!htp #17965 more consistent and 22-ified javadsl handleWith
This commit is contained in:
commit
77d3e693c5
27 changed files with 339 additions and 272 deletions
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
|
||||
package docs.http.javadsl;
|
||||
|
||||
import akka.http.javadsl.model.HttpRequest;
|
||||
import akka.http.javadsl.server.*;
|
||||
import akka.http.javadsl.server.values.Parameters;
|
||||
import akka.http.javadsl.server.values.PathMatchers;
|
||||
import akka.http.javadsl.testkit.JUnitRouteTest;
|
||||
import akka.http.javadsl.testkit.TestRoute;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HandlerExampleSpec extends JUnitRouteTest {
|
||||
@Test
|
||||
public void testSimpleHandler() {
|
||||
//#simple-handler-example-full
|
||||
class TestHandler extends akka.http.javadsl.server.AllDirectives {
|
||||
//#simple-handler
|
||||
Handler handler = new Handler() {
|
||||
@Override
|
||||
public RouteResult handle(RequestContext ctx) {
|
||||
return ctx.complete("This was a " + ctx.request().method().value() +
|
||||
" request to "+ctx.request().getUri());
|
||||
}
|
||||
};
|
||||
//#simple-handler
|
||||
|
||||
Route createRoute() {
|
||||
return route(
|
||||
get(
|
||||
handleWith(handler)
|
||||
),
|
||||
post(
|
||||
path("abc").route(
|
||||
handleWith(handler)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// actual testing code
|
||||
TestRoute r = testRoute(new TestHandler().createRoute());
|
||||
r.run(HttpRequest.GET("/test"))
|
||||
.assertStatusCode(200)
|
||||
.assertEntity("This was a GET request to /test");
|
||||
|
||||
r.run(HttpRequest.POST("/test"))
|
||||
.assertStatusCode(404);
|
||||
|
||||
r.run(HttpRequest.POST("/abc"))
|
||||
.assertStatusCode(200)
|
||||
.assertEntity("This was a POST request to /abc");
|
||||
//#simple-handler-example-full
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
RequestVal<Integer> xSegment = PathMatchers.intValue();
|
||||
RequestVal<Integer> ySegment = PathMatchers.intValue();
|
||||
|
||||
//#handler2
|
||||
Handler2<Integer, Integer> multiply =
|
||||
new Handler2<Integer, Integer>() {
|
||||
@Override
|
||||
public RouteResult handle(RequestContext ctx, Integer x, Integer y) {
|
||||
int result = x * y;
|
||||
return ctx.complete("x * y = " + result);
|
||||
}
|
||||
};
|
||||
|
||||
Route multiplyXAndYParam = handleWith(xParam, yParam, multiply);
|
||||
//#handler2
|
||||
|
||||
Route createRoute() {
|
||||
return route(
|
||||
get(
|
||||
pathPrefix("calculator").route(
|
||||
path("multiply").route(
|
||||
multiplyXAndYParam
|
||||
),
|
||||
path("path-multiply", xSegment, ySegment).route(
|
||||
handleWith(xSegment, ySegment, multiply)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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/path-multiply/23/5"))
|
||||
.assertStatusCode(200)
|
||||
.assertEntity("x * y = 115");
|
||||
//#handler2-example-full
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculatorReflective() {
|
||||
//#reflective-example-full
|
||||
class TestHandler extends akka.http.javadsl.server.AllDirectives {
|
||||
RequestVal<Integer> xParam = Parameters.intValue("x");
|
||||
RequestVal<Integer> yParam = Parameters.intValue("y");
|
||||
|
||||
RequestVal<Integer> xSegment = PathMatchers.intValue();
|
||||
RequestVal<Integer> ySegment = PathMatchers.intValue();
|
||||
|
||||
|
||||
//#reflective
|
||||
public RouteResult multiply(RequestContext ctx, Integer x, Integer y) {
|
||||
int result = x * y;
|
||||
return ctx.complete("x * y = " + result);
|
||||
}
|
||||
|
||||
Route multiplyXAndYParam = handleWith(this, "multiply", xParam, yParam);
|
||||
//#reflective
|
||||
|
||||
Route createRoute() {
|
||||
return route(
|
||||
get(
|
||||
pathPrefix("calculator").route(
|
||||
path("multiply").route(
|
||||
multiplyXAndYParam
|
||||
),
|
||||
path("path-multiply", xSegment, ySegment).route(
|
||||
handleWith(this, "multiply", xSegment, ySegment)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 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/path-multiply/23/5"))
|
||||
.assertStatusCode(200)
|
||||
.assertEntity("x * y = 115");
|
||||
//#reflective-example-full
|
||||
}
|
||||
}
|
||||
|
|
@ -32,12 +32,12 @@ public class HighLevelServerExample extends HttpApp {
|
|||
public Route createRoute() {
|
||||
// This handler generates responses to `/hello?name=XXX` requests
|
||||
Route helloRoute =
|
||||
handleWith(name,
|
||||
handleWith1(name,
|
||||
// in Java 8 the following becomes simply
|
||||
// (ctx, name) -> ctx.complete("Hello " + name + "!")
|
||||
new Handler1<String>() {
|
||||
@Override
|
||||
public RouteResult handle(RequestContext ctx, String name) {
|
||||
public RouteResult apply(RequestContext ctx, String name) {
|
||||
return ctx.complete("Hello " + name + "!");
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import java.io.BufferedReader;
|
|||
import java.io.InputStreamReader;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class HttpServerExampleSpec {
|
||||
public class HttpServerExampleDocTest {
|
||||
public static void bindingExample() {
|
||||
//#binding-example
|
||||
ActorSystem system = ActorSystem.create();
|
||||
|
|
@ -44,7 +44,7 @@ public class PathDirectiveExampleTest extends JUnitRouteTest {
|
|||
Handler1<Integer> completeWithUserId =
|
||||
new Handler1<Integer>() {
|
||||
@Override
|
||||
public RouteResult handle(RequestContext ctx, Integer userId) {
|
||||
public RouteResult apply(RequestContext ctx, Integer userId) {
|
||||
return ctx.complete("Hello user " + userId);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ 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
|
||||
``BasicDirectives.handleWith`` overloads. They come in several forms:
|
||||
|
||||
* with a single ``Handler`` 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<?>``
|
||||
arguments
|
||||
* 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 ``Class<?>`` and/or instance and a method name String argument and a variable number of ``RequestVal<?>`` (may be 0)
|
||||
arguments
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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:
|
||||
|
||||
.. 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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
------------------
|
||||
|
||||
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
|
||||
--------------------------------
|
||||
|
||||
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:
|
||||
|
||||
.. includecode:: ../../code/docs/http/javadsl/HandlerExampleSpec.java
|
||||
.. includecode:: /../../akka-http-tests-java8/src/test/java/docs/http/javadsl/server/HandlerExampleDocTest.java
|
||||
:include: reflective
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
Deferring Result Creation
|
||||
|
|
|
|||
|
|
@ -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
|
||||
(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
|
||||
|
||||
While it'd be perfectly possible to define a complete REST API service purely by inspecting the incoming
|
||||
|
|
|
|||
|
|
@ -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`_
|
||||
extension:
|
||||
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleDocTest.java
|
||||
:include: binding-example
|
||||
|
||||
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:
|
||||
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleSpec.java
|
||||
.. includecode:: ../../code/docs/http/javadsl/HttpServerExampleDocTest.java
|
||||
:include: full-server-example
|
||||
|
||||
In this example, a request is handled by transforming the request stream with a function ``Function<HttpRequest, HttpResponse>``
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue