SlideShare a Scribd company logo
1 of 61
Download to read offline
Spring I/O 2018 報告会
2018.7.30 Tagbangers 佐々⽊木
!1
⾃自⼰己紹介
タグバンガーズ
JSUGスタッフ
佐々⽊木亜⾥里里沙
TagBar
!2
お詫び
Reactive多めになってしまいました
!3
Spring I/O 2018 Digest
https://codezine.jp/article/detail/10930
!4
!5
・Flight of the Flux: A look at Reactor execution model
・Under the hood of Reactive Data access
・REST beyond the obvious
!6
https://www.slideshare.net/TakuyaIwatsuka/spring-5
http://otndnld.oracle.co.jp/ondemand/javaday2017/D1-D5_JavaDayTokyo2017
https://www.slideshare.net/mikeneck/jjug-ccc-2018-spring-i7-netty
Thank you!!
http://argius.hatenablog.jp/entry/20131226/1388068061
https://blog.ik.am/entries/413
https://qiita.com/kencharos/items/2ad090e7a6b7e9664f04
http://d.hatena.ne.jp/Kazuhira/20180107/1515327957
!7
サーバサイドの Reactive の話
イベント ≒ 通信
データが発⽣生するごとに
どのようにデータを処理理していくかの
⼯工程をReadableに書ける
+
データもらう側-あげる側間で
データ流量量調整できる
ここでのReactive
!8
マルチスレッド 別スレッドを⽴立てて処理理 -> 結果はCallback、 Future
⾮非同期処理理(async)
待たない
ノンブロッキング I/O IOの準備ができているか⾃自分で⾒見見に⾏行行く

できてない場合は制御を返す

イベントループ(シングルスレッド)を使ってループ中に複数のIOの状態を監視

IO準備ができたものはループ中で処理理を⾏行行う
Future,
CompletableFuture
NIO というかNetty
並⾏行行処理理(Concurrency) 複数の異異なるタスクを同時に実⾏行行状態にする

処理理実⾏行行中にキャンセルして処理理をやめたりなど。
java.util.concurrent
並列列処理理(Parallel)
Java 1.5〜
Executor, Threadpool,
ConcurrentHashMap …
Java 1.5〜
データを分割(folk)して⼦子スレッドで並列列実⾏行行し、

終わったら⾃自分のスレッドも完了了させる

Work-stealing (ForkJoinPool)

joinによってタスクが中断してスレッドが別のforkしたタスクの処理理に回される
Functional Interface
Function
Consumerlambda式でデータの加⼯工⼯工程をReadable&Composableな形で書ける
Supplier
Predicate
Fork/Join
Java 1.7〜
Java 1.8〜
Reactor を⽀支える技術要素
対応技術説明
Stream#parallel
!9
Reactor
Reactor
Your app
Reactor
Micro service
Driver
Connector
Spring
Data
Spring
Cloud
Spring
WebFlux
NIO
NIO
NIO
Web
Server
UI
Storage
WebSocket
Non-blocking end-to-end data flow architecture
JVM
Server/
Client
Reactor Spring
※
mongodb
redis
couchbase
RabbitMQ
Kafka
Event loop
※使ったり使わなかったり
Event Driven
Netty
Spring
Reactor
Java
!10
Flight of the Flux: A look at Reactor execution model
Nothing happens until you subscribe
 Assembly & Execution Time
 Debug
 Hot&Cold Publisher(例例外)
Concurrency Agnosticだけどスレッドを使う
 publishOn&subscribeOn
 work stealing
その他のよしなに系処理理
 macro & micro fusion
!11
Publisher
データを送る⼈人
Subscriber
データをもらう⼈人
Subscription
pub/subの受付
おさらい:Pub/Sub
onNext()
onError|onComplete
onSubscribe
スタッフ(受付)
おきゃく店の⼈人
こういうデータが流れてきたら
こうやって処理理する
そのデータください
request(n)
cancel()
!12
subscribeするまではpipeline(⼯工程、ステップ)
が書かれてるだけAssembly Time
Nothing happens until you subscribe
!13
subscribe()して初めてデータが流れ出す

subscribeすると最後にfluxがnewされソースにシグナルを送り返す

ソースがデータを渡し始め、パイプライン(⼯工程)のステップごとに

