4
4
5
5
package akka .http .javadsl .server .directives
6
6
7
- import java .util .concurrent .CompletionStage
7
+ import java .util .concurrent .{ CompletionException , CompletionStage }
8
8
9
9
import akka .dispatch .ExecutionContexts
10
10
import akka .http .javadsl .marshalling .Marshaller
@@ -20,7 +20,7 @@ import akka.http.javadsl.model.RequestEntity
20
20
import akka .http .javadsl .model .ResponseEntity
21
21
import akka .http .javadsl .model .StatusCode
22
22
import akka .http .javadsl .model .Uri
23
- import akka .http .javadsl .server .{ RoutingJavaMapping , Rejection , Route }
23
+ import akka .http .javadsl .server .{ Rejection , Route , RoutingJavaMapping }
24
24
import akka .http .scaladsl
25
25
import akka .http .scaladsl .marshalling .Marshaller ._
26
26
import akka .http .scaladsl .marshalling .ToResponseMarshallable
@@ -239,47 +239,56 @@ abstract class RouteDirectives extends RespondWithDirectives {
239
239
*/
240
240
@ CorrespondsTo (" complete" )
241
241
def completeWithFuture (value : CompletionStage [HttpResponse ]) = RouteAdapter {
242
- D .complete(value.asScala.fast.map(_.asScala))
242
+ D .complete(value.asScala.fast.map(_.asScala).recover(unwrapCompletionException) )
243
243
}
244
244
245
245
/**
246
246
* Completes the request by marshalling the given future value into an http response.
247
247
*/
248
248
@ CorrespondsTo (" complete" )
249
249
def completeOKWithFuture (value : CompletionStage [RequestEntity ]) = RouteAdapter {
250
- D .complete(value.asScala.fast.map(_.asScala))
250
+ D .complete(value.asScala.fast.map(_.asScala).recover(unwrapCompletionException) )
251
251
}
252
252
253
253
/**
254
254
* Completes the request by marshalling the given future value into an http response.
255
255
*/
256
256
@ CorrespondsTo (" complete" )
257
257
def completeOKWithFutureString (value : CompletionStage [String ]) = RouteAdapter {
258
- D .complete(value.asScala)
258
+ D .complete(value.asScala.recover(unwrapCompletionException) )
259
259
}
260
260
261
261
/**
262
262
* Completes the request using the given future status code.
263
263
*/
264
264
@ CorrespondsTo (" complete" )
265
265
def completeWithFutureStatus (status : CompletionStage [StatusCode ]): Route = RouteAdapter {
266
- D .complete(status.asScala.fast.map(_.asScala))
266
+ D .complete(status.asScala.fast.map(_.asScala).recover(unwrapCompletionException) )
267
267
}
268
268
269
269
/**
270
270
* Completes the request with an `OK` status code by marshalling the given value into an http response.
271
271
*/
272
272
@ CorrespondsTo (" complete" )
273
273
def completeOKWithFuture [T ](value : CompletionStage [T ], marshaller : Marshaller [T , RequestEntity ]) = RouteAdapter {
274
- D .complete(value.asScala.fast.map(v ⇒ ToResponseMarshallable (v)(fromToEntityMarshaller()(marshaller))))
274
+ D .complete(value.asScala.fast.map(v ⇒ ToResponseMarshallable (v)(fromToEntityMarshaller()(marshaller))).recover(unwrapCompletionException) )
275
275
}
276
276
277
277
/**
278
278
* Completes the request by marshalling the given value into an http response.
279
279
*/
280
280
@ CorrespondsTo (" complete" )
281
281
def completeWithFuture [T ](value : CompletionStage [T ], marshaller : Marshaller [T , HttpResponse ]) = RouteAdapter {
282
- D .complete(value.asScala.fast.map(v ⇒ ToResponseMarshallable (v)(marshaller)))
282
+ D .complete(value.asScala.fast.map(v ⇒ ToResponseMarshallable (v)(marshaller)).recover(unwrapCompletionException))
283
+ }
284
+
285
+ // TODO: This might need to be raised as an issue to scala-java8-compat instead.
286
+ // Right now, having this in Java:
287
+ // CompletableFuture.supplyAsync(() -> { throw new IllegalArgumentException("always failing"); })
288
+ // will in fact fail the future with CompletionException.
289
+ private def unwrapCompletionException [T ]: PartialFunction [Throwable , T ] = {
290
+ case x : CompletionException if x.getCause ne null ⇒
291
+ throw x.getCause
283
292
}
284
293
285
294
}
0 commit comments