rest in an async world

50
Copyright © 2017, Oracle and/or its affiliates. All rights reserved. | David Delabassee @delabassee Oracle REST in an Async World Israel – July 2017

Upload: david-delabassee

Post on 22-Jan-2018

492 views

Category:

Software


4 download

TRANSCRIPT

Page 1: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

DavidDelabassee@delabasseeOracle

RESTinanAsyncWorldIsrael–July2017

Page 2: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 2

Page 3: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 3

Page 4: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

SafeHarborStatementThefollowingisintendedtooutlineourgeneralproductdirecPon.ItisintendedforinformaPonpurposesonly,andmaynotbeincorporatedintoanycontract.Itisnotacommitmenttodeliveranymaterial,code,orfuncPonality,andshouldnotberelieduponinmakingpurchasingdecisions.Thedevelopment,release,andPmingofanyfeaturesorfuncPonalitydescribedforOracle’sproductsremainsatthesolediscrePonofOracle.

4

Page 5: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Agenda

• REST&JAX-RS•  Synchronousvs.Asynchronous• Client-sidevs.Server-side

5

Page 6: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Client-sideREST

ConfidenPal–OracleInternal/Restricted/HighlyRestricted 6

Page 7: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS

•  JavaAPIforRESTfulWebServices– JAX-RS2.0–JSR339(*)– JAX-RS2.1–JSR370

•  StandardbasedRESTfulframework– Server-sideandclient-side– Jersey,JBossRESTEasy,Restlet,ApacheCXF,ApacheWink,IBMJAX-RS,…

•  JavaSEandJavaEE

7

Page 8: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 8