処理理されていく
Execution Time
Subscriber がデータをリクエストして受け取るの繰り返し
Nothing happens until you subscribe
Subscription
RunTime
!14
例例
Flux.just("kaicho","maki", "toki", "iwatsuka", "ikeya")
.filter(s -> s.startWith("i"))
.map(s -> s.toUpperCase())
.take(2)
.subscribe(System.out::println);
!15
filter(->)
map(->)
take(n)
Flux.just
filter(->)
map(->)
take(n)
Publisher
new
Op
new
Op
new
Op
new
Flux.just
!17
Assembly Time
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
!18
Subscription Time
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->)
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
subscribe(->)
!19
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->)
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
subscribe(->)
Subscription
new
!20
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->) onSubscribe
onSubscribe
onSubscribe
onSubscribe
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
subscribe(->)
Subscription
new
!21
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->) onSubscribe
onSubscribe
onSubscribe
onSubscribe
request(n)
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
subscribe(->)
request(n)
request(n)
request(n)
Subscription
new
!22
データ
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->) onSubscribe
onSubscribe
onSubscribe
onSubscribe
request(n)
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
onNext
subscribe(->)
request(n)
request(n)
request(n)
onNext
onNext
onNext
Subscription
new
!23
データ
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->) onSubscribe
onSubscribe
onSubscribe
onSubscribe
request(n)
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
onNext
subscribe(->)
cancel
request(n)
request(n)
request(n)
onNext
onNext
onNext
cancel
cancel
Subscription
new
!24
データ
filter(->)
map(->)
take(n)
subscribe() Subscriber
new
subscribe(->)
subscribe(->)
subscribe(->) onSubscribe
onSubscribe
onSubscribe
onSubscribe
request(n)
Subscriber/Subscription
new
Subscriber/Subscription
new
Subscriber/Subscription
new
Publisher
new
Op
new
Op
new
Op
new
Flux.just
onNext
subscribe(->)
cancel onComplete
request(n)
request(n)
request(n)
onNext
onNext
onNext
cancel
cancel
onComplete
onComplete
onComplete
Subscription
new
!25
データ
Assembly Time / Execution Time はタイミングが違う
java.lang.IndexOutOfBoundsException: Source emitted more than one item
at reactor.core.publisher.MonoSingle$SingleSubscriber.onNext(MonoSingle.java:129)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmitScalar(FluxFlatMap.java:445)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:379)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
at reactor.core.publisher.FluxRange$RangeSubscription.slowPath(FluxRange.java:154)
at reactor.core.publisher.FluxRange$RangeSubscription.request(FluxRange.java:109)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
at reactor.core.publisher.FluxFlatMap$FlatMapMain.onSubscribe(FluxFlatMap.java:332)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:
90)
at reactor.core.publisher.FluxRange.subscribe(FluxRange.java:68)
at reactor.core.publisher.FluxMapFuseable.subscribe(FluxMapFuseable.java:63)
at reactor.core.publisher.FluxFlatMap.subscribe(FluxFlatMap.java:97)
at reactor.core.publisher.MonoSingle.subscribe(MonoSingle.java:58)
at reactor.core.publisher.Mono.subscribe(Mono.java:3096)
at reactor.core.publisher.Mono.subscribeWith(Mono.java:3204)
at reactor.core.publisher.Mono.subscribe(Mono.java:3090)
at reactor.core.publisher.Mono.subscribe(Mono.java:3057)
at reactor.core.publisher.Mono.subscribe(Mono.java:3029)
at reactor.guide.GuideTests.debuggingCommonStacktrace(GuideTests.java:995)
→ stacktraceが追いづらい
!26
Hooks.onOperatorDebug();
Assembly timeの機構を利利⽤用

アプリ起動時(Flux,Monoのインスタンス
化前)に⾏行行われる
java.lang.IndexOutOfBoundsException: Source emitted more than one item
at reactor.core.publisher.MonoSingle$SingleSubscriber.onNext(MonoSingle.java:120)
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:314)
...
...
at reactor.core.publisher.Mono.subscribeWith(Mono.java:2668)
at reactor.core.publisher.Mono.subscribe(Mono.java:2629)
at reactor.core.publisher.Mono.subscribe(Mono.java:2604)
at reactor.core.publisher.Mono.subscribe(Mono.java:2582)
at reactor.guide.GuideTests.debuggingActivated(GuideTests.java:727)
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Assembly trace from producer [reactor.core.publisher.MonoSingle] :
reactor.core.publisher.Flux.single(Flux.java:5335)
reactor.guide.GuideTests.scatterAndGather(GuideTests.java:689)
reactor.guide.GuideTests.populateDebug(GuideTests.java:702)
org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
org.junit.rules.RunRules.evaluate(RunRules.java:20)
Error has been observed by the following operator(s):
|_ Flux.single(TestWatcher.java:55)
Debugモードにする魔法
エラーが起きるとFluxがnewされた箇所を

