piątek, 3 października 2014

PlayFramework warsztaty - REST - część 2

To jest dalszy ciąg lekcji o Jsonie i webserwisach -- A tutaj jest część 1

Pomimo iż materiału wydawało się być dużo to jednak udało się zrobić całość w 2,5 godziny (Między innymi dlatego, ze już nie chce mi się z pizzą kombinować i nie ma przerwy - ale zawsze ostrzegam - ludzie weźcie kanapki! (Albo odżywki - przyp. red.)).

Prąd i sala się same nie opłaciły to ten tego :
A poniżej wszyscy bez żadnego zewnętrznego przymuszenia promieniują wewnętrznym szczęściem i radością :

A tutaj są linki do poprzednich części :

Wywołanie

Do tego ćwiczenia zostawiamy włączoną aplikacyjkę z poprzedniej części - to będzie apiserwer , zaś to co powstanie tutaj to taki apiclient.

By obydwa serwery się nie pogryzły ten drugi uruchamiamy na innym porcie w ten oto wygodny sposób :

~run 8000

I wołamy :
def webserwis = Action.async {
    import scala.concurrent.ExecutionContext.Implicits.global
    val futureResult=WS.url("http://localhost:9000/list").get
    futureResult.map{response=>
     Ok("otrzymalem : "+response.json)
    }
  }

I to w zasadzie tyle w wariancie podstawowym - powinno śmigać. Trzeba uczestnikom wytłumaczyć tutaj co to jest to "async" i nadmienić, że z wywołania WS dostajemy

Future[Response]
. O samych Future będzie więcej za chwilę.

No i mogą pojawić się pytania o to co to jest i skąd się wziął ExecutionContext. W tym miejscu może się przydać strona z dokumentacji Playa o pulach wątków.

Wysyłanie posta z ciałem

Wygląda tak :
def dodajMeal = Action.async {
    val result = WS.url("http://localhost:9000/add").post(Json.obj("name" -> "kurczak", "calories" -> 1000))
    result.map(r => Ok("dostałem : " + r.body))
  }

Future poligon

Kiedy już mamy ogólne pojęcie o używaniu klienta Webserwisów przyjrzyjmy się bliżej temu co ono zwraca - czyli Future. Tutaj można wspomnieć jak Future jako abstrakcja ratuje nas od masy zagnieżdżonych callbacków.

Jedna ważna rzecz jeśli chodzi o zabawę Future - tutaj nie da się używać worksheet bo plik jest cały czas odświeżany i procek się pali dlatego normalnie w mainie napiszemy kod.

Najpierw zasymulujmy synchroniczne wywołanie serwisu z zamuleniem jednej sekundy

object Poligon {

  def main(args: Array[String]) {
    val result = servis1
    println("start")
    println(result)
    println("end")
  }

  def servis1 = {
    Thread.sleep(1000)
    10
  }
}

I wynik :
start
10
end

Z future


  def main(args: Array[String]) {
    val executorService = Executors.newCachedThreadPool()
    implicit val executionContext = ExecutionContext.fromExecutorService(executorService)

    val result = Future{servis1}
    println("start")
    result.onSuccess{case result=>println(result)}
    println("end")
  }
Wywołanie serwisu nastąpiło asynchronicznie więc rezultat będzie na samym końcu.
start
end
10
No i aby pokazać jakie patenty są możliwe to dajmy na to zmodyfikujemy sobie rezultat
val result = Future { servis1 }.map(_+3)
I mamy teraz :
start
end
13

dwa servisy

O a tutaj proszę jak ładnie komponujemy dwa asynchroniczne wywołania serwisów
object FuturePoligon {
  def servis1() = {
    Thread.sleep(1000)
    10
  }
  
  def servis2(arg:Int) = {
    Thread.sleep(1000)
    arg+7
  }
}

val result = Future { servis1 }.map(result1=>servis2(result1))
    println("start")
    result.onSuccess{case result=>println(result)}
    println("end")
start
end
17

Który future pierwszy

object FuturePoligon {
  def servis1() = {
    Thread.sleep(1000)
    10
  }
  
  def servis2(arg:Int) = {
    Thread.sleep(800)
    arg+7
  }
}

    val future1 = Future { servis1 }
    val future2 = Future { servis2(4) }
    val completedFuture=Future.firstCompletedOf(Seq(future1,future2))
    println("start")
    completedFuture.onSuccess{case result=>println(result)}
    println("end")

start
end
11

Obsluga faili

import scala.util.{Failure,Success}

 val futureFail = Future {
      throw new Exception("się zjebało")
    }

    futureFail.onComplete {
      case Success(value) => println(value)
      case Failure(e)     => println(e)
    }

    futureFail.onFailure {
      case e => println(e)
    }
wypisuje :
java.lang.Exception: się zjebało
java.lang.Exception: się zjebało

Zaginione strony

Ponieważ te ćwiczenia nie powstają za jednym razem ale ciągle wracam i coś poprawiam także czasem zostawiam sobie notatki na przyszłość. W tym miejscu zapisałem sobie "ćwiczenia na typach i zdjęcie z goblinsów" - o co mogło mi chodzić? Pojęcia nie mam. Ale obrazek będzie :

Co dalej?

Na pewno ciekawe będzie poćwiczenie użycia Play i Akka razem ale wcześniej - ponieważ jest zainteresowanie takimi ogólnymi warsztatami o Scali to coś zrobimy też w tym kierunku :

Brak komentarzy:

Prześlij komentarz