Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction of Jooby. DevIO2016

cm-komuro
October 08, 2016

Introduction of Jooby. DevIO2016

Developers IO 2016 in Fukuoka

cm-komuro

October 08, 2016
Tweet

More Decks by cm-komuro

Other Decks in Technology

Transcript

  1. ⡥$MBTTNFUIPE *OD ࣗݾ঺հ w খࣨܒ w ϞόΠϧΞϓϦαʔϏε෦όοΫΤϯυάϧʔϓ w ։ൃऀ 1-

    ࡳຈΦϑΟεϚωʔδϟ w ࡛ۄݝग़਎࡛ۄҭͪ
 Կނ͔ࠓ͸๺ւಓࡳຈࢢࡏॅ w ϞόΠϧΞϓϦ(ͷ஍ํΦϑΟε্ཱͪ͛෦ୂʢࣗশ w 5XJUUFS!DPNED 
  2. KPPCZͱ͸  w ࡞ऀ͸&EHBS&TQJOB !KLOBDL ͞Μ w +BWBωΠςΟϒ w .JDSP8FCΞϓϦέʔγϣϯ։ൃͷϑϨʔϜϫʔΫ

    w ར༻ՄೳͳϞδϡʔϧ͕ެࣜͰ݁ߏ༻ҙ͞ΕͯΔ w طଘͷ+BWBϥΠϒϥϦΛ࢖͍·ΘͤΔ w εςʔτϨεͳͷͰεέʔϧ͠΍͍͢ w /FUUZ +FUUZ VOEFSUPX ਖ਼֬ͳൃԻ͸ෆ໌ɾɾ
  3. ⡥$MBTTNFUIPE *OD +BWB/BUJWF w ಈ࡞࠷௿৚͕݅+BWBҎ্ w +BWBҎ্ NBWFOYҎ্ w ϥϜμࣜΛ࢖ͬͨهड़͕ެࣜͷελϯμʔυ

    w ίϯύΫτʹॻ͚Δ w ܕਪ࿦ͱϥϜμࣜͷԸܙʹ༩Γ·͠ΐ͏ w +BWBҎ߱ͷ+7.͕ಈ࡞ج൫ w IUUQPUOEOMEPSBDMFDPKQPOEFNBOEKBWBEBZ QEG$+BWB%BZQEG 
  4. ⡥$MBTTNFUIPE *OD 'BTU w ىಈ͕ૣ͍ w σϑΥϧτͷαʔόʔ͸/FUUZ w IUUQOFUUZJP w

    ͦͷଞαϙʔτ w +FUUZ IUUQXXXFDMJQTFPSHKFUUZ  w VOEFSUPX IUUQVOEFSUPXJP  w 5PNDBU͸ͳ͍  IUUQKPPCZPSHEPDTFSWFST
  5. ⡥$MBTTNFUIPE *OD $PEF w ίʔυ͕εοΩϦ ίϯύΫτʹ  public class App

    extends Jooby { Logger log = LoggerFactory.getLogger(App.class); { get("/", request -> "Hello jooby"); } public static void main(final String[] args) throws Throwable { run(App::new, args); } } ͜Ε͚ͩ
  6. ⡥$MBTTNFUIPE *OD $PNQBSF @Controller public class SimpleController { @RequestMapping("/simple") public

    @ResponseBody String simple() { return "Hello world!"; } }  { get("/simple", () -> "Hello World!"); } 4QSJOH.7$ +PPCZ ͪΐͬͱ൓ଇؾຯɾɾʁ
  7. ⡥$MBTTNFUIPE *OD ಛ௃ w SPVUFT΋ίʔυͰॻ͘ w 4JOBUSB΍FYQSFTTKT͔ΒΠϯεύΠΞ w εΫϦϓτͬΆ͘ॻ͚ΔߏจΛ༻ҙ w

    جຊ͸ϥϜμࣜ w 'VODUJPOབྷΈͷγϯλοΫεγϡΨʔʹΑͬͯɺѹ౗తʹه ड़ྔ͕গͳ͍ɻϥϜμࣜͱܕਪ࿦͸ڧྗɻ w ܕਪ࿦ʹΑΓهड़͕লུ͞ΕΔ͕ɺ*%&ͷྗʹཔΔͱಛʹࠔΒ ͳ͍ɻ w ΠϯελϯεΠχγϟϥΠβ w ίϯετϥΫλ಺Ͱهड़͢ΔΑΓݟ௨͕͠ྑ͍ ڧ੍Ͱ͸ͳ͍ 
  8. ⡥$MBTTNFUIPE *OD Ϟδϡʔϧͱ͸ʁ w +PPCZͷಛ௃ͷҰͭɻऔΓࠐΈɺऔΓ֎ָ͕͠ w +PPCZʹ͓͍ͯͷϞδϡʔϧͱ͸ɺ+PPCZʹ૊Έࠐ Ή͜ͱͷͰ͖Δίϯϙʔωϯτʢ࣮ࡍʹ͸ΠϯλϑΣʔ ε 

    w +PPCZ.PEVMFͱ͍͏ΠϯλϑΣʔεΛ࣮૷ɺϒ Ϧοδͯ͋͛͠Ε͹طଘͷϥΠϒϥϦΛऔΓࠐΉͷ͸ ͱͯ΋؆୯ w ͪΐͬͱ಄ͷྑ͍ϑΝΫτϦͷΑ͏ͳΠϝʔδ 
  9. ⡥$MBTTNFUIPE *OD ϞδϡʔϧͷಡΈࠐΈ ΞϓϦέʔγϣϯ΁؆୯ʹ૊ΈࠐΊΔ  public class App extends Jooby

    { { use(new MyModule()); } { get("/", req -> { MyService service = req.require(MyService.class); return service.doSomething(); }); } } ϞδϡʔϧΛϩʔυ ϞδϡʔϧͰϩʔυ͞ΕͨΫ ϥεΛΠϯελϯεԽ Ϟδϡʔϧ͕ϩʔυ͞Εͯͳ͍ ͱ/VMM1PJOUFS&YDFQUJPO ϞδϡʔϧͰ४උ͞Εͨ αʔϏεΫϥε
  10. ⡥$MBTTNFUIPE *OD .PEVMFͷ४උ  <dependency> <groupId>org.jooby</groupId> <artifactId>jooby-aws</artifactId> <version>1.0.0.CR7</version> </dependency> QPNYNMʹґଘ௥Ճ

    aws.accessKey = ACCCESSSSSSSSSKEYYYYYYYYYYYYYYYY aws.secretKey = seeeeeCreeeeeeetKeeeyyyyyyyyyyy BQQMJDBUJPODPOGʹઃఆ௥Ճ IUUQTHJUIVCDPNKPPCZQSPKFDUKPPCZUSFFNBTUFSKPPCZBXT
  11. ⡥$MBTTNFUIPE *OD "84.PEVMFΛϩʔυ  public class App extends Jooby {

    { use(new Aws()
 .with(creds -> new AmazonS3Client(creds))
 ); } } Ϟδϡʔϧ௥Ճ "NB[PO4Λ࢖͏৔߹ public class App extends Jooby { { get("/", req -> { AmazonS3Client s3Client = req.require(AmazonS3Client.class); log.info("get s3Client. {}”, s3Client); return “AmazonS3Client"; }); } } ඞཁͳΠϯελϯεऔಘ
  12. ⡥$MBTTNFUIPE *OD "84.PEVMFͷதΛ೷͍ͯΈΔ  private Builder<BiFunction<AWSCredentialsProvider, Config, AmazonWebServiceClient>> callbacks =

    ImmutableList.builder(); public Aws with( final BiFunction<AWSCredentialsProvider, Config, AmazonWebServiceClient> callback) { requireNonNull(callback, "Callback is required."); callbacks.add(callback); return this; } public Aws with(final Function<AWSCredentialsProvider, AmazonWebServiceClient> callback) { return with((creds, conf) -> callback.apply(creds)); } "XTϞδϡʔϧ͸XJUIϝιουΛ࢖ͬͯ$BMMCBDLΛొ࿥ ͠·͢ɻSFUVSOUIJTͰࣗ਎Λฦ٫͍ͯ͠ΔͨΊCVJMEFS ͱͯ͠ར༻Ͱ͖·͢ɻ
  13. ⡥$MBTTNFUIPE *OD ॳظԽॲཧ  @Override public void configure(final Env env,

    final Config config, final Binder binder) { callbacks.build().forEach(it -> { ConfigCredentialsProvider creds = new ConfigCredentialsProvider(config); AmazonWebServiceClient service = it.apply(creds, config); creds.service(service.getServiceName()); Class serviceType = service.getClass(); Class[] interfaces = serviceType.getInterfaces(); if (interfaces.length > 0) { // pick first binder.bind(interfaces[0]).toInstance(service); } binder.bind(serviceType).toInstance(service); env.onStop(new AwsShutdownSupport(service)); after(env, binder, config, service); }); } DPOpHVSF͸.PEVMF͕ϩʔυ͞ΕͨࡍʹॳظԽॲཧΛ࣮ߦ͠·͢ɻ ඞཁͳ$MJFOUͷΫϥεΛDBMMCBDLT͔ΒऔΓग़͠ɺ$SFEFOUJBMͱڞʹॳ ظԽͭͭ͠ɺΫϥεʹରͯ͠ͷΠϯελϯεΛొ࿥͍͖ͯ͠·͢ɻ
  14. ⡥$MBTTNFUIPE *OD ϞδϡʔϧϥΠϑαΠΫϧ  .PEVMF Πϯελϯεੜ੒ ΞϓϦέʔγϣϯ ॳظԽ ΞϓϦέʔγϣϯ ऴྃ

    .PEVMF ऴྃ .PEVMFDPOpHVSF &OWPO4UBSU &OWPO4UPQ .PEVMFͰඞཁͳॳظઃఆͳͲ͸DPOpHVSFͰ࣮ߦɻ PO4UBSU PO4UPQͷఆٛ΋ͪ͜ΒͰߦ͓͚ͬͯ͹ྑ͍ɻ
  15. ⡥$MBTTNFUIPE *OD .PEVMFͷ४උ  <dependency> <groupId>org.jooby</groupId> <artifactId>jooby-jackson</artifactId> <version>1.0.0.CR7</version> </dependency> QPNYNMʹґଘ௥Ճ

    IUUQTHJUIVCDPNKPPCZQSPKFDUKPPCZUSFFNBTUFSKPPCZKBDLTPO public class App extends Jooby { { use(new Jackson()); } } Ϟδϡʔϧ௥Ճ
  16. ⡥$MBTTNFUIPE *OD +BDLTPOϞδϡʔϧ௥Ճͷ#FGPSFͱ"GUFS  IUUQTHJUIVCDPNKPPCZQSPKFDUKPPCZUSFFNBTUFSKPPCZKBDLTPO public class User { public

    User(String name, boolean steamer) { this.name = name; this.steamer = steamer; } public String name; public boolean steamer; } get("/user/{name}", (req) -> { return new User(req.param("name").value(), true); }); Ϩεϙϯεʹ6TFSΛฦ٫͢Δ
  17. ⡥$MBTTNFUIPE *OD ͦͷଞ༻ҙ͞ΕͯΔϞδϡʔϧ w KPPCZBLLB w KPPCZBTTFUTMFTTK w KPPCZBTTFUTOPEFKT w

    KPPCZDBTTBOESB w KPPCZDPVDICBTF w KPPCZFMBTUJDTFBSDI w KPPCZKBDLTPO w KPPCZNPOHPEC w KPPCZTXBHHFS  IUUQTHJUIVCDPNKPPCZQSPKFDUKPPCZ
  18. ⡥$MBTTNFUIPE *OD εςʔλείʔυ  err(400, (req, rsp, ex) -> {

    logger.error("Bad Request“, ex); rsp.send("Bad Request"); }); +PPCZ શͯͷύεʹରͯ͠ɺΤϥʔ͕ൃੜͨ͠৔߹ͷॲཧΛهड़͠·͢ɻ͜ͷ৔ ߹͸ɺจࣈྻΛϨεϙϯεͰฦ٫
  19. ⡥$MBTTNFUIPE *OD &YDFQUJPOΫϥε  err(NullPointerException.class, (req, rsp, ex) -> {

    Map<String, String> messageMap = new HashMap<>(); messageMap.put("reaction", "Ψο"); messageMap.put("cause", "͵ΔΆʂ"); logger.error(“null pointer exception”, ex); rsp.send(messageMap.get(“reaction")); // ΤϥʔΛฦ٫ }); +PPCZ શͯͷύεʹରͯ͠ɺ/VMM1PJUFS&YDFQUJPO͕ൃੜͨ͠৔߹ͷॲཧΛهड़͠· ͢ɻ
  20. ⡥$MBTTNFUIPE *OD ͦͷଞྫ֎  public class App extends Jooby {

    { err((req, rsp, ex) -> { logger.error("ex: {}", ex); rsp.send("other error"); }); } } +PPCZ 3PVUFTFSS &SS)BOEMFSFSS ͷγϯλοΫεγϡΨʔͰ͢ɻ IUUQKPPCZPSHBQJEPDTPSHKPPCZ3PVUFTIUNMFSS PSHKPPCZ&SS)BOEMFS Ҿ਺ʹ͍ͭͯ͸ɺΠϯλϑΣʔε&SS)BOEMFSͷIBOEMFϝιουͰ֬ೝͰ͖ ·͢ɻ IUUQKPPCZPSHBQJEPDTPSHKPPCZ&SS)BOEMFSIUNM
  21. ⡥$MBTTNFUIPE *OD #FGPSF  before("/simple", (req, rsp) -> { logger.info("Header

    : {}", req.headers()); }); TJNQMFʹϦΫΤετ͢ΔͱॲཧલʹΠϯλʔηϓτ͠·͢ɻϦΫΤετͷό Ϧσʔγϣϯ΍ϑΟϧλʔ࣮૷ʹ༗ޮͰ͠ΐ͏͔ɻ $ curl http://localhost:8080/simple Hello World! [2016-10-06 17:51:23,524]-[netty task-3-4] INFO jp.classmethod.App - Header : {Host=[localhost:8080], Connection=[keep-alive], Cache-Control=[max-age=0], Upgrade-Insecure-Requests=[1], User-Agent=[Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/ 537.36], Accept=[text/html,application/xhtml+xml,application/xml;q=0.9,image/ webp,*/*;q=0.8], Accept-Encoding=[gzip, deflate, sdch], Accept-Language=[ja,en- US;q=0.8,en;q=0.6], content-length=[0]} ग़ྗ
  22. ⡥$MBTTNFUIPE *OD "GUFS  after("*", (req, rsp, result) -> {

    logger.info("after process"); return result; }); ग़ྗ શͯͷύεʹରͯ͠ϨεϙϯεΛฦ٫͢ΔલʹΠϯλʔηϓτɻ Τϥʔ͕ൃੜͨ͠৔߹͸࣮ߦ͞Εͳ͍ͷͰ஫ҙɻ $ curl http://localhost:8080/simple/revisited revisited [2016-10-06 18:38:17,360]-[netty task-3-2] INFO jp.classmethod.App - after process [2016-10-06 18:38:17,361]-[netty task-3-2] INFO jp.classmethod.App - Call path: / simple/revisited
  23. ⡥$MBTTNFUIPE *OD $PNQMFUF  complete("*", (req, rsp, cause) -> {

    // intercept log logger.info("Call path: {}", req.path()); }); ग़ྗ શͯͷύεʹରͯ͠3FTQPOTFฦ٫ޙʹ࣮ߦ͞Ε·͢ɻϩάͱ͔ʹར༻Ͱ͖ͦ ͏ɻͪ͜Β͸ਖ਼ৗɾΤϥʔؔ܎ͳ͘ඞ࣮ͣߦ͞Ε·͢ɻ [2016-10-06 18:42:21,520]-[netty task-3-6] INFO jp.classmethod.App - after process [2016-10-06 18:42:21,520]-[netty task-3-6] INFO jp.classmethod.App - Call path: / simple/revisited