Assembly Timeに解析した内容を元に

追記してくれる

(がコストが⾼高い)!27
checkpoint()
Debugの仕⽅方2
!28
public void checkpointWithDescriptionIsLight() {
StringWriter sw = new StringWriter();
Flux<Integer> tested = Flux.range(1, 10)
.map(i -> i < 3 ? i : null)
.filter(i -> i % 2 == 0)
.checkpoint("foo")
.doOnError(t -> t.printStackTrace(new PrintWriter(sw)));
StepVerifier.create(tested)
.expectNext(2)
.verifyError();
String debugStack = sw.toString();
}
Assembly site of producer [reactor.core.publisher.FluxFilterFuseable] is
identified by light checkpoint [foo].
Nothing happens until you subscribe… ですが 例例外あり
Hot Publisher
Cold Publisher
これはこっちの話
subscriptionごとにデータを新しくこさえる

例例:HTTP request
⼀一度でもsubscribeされたら(⼀一度データが流れ出したら)

その後はお構いなく流れていく

途中からsubscribeしたSubscriberはsubscribeするより前に

何かが起こっていることになる

例例:Processorクラスを継承したもの
!29
Flux<String> source = Flux.fromIterable(Arrays.asList("blue", "green", "orange", "purple"))
.map(String::toUpperCase);
source.subscribe(d -> System.out.println("Subscriber 1 to Cold Source: "+d));
source.subscribe(d -> System.out.println("Subscriber 2 to Cold Source: "+d));
Cold Publisher
!30
Flux<String> source = Flux.fromIterable(Arrays.asList("blue", "green", "orange", "purple"))
.map(String::toUpperCase);
source.subscribe(d -> System.out.println("Subscriber 1 to Cold Source: "+d));
source.subscribe(d -> System.out.println("Subscriber 2 to Cold Source: "+d));
Subscriber 1 to Cold Source: BLUE
Subscriber 1 to Cold Source: GREEN
Subscriber 1 to Cold Source: ORANGE
Subscriber 1 to Cold Source: PURPLE
Subscriber 2 to Cold Source: BLUE
Subscriber 2 to Cold Source: GREEN
Subscriber 2 to Cold Source: ORANGE
Subscriber 2 to Cold Source: PURPLE
Cold Publisher
!31
UnicastProcessor<String> hotSource = UnicastProcessor.create();
Flux<String> hotFlux = hotSource.publish()
.autoConnect()
.map(String::toUpperCase);
hotSource.onNext("blue");
hotSource.onNext("green");
hotFlux.subscribe(d -> System.out.println("Subscriber 1 to Hot Source: "+d));
hotFlux.subscribe(d -> System.out.println("Subscriber 2 to Hot Source: "+d));
hotSource.onNext("orange");
hotFlux.subscribe(d -> System.out.println("Subscriber 3 to Hot Source: "+d));
hotSource.onNext("purple");
hotSource.onComplete();
Hot Publisher
!32
Subscriber 1 to Hot Source: BLUE
Subscriber 1 to Hot Source: GREEN
Subscriber 1 to Hot Source: ORANGE
Subscriber 2 to Hot Source: ORANGE
Subscriber 1 to Hot Source: PURPLE
Subscriber 2 to Hot Source: PURPLE
Subscriber 3 to Hot Source: PURPLE
Hot Publisher
UnicastProcessor<String> hotSource = UnicastProcessor.create();
Flux<String> hotFlux = hotSource.publish()
.autoConnect()
.map(String::toUpperCase);
hotSource.onNext("blue");
hotSource.onNext("green");
hotFlux.subscribe(d -> System.out.println("Subscriber 1 to Hot Source: "+d));
hotFlux.subscribe(d -> System.out.println("Subscriber 2 to Hot Source: "+d));
hotSource.onNext("orange");
hotFlux.subscribe(d -> System.out.println("Subscriber 3 to Hot Source: "+d));
hotSource.onNext("purple");
hotSource.onComplete();
!33
Concurrency agnosticだがスレッドを⽴立てる
subscribeOn(Schedulers) …
subscriptionが発⽣生するシーケンスを変更更する
publishOn(Schedulers) …
subscribeしてスレッドが始まりパイプラインの先頭から
処理理されていくが、publishOnがきたら別のスレッドに
ジャンプする
Schedulers#immediate(),single(),elastic(),parallel()
!34
!35
!36
!37
macro fusion … 同じオペレータをまとめる
オペレータのインスタンス⽣生成を節約するFusion
!38
micro fusion … 異異なるオペレータを1つのキューに(話し合って)まとめる
QueueSubscription
#requestFusion(requestMode)
Fusesable.NONE
Fusesable.SYNC
Fusesable.ASYNC
Fusesable.ANY
Fusesable.THREAD_BARRIER
!39
・Flight of the Flux: A look at Reactor execution model
・Under the hood of Reactive Data access
・REST beyond the obvious
!40
Under the hood of Reactive Database
話のスコープ
各DB Driverの実装の仕⽅方
!41
Reactor
Reactor
Your app
Reactor
Micro service
Driver
Connector
Spring
Data
Spring
Cloud
Spring
WebFlux
NIO
NIO
NIO
Web
Server
UI
Storage
WebSocket
Non-blocking end-to-end data flow architecture
JVM
Server/
Client
Reactor Spring
※
mongodb
redis
couchbase
RabbitMQ
Kafka
Event loop
※使ったり使わなかったり
Event Driven
Netty
Spring
Reactor
Java
!42
!43
prefetch, backpressureのおかげで
ReactiveDriverはデータがどこまで取得できているのかを把握できるため
データをすべてロードするまで待たなくて良い
!44
Spring Data で Reactive に DB アクセスできるもの
•Spring Data Commons
•Spring Data JPA
•Spring Data KeyValue
•Spring Data LDAP
•Spring Data MongoDB
•Spring Data REST
•Spring Data Redis
•Spring Data for Apache Cassandra
•Spring Data for Apache Geode
•Spring Data for Apache Solr
•Spring Data for Pivotal GemFire
•Spring Data Couchbase (community module)
•Spring Data Elasticsearch (community module)
•Spring Data Neo4j (community module)
http://projects.spring.io/spring-data/
ドキュメント指向
Key-Value型
Column型
KVS
!45
アクションログ
Spring Data
JDBC
JVM
RDBS
Reactor
MongoDB
Reactive Streams
Java Driver
JVM
MongoDB
Reactor
Lettuce
JVM
Redis
Reactor
DataStax Java driver
for Cassandra
JVM
Cassandra
Reactor
Reactive
Couchbase
JVM
Couchbase
Server
Spring Data JPA
Spring Data
MongoDB
Spring Data
Redis
Spring Data for
Cassandra
Spring Data
Couchbase
Under the hood of ~の話のスコープ
… 各ベンダが⽤用意している DB Driver の Reactive 対応状況
!46
Spring Data
JDBC
JVM
RDBS
Reactor
MongoDB
Reactive Streams
Java Driver
JVM
MongoDB
Reactor
Lettuce
JVM
Redis
Reactor
DataStax Java driver
for Cassandra
JVM
Cassandra
Reactor
Reactive
Couchbase
JVM
Couchbase
Server
Spring Data JPA
Spring Data
MongoDB
Spring Data
Redis
Spring Data for
Cassandra
Spring Data
Couchbase
Under the hood of ~の話のスコープ
… 各ベンダが⽤用意している DB Driver の Reactive 対応状況
Fully blocking API
ADBA,R2DBCなどがnon-blocking api
!47
•Driverが必要とするThreadの構造

•タイムアウトのハンドリング

•ConnectTimeout

•ReadTimeout

•CommandTimeout
ReactiveでないDBとの違い
!48
Imperative
Imperative
Reactive
Reactive ⾃自分で完了了シグナルを送る必要がある
データが来るのを待ち続けるので
ReadTimeoutの概念が存在しない
Reactive Drivers
End-to-end nonblocking
Asynchronous request-response processing
Non-blocking pooling
Non-blocking connect
!49
mongodb dependencies
mongodb の driver が Reactive Streamsの API を実装している
mongodb Publisher を Flux.from(mongodbのPublisher) によって Reactor の Publisher に変換してる
!50
mongodb dependencies
mongodb の driver が Reactive Streamsの API を実装している
mongodb Publisher を Flux.from(mongodbのPublisher) によって Reactor の Publisher に変換してる
!51
redis dependencies
!52
cassandra dependencies
!53
cassandra dependencies
!54
couchbase dependencies
!55
couchbase dependencies
!56
MongoDB Reactive-over-async driver (Reactor/RxJava)
Cursor lifecycle
Pluggable I/O … SSL通信、Java6を使⽤用する場合はNettyを使う必要あり
Pooled Connections
CursorにBatchsizeがある
.filter()を使うとデータをrequestした分以上に取得してしまうので、ReactorのlimitRateを使う
Redis
Apache Cassandra
Reactive Driver (Lettuce5)
Netty&Project Reactor
データがリクエストされるとすぐにデータがemitされる
Pooled Connectionはオプション
Reactive Driverは持っていない (Reactive bridge over async driver)
Netty-based Driver(Datastax)
Pooled Connection
Couchbase Reactive Driver
Netty&RxJava1 -> RxJava2に移⾏行行しつつある
JavaのexecuteAsync()
!57
!58
・Flight of the Flux: A look at Reactor execution model
・Under the hood of Reactive Data access
・REST beyond the obvious
!59
!60
ありがとうございました
!61

More Related Content

Similar to JSUG勉強会 2018年その5 Spring I/O 報告会

Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
Shinpei Ohtani
 
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframeworkSpring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Toshiaki Maki
 
AWSをコードで定義する
AWSをコードで定義するAWSをコードで定義する
AWSをコードで定義する
Sugawara Genki
 
ROS JAPAN Users Group Meetup 03
ROS JAPAN Users Group Meetup 03ROS JAPAN Users Group Meetup 03
ROS JAPAN Users Group Meetup 03
Daiki Maekawa
 

Similar to JSUG勉強会 2018年その5 Spring I/O 報告会 (20)

Azure のポータル画面で、AI フレーバな BOT の作成ハンズオン
Azure のポータル画面で、AI フレーバな BOT の作成ハンズオンAzure のポータル画面で、AI フレーバな BOT の作成ハンズオン
Azure のポータル画面で、AI フレーバな BOT の作成ハンズオン
 
React を導入した フロントエンド開発
React を導入したフロントエンド開発React を導入したフロントエンド開発
React を導入した フロントエンド開発
 
Rx java x retrofit
Rx java x retrofitRx java x retrofit
Rx java x retrofit
 
Reactor Netty & Apache Kafka Stack #jsug
Reactor Netty & Apache Kafka Stack #jsugReactor Netty & Apache Kafka Stack #jsug
Reactor Netty & Apache Kafka Stack #jsug
 
これからのJDK/JVM 何を選ぶ?どう選ぶ?
これからのJDK/JVM 何を選ぶ?どう選ぶ?これからのJDK/JVM 何を選ぶ?どう選ぶ?
これからのJDK/JVM 何を選ぶ?どう選ぶ?
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
 
Wicket勉強会2
Wicket勉強会2Wicket勉強会2
Wicket勉強会2
 
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframeworkSpring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
Spring Frameworkの今 (2013年版) #jjug_ccc #ccc_r17 #springframework
 
Lightweight Keycloak
Lightweight KeycloakLightweight Keycloak
Lightweight Keycloak
 
AWSをコードで定義する
AWSをコードで定義するAWSをコードで定義する
AWSをコードで定義する
 
Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話Async awaitでの繰り返し処理についての小話
Async awaitでの繰り返し処理についての小話
 
Springでdao 20070413
Springでdao 20070413Springでdao 20070413
Springでdao 20070413
 
Ptt391
Ptt391Ptt391
Ptt391
 
どこよりも早い Spring Boot 1.2 解説 #渋谷Java
どこよりも早い Spring Boot 1.2 解説 #渋谷Javaどこよりも早い Spring Boot 1.2 解説 #渋谷Java
どこよりも早い Spring Boot 1.2 解説 #渋谷Java
 
SappoRo.R #3 LT: Shiny by RStudio
SappoRo.R #3 LT: Shiny by RStudioSappoRo.R #3 LT: Shiny by RStudio
SappoRo.R #3 LT: Shiny by RStudio
 
ROS JAPAN Users Group Meetup 03
ROS JAPAN Users Group Meetup 03ROS JAPAN Users Group Meetup 03
ROS JAPAN Users Group Meetup 03
 
JavaOne 2016 Java SE Feedback #jjug #j1jp
JavaOne 2016 Java SE Feedback #jjug #j1jpJavaOne 2016 Java SE Feedback #jjug #j1jp
JavaOne 2016 Java SE Feedback #jjug #j1jp
 
sgvizler
sgvizlersgvizler
sgvizler
 
20130511 jjug ccc講演 さらばjsp JAXBとmixer2
20130511 jjug ccc講演 さらばjsp JAXBとmixer220130511 jjug ccc講演 さらばjsp JAXBとmixer2
20130511 jjug ccc講演 さらばjsp JAXBとmixer2
 
Oracle In-database-archiving ~Oracleでの論理削除~
Oracle In-database-archiving ~Oracleでの論理削除~Oracle In-database-archiving ~Oracleでの論理削除~
Oracle In-database-archiving ~Oracleでの論理削除~
 

JSUG勉強会 2018年その5 Spring I/O 報告会