Clientclient=ClientBuilder.newClient();WebTargettarget=client.target("http://weath.er/api").queryParam("city","Paris”);Forecastforecast=target.request().get(Forecast.class);…client.close();

JAX-RSClientAPI

Page 9: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

• Client– Clientsidecontainer– Customizable&tunable• E.g.executorService()(newinJAX-RS2.1!)

• WebTarget– TargetremoteURI– Buildfromaclient– path()+resolveTemplates(),queryParam(),matrixParam()

javax.ws.rs.client.Clientinterface

9

Page 10: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

• RequestinvocaPonbuilder– BuildfromaWebTarget– acceptXXX(),cookie(),header(),cacheControl()…– HTTPmethods

javax.ws.rs.client.Clientinterface

10

Page 11: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

•  FluentAPI– ClientBuilderèClientèWebTargetèRequestbuildingèResponse

javax.ws.rs.client.Clientinterface

11

List<Forecast>forecast=ClientBuilder.newClient().target("http://weath.er/cities").request().accept("application/json").header("Foo","bar").get(newGenericType<List<Forecast>>(){});

Page 12: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

•  Synchronousinvoker

• Asynchronousinvoker

12

Stringcity=client.target("http://locati.on/api").queryParam("city","Paris").request().get(String.class);

Future<String>fCity=client.target("http://locati.on/api").queryParam("city","Paris").request().async().get(String.class);

Page 13: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPIAsynchronousinvoca.on

13

Future<String>fCity=client.target("http://locati.on/api")…

.request().async().get(String.class);Stringcity=future.get();

Page 14: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPIAsynchronousinvoca.on

14

Future<String>fCity=client.target("http://locati.on/api")…

.request().async().get(String.class);

try{

Stringcity=future.get(4,TimeUnit.SECONDS);

}catch(TimeoutExceptiontimeout){…}

Page 15: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPIAsynchronousinvoca.on

15

Future<String>future=client.target("http://locati.on/api")…

.request().async().get(String.class);

while(!future.isDone()){//responsehasn'tbeenreceivedyet…}

Stringcity=f.get();…

//SetClientProperties.CONNECT_TIMEOUT&READ_TIMEOUT

Page 16: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

•  InvocaPonCallbackInterface– javax.ws.rs.client.InvocaPonCallback<RESPONSE>

• ContainerwillreceiveasynchronousprocessingeventsfromaninvocaPon– completed(RESPONSEresponse)– failed(Throwablethrowable)

16

Asynchronousinvoca.on

Page 17: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

17

Invoca.onCallback…WebTargetmyResource=client.target("http://examp.le/api/read");Future<Customer>future=myResource.request(MediaType.TEXT_PLAIN).async().get(newInvocationCallback<Customer>(){

@Overridepublicvoidcompleted(Customercustomer){//dosomethingwiththegivencustomer}

@Overridepublicvoidfailed(Throwablethrowable){//Oops!}

});

Page 18: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 18

TheTravelService

Page 19: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

TheTravelService-Synchronous• Customerdetails:150ms• RecommendeddesPnaPons:250ms• PricecalculaPonforacustomeranddesPnaPon:170ms(each)• WeatherforecastforadesPnaPon:330ms(each)

19

5400ms

Page 20: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

TheTravelService-Asynchronous

20

730ms

Page 21: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 21

TheTravelService

Page 22: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 22

TheTravelServicedestination.path("recommended").request().header("Rx-User","Async").async().get(newInvocationCallback<List<Destination>>(){@Overridepublicvoidcompleted(finalList<Destination>recommended){finalCountDownLatchinnerLatch=newCountDownLatch(recommended.size());finalMap<String,Forecast>forecasts=Collections.synchronizedMap(newHashMap<>());for(finalDestinationdest:recommended){forecast.resolveTemplate("dest",dest.getDestination()).request().async().get(newInvocationCallback<Forecast>(){@Overridepublicvoidcompleted(finalForecastforecast){forecasts.put(dest.getDestination(),forecast);innerLatch.countDown();}

Page 23: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 23

JAX-RS2.0

@Overridepublicvoidfailed(finalThrowablethrowable){innerLatch.countDown();}});}

try{if(!innerLatch.await(10,TimeUnit.SECONDS)){//timeout}}catch(finalInterruptedExceptione){//Ooops,interrupted!}

//Continuewithprocessing…}

@Overridepublicvoidfailed(finalThrowablethrowable){//Recommendationerror}});

Page 24: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 24

JAX-RS2.1

//JAX-RS2.1CompletionStage<Response>csResponse=ClientBuilder.newClient().target("http://example.com/api").request().rx().get();

Future<Response>fResponse=ClientBuilder.newClient().target("http://example.com/api").request().async().get();

Responseresponse=ClientBuilder.newClient().target("http://example.com/api").request().get();

Page 25: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

ComplePonStageinterface

•  “AstageofapossiblyasynchronouscomputaPon,thatperformsanac.onorcomputesavalue”•  “Ontermina.onastagemayinturntriggerotherdependentstages.”•  StageexecuPontriggeredbycomplePonof– “then”-asinglestage– “combine”-bothoftwostages– “either”-eitheroftwostages

25

Page 26: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

ComplePonStageinterface

• ComputaPontakesanargumentandreturnsaresult?– “apply”–Func.ontakeresultofthepreviousstageasargument,returnaresult– “accept”–Consumeronlytakeanargument– “run”–Runnablenoargumentanddoesn’treturnaresult

• HowtheexecuPonofthecomputaPonisarranged?– Doesn'tendwith“async”–executeusingthestage’sdefaultexecuPonfacility– Endwith“async”-usethestage’sdefaultasynchronousexecuPonfacility

• …

26

hsps://docs.oracle.com/javase/8/docs/api/java/uPl/concurrent/ComplePonStage.html

Page 27: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 27

JAX-RS2.1

CompletionStage<Number>csPrice=client.target("price/{destination}").resolveTemplate("destination","Paris").request().rx().get(Number.class);CompletionStage<String>csForecast=client.target("forecast/{destination}").resolveTemplate("destination","Paris").request().rx().get(String.class);csPrice.thenCombine(csForecast,(price,forecast)->book(price,forecast));

Page 28: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 28

DemoTheTravelService

hsps://github.com/jersey/jersey/tree/master/examples/rx-client-webapp

Page 29: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RSClientAPI

• RESTClientSidecontainer•  Synchronousinvoker– Defaultinvoker-javax.ws.rs.client.SyncInvoker

• Asynchronousinvokers– async()invoker-javax.ws.rs.client.AsyncInvoker• Mightblock->InvocaPonCallback

– ReacPverx()invoker-javax.ws.rs.client.RxInvoker•  NewinJAX-RS2.1!•  ComplePonStageAPI+otherReacPvelibrary(opt.)

29

Summary

Page 30: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Server-sideREST

ConfidenPal–OracleInternal/Restricted/HighlyRestricted 30

Page 31: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 31

Server-side@Path("/Item")publicclassItemResource{@Path("{id}")@Produces(MediaType.APPLICATION_XML)publicItemResourcegetItemResource(@PathParam("id")Stringid){returnItemResource.getInstance(id);}@POST@Consumes(MediaType.APPLICATION_XML)@Produces(MediaType.APPLICATION_XML)publicResponsecreateItem(@QueryParam("name")Stringname){//...returnResponse.status(Status.OK).entity(…).build();}}

Page 32: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.| 32

Server-sideAsync@Path("/Async")publicclassItemResource{

@GETpublicvoidheavyResource(@SuspendedAsyncResponsear){

mes.execute(newRunnable(){@Overridepublicvoidrun(){try{//longrunningcomputation...ar.resume(Response.ok(...).build());}catch(InterruptedExceptionex){//Ooops!}}});...

Page 33: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Server-sideAsync

• Providesmeansforasynchronousserversideresponseprocessing– Injectablevia@SuspendedOR– ResourcemethodcanreturnaComplePonStage<T>instance(newinJAX-RS2.1!)

• Boundtotherequest– Suspend– Resume– Configure– Cancel

33

AsyncResponseinterface

Page 34: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Server-sideAsync

34

Client Server

@Suspended

AsyncResponse.resume(…)

LongrunningoperaPon…

Request

Response

Page 35: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

LongrunningRESToperaPons

è POST...longrunningoperaPon...ç ‘201Created’+LocaPon

35

è POSTç ‘202Accepted’+TempLocaPon

è GETTempLocaPonç ‘200OK’(+ETA)…è GETTempLocaPonç ‘303SeeOther’+FinalLocaPon

Page 36: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Server-sentEvents

• Persistent,one-waycommunicaPonchannel•  Textprotocol,specialmediatype"text/event-stream"•  ServercansendmulPplemessages(events)toaclient• Cancontainid,name,commentretryinterval•  Supportedinallmodernbrowsers

36

Page 37: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS2.1

37

SSE

•  SseEvent– ID,Name,Comment,…

• OutboundSseEvent– Server-siderepresentaPonofaServer-sentevent– OutboundSseEvent.Builder()

•  InboundSseEvent– Client-siderepresentaPonofaServer-sentevent

Page 38: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS2.1

38

SSE–Serverside

•  SseEventSink– OutboundServer-SentEventsstream– SseBroadcaster

@GET@Path("sse")@Produces(MediaType.SERVER_SENT_EVENTS)publicvoideventStream(@ContextSseEventSinkeventSink,@ContextSSEsse){...eventSink.send(sse.newEvent("anevent"));eventSink.send(sse.newEvent("anotherevent"));...eventSink.close();}

Page 39: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS2.1

39

SSE–Clientside

•  SseEventSource– ClientforprocessingincomingServer-SentEvents

SseEventSourcees=SseEventSource.target(SSE_target).reconnectingEvery(5,SECONDS).build();es.register(System.out::println);//InboundSseEventconsumeres.register(...);//Throwableconsumeres.open();...es.close();

Page 40: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Wrap-up

ConfidenPal–OracleInternal/Restricted/HighlyRestricted 40

Page 41: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS

•  JavaAPIforRESTfulWebServices– JAX-RS2.0–JSR339(*)– JAX-RS2.1–JSR370

•  StandardbasedRESTfulframework– Server-sideandclient-side– JavaSEandJavaEE– Jersey,JBossRESTEasy,Restlet,ApacheCXF,ApacheWink,IBMJAX-RS,…

41

Page 42: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS–Client-side

• RESTClientSidecontainer•  Invokers– Synchronous•  javax.ws.rs.client.SyncInvoker•  Default

– Asynchronous•  javax.ws.rs.client.AsyncInvoker

– ReacPve•  NewinJAX-RS2.1!•  javax.ws.rs.client.AsyncInvoker

42

Page 43: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS–Client-side

43

Sync Async RXPerformanceandscalability ✗✗ ✔ ✔Easytodevelopandmaintain ✔ ✗ ✔

…complexworkflow ✗ ✗ ✔…errorhandling ✗ ✗ ✔

LeveragenewJavaSEfeature ✗ ✗ ✔

Page 44: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS–ReacPveClientAPI•  JavaSE8ComplePonStage– Asmandatedbythespec.

•  Jersey– RxJava-rx.Observable– RxJava2-io.reacPvex.Flowable– Guava-ListenableFuture

44

Page 45: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JAX-RS–Server-side

• AsyncResponse– ResumeexecuPononadifferentthread– @Suspended– ResourcemethodreturningaComplePonStage<T>instance

•  LongrunningoperaPonpasern•  Server-sentEvents

45

Page 46: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JavaEE8

46

BeanValida.on

CDI2.0

JSON-B1.0

Security1.0

BeanValida.on2.0

JSF2.3

Servlet4.0

JSON-P1.1

JAX-RS2.1 ReacPveclientAPI,Server-sentevents,…

HTTP/2,serverpush,…

Java<->JSONbinding

UpdatestoJSONstandards,JSONCollectors,…

Asyncevent,eventpriority,SEsupport,…

EmbraceJavaSE8,newconstraints

ImprovedCDI,WebSocket,SE8integraPon,…

StandardizedIdenPtyStore,AuthenPcaPon,SecurityContext

Page 47: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

JavaEE8• Workinprogress– FinalRelease-Summer2017(plan)

• OpenSourceReferenceImplementaPons– hsps://github.com/jersey

– hsps://github.com/javaee

•  Staytuned…– hsps://blogs.oracle.com/theaquarium/

47

Page 48: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

תודה רבה.

ConfidenPal–OracleInternal/Restricted/HighlyRestricted 48

Page 49: REST in an Async World

Copyright©2017,Oracleand/oritsaffiliates.Allrightsreserved.|

Resources

•  JAX-RSspecificaPon– hsps://github.com/jax-rs/api

•  Jersey–AsynchronousServicesandClients– hsps://jersey.java.net/documentaPon/latest/async.html#d0e8611– hsps://github.com/jersey/jersey/tree/master/examples/rx-client-webapp

• ComplePonStage– hsps://docs.oracle.com/javase/8/docs/api/java/uPl/concurrent/ComplePonStage.html

•  JavaEETutorial– hsps://docs.oracle.com/javaee/7/tutorial/

49

Page 50: REST in an Async World