Slide 1

Slide 1 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | Asynchronous Database Access (ADBA) #JJUG_CCC #ccc_g7 Akihiro Nishikawa Oracle Corporation Japan May 26, 2018 JDBC API

Slide 2

Slide 2 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Safe Harbor Statement The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 2

Slide 3

Slide 3 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | First of All... 3

Slide 4

Slide 4 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. NOTICE • Today’s topic is now discussed actively. • Everything is subject to change. • This has not been in Java specifications yet. 4

Slide 5

Slide 5 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Agenda Introduction Basic Concepts More Concepts with Codes Wrap up 1 2 3 4 5

Slide 6

Slide 6 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | Introduction 6

Slide 7

Slide 7 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Nowadays... • JDBC APIs are based on synchronous access. • You might think it is no problem at all since you use pooled connections. 7 !

Slide 8

Slide 8 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. But... • What do you do if application requires high throughput? • What if does the application run standalone as an AOT compiled native image or a function? 8 !

Slide 9

Slide 9 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 9 How about introducing asynchronous paradigm to database access?

Slide 10

Slide 10 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Asynchronous Database Access (ADBA) • Being developed by the JDBC Expert Group with community input • Targeted for a near future release of Java • Asynchronous apps have better throughput – Fewer threads means less thread scheduling, less thread contention – Database access is slow so blocked threads leave resources idle for a long time – Simultaneous access to multiple databases (map/reduce, sharded databases, ...) – Fire and forget (DML, stored procedures, ...) 10 Java standard database access API that never blocks user threads

Slide 11

Slide 11 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Goals • No user thread blocks – Minimize the number of threads used for database access • Alternate API for database access – Not an extension of the standard JDBC API – Not a replacement for the standard JDBC API • Target high throughput apps – Not a completely general purpose database access API – The initial version will have a limited feature set • Build on the Java SE class library 11

Slide 12

Slide 12 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Goals • No user thread blocks – Minimize the number of threads used for database access • Alternate API for database access – Not an extension of the standard JDBC API – Not a replacement for the standard JDBC API • Target high throughput apps – Not a completely general purpose database access API – The initial version will have a limited feature set • Build on the Java SE class library 12 Neither replacement nor enhancement, but complementary

Slide 13

Slide 13 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Design choices • Minimal or no reference to java.sql • Rigorous use of types • Builder pattern • Fluent API • Immutable after initialization • One way to do something is enough • Avoid SQL processing • Avoid callback hell 13

Slide 14

Slide 14 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. ADBA (Asynchronous Database Access) • Package –java.sql2 (jdk.incubator.sql2) • Module –jdk.adba (jdk.incubator.adba) [Note] • Implementation-specific features are out of scope of this session. – Statement cache – Connection cache... 14

Slide 15

Slide 15 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 15 We have lots of ways to access databases asynchronously, don’t we?

Slide 16

Slide 16 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. What About... ? • Streams – Java streams are inherently synchronous • Reactive Streams – Not integrated into the Java SE class library • Node.js – JavaScript... (Indeed this runs on Graal VM, but...) • ADBCJ - Asynchronous Database Connectivity in Java (ADBCJ) https://code.google.com/archive/p/adbcj/ 16 There are already multiple asynchronous/non-blocking Java and JavaScript APIs...

Slide 17

Slide 17 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | Basic Concepts 17

Slide 18

Slide 18 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. CompletionStage & CompletableFuture • Java class library mechanism for asynchronous style programming – Brings reactive programming to Java – Enables the composition of asynchronous tasks – A task has a state and it might be... • running • completed normally with a result • completed exception all with an exception – Event thread : the result of the completion is pushed to dependent tasks • Push model à higher scalability than pull or poll • Supports lambda expressions and fluent programming 18

Slide 19

Slide 19 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Execution Model (1/2) • Operation consists of a result and a CompletionStage • SQL or other database operation • Parameter assignments • Result handling • Submission and CompletableFuture 19 Everything is an Operation

Slide 20

Slide 20 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Execution Model (2/2) • User thread creates and submits Operations – User thread is never blocked when creating and submitting Operations. • Implementation executes those Operations asynchronously – Performs round trip(s) to the database – Executes result handling – Completes CompletableFutures 20

Slide 21

Slide 21 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | More concepts with Codes 21

Slide 22

Slide 22 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 22 public void trivialInsert(DataSource ds) { String sql = "insert into tab values (:id, :name, :answer)"; try (Connection conn = ds.getConnection()) { conn.countOperation(sql) .set("id", 1, AdbaType.NUMERIC) .set("name", "Deep Thought", AdbaType.VARCHAR) .set("answer", 42, AdbaType.NUMERIC) .submit(); } } Trivial Insert

Slide 23

Slide 23 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. All SQL is Vendor Specific • No escape sequences • No specified parameter markers • Non vendor specific syntax requires processing by the driver – Adds overhead – Increases code complexity – Minimal benefit as most apps are tied to a specific database regardless 23

Slide 24

Slide 24 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. All SQL is Vendor Specific • DB2 (:foo) • MySQL (?) • Oracle Database (:foo) • PostgresSQL ($1) • SQL Server (@foo) 24 Note: Code examples use parameter markers from a variety of databases.

Slide 25

Slide 25 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 25 public void trivialSelect(DataSource ds, List result) { String sql = "select id, name, answer from tab where answer = $1"; try (Connection conn = ds.getConnection()) { conn.>rowOperation(sql) .set("1", 42, AdbaType.NUMERIC) .collect((ignore, row) -> { result.add(row.get("id", Integer.class)); return null; }) .submit(); } } Trivial Select

Slide 26

Slide 26 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 26 public DataSource getDataSource(String url, String user, String pass) { return DataSourceFactory.forName("Oracle Database") .builder() .url("jdbc:oracle:nonblocking:@//ccc18.example.org:5521/ccc18") .username("scott") .password("tiger") .connectionProperty(AdbaConnectionProperty.TRANSACTION_ISOLATION, AdbaConnectionProperty.TransactionIsolation.SERIALIZABLE) .connectionProperty(NLS_LANGUAGE, "Japanese") .build(); } ConnectionProperties

Slide 27

Slide 27 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 27 in interface DataSource: public default Connection getConnection() { return builder().build().connect(); } in interface Connection: public default Connection connect() { holdForMoreMembers(); submit(); connectOperation().submit(); return this; } Getting Connection

Slide 28

Slide 28 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Connection Pooling in interface Connection: public Connection activate(); public Connection deactivate(); public registerLifecycleListener(LifecycleListener listener); 28 If you remove registered LifecycleListener, call deregisterLifecycleListener()

Slide 29

Slide 29 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 29 public Future selectIdForAnswer(DataSource ds, int answer) { String sql = "select id, name, answer from tab where answer = @target"; try (Connection conn = ds.getConnection()) { return conn.>rowOperation(sql) .set("target", 42, AdbaType.NUMERIC) .collect((list, row) -> { list.add(row.get("id", Integer.class)); return list; } ) .submit() .toCompletableFuture() .thenApply(l -> l.get(0)); } } Basic SELECT

Slide 30

Slide 30 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 30 public class Item { protected int id; protected String name; protected int answer; @SqlColumns({"ID", "USER", "RESPONSE"}) public Item(int id, String name, int answer) { this.id = id; this.name = name; this.answer = answer; } @SqlParameter(marker = "id", sqlType = "NUMERIC") public int getId() { return id; } (cont.) POJOs (1/2)

Slide 31

Slide 31 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 31 (cont.) @SqlParameter(marker = "name", sqlType = "VARCHAR") public String getName() { return name; } @SqlParameter(marker = "answer", sqlType = "NUMERIC") public int getAnswer() { return answer; } } POJOs (2/2)

Slide 32

Slide 32 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. OperationGroup (1/2) • OperationGroup has its own result handling and CompletableFuture • Members submitted to group.OperationGroup is submitted as a unit • Execution Order – Default : Sequential in order submitted – parallel() : should be marked if having member Operations executed in any order including in parallel. 32 group of Operations

Slide 33

Slide 33 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. OperationGroup (1/2) • Error response – Default : Skip remaining group members if failure of one member Operation happens. (with a SqlSkippedException with the cause set to the original exception). – independent(): should be marked if remaining group members unaffected • Conditional or unconditional • Connection is an OperationGroup – Sequential, dependent, unconditional by default 33

Slide 34

Slide 34 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 34 public void insertListHold(List list, DataSource ds) { String sql = "insert into tab values (@elem_id, @elem_name, @elem_answer)"; try (Connection conn = ds.getConnection()) { OperationGroup group = conn.operationGroup().independent(); group.submitHoldingForMoreMembers(); for (Item elem : list) { group.countOperation(sql) .set("elem_", elem).submit().getCompletionStage() .exceptionally(t -> { System.out.println(elem.getId()); return null; }); } group.releaseProhibitingMoreMembers(); } } Independent INSERT

Slide 35

Slide 35 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 35 public void deposit(Connection conn, int accountId, double amount) { String selectSql = "select balance from account where id = $1"; CompletableFuture newBalanceF = conn.rowOperation(selectSql) .set("1", accountId, AdbaType.INTEGER) .collect((p, row) -> row.get("balance", Double.class)) .submit() .toCompletableFuture() .thenApply(b -> b + amount); String updateSql = "update account set balance=$2 where id = $1"; conn.countOperation(updateSql).set("1", accountId, AdbaType.INTEGER) .set("2", newBalanceF, AdbaType.DOUBLE) .submit(); } Future Parameters

Slide 36

Slide 36 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 36 public void updateListParallel(List list, DataSource ds) { String query = "select id from tab where answer = ?"; String update = "update tab set answer = ? where id = ?"; try (Connection conn = ds.getConnection()) { OperationGroup group = conn.operationGroup() .independent() .parallel(); group.submitHoldingForMoreMembers(); (cont.) Parallel UPDATE (1/3)

Slide 37

Slide 37 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 37 (cont.) for (Item elem : list) { CompletableFuture idF = group.rowOperation(query) .set("1", elem.getAnswer(), AdbaType.NUMERIC) .collect((ignore, row) -> { return row.get("id", Integer.class); }) .submit() .toCompletableFuture(); (cont.) Parallel UPDATE (2/3)

Slide 38

Slide 38 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 38 (cont.) group.countOperation(update).set("1", idF) .set("2", "42") .submit() .getCompletionStage() .exceptionally(t -> { System.out.println("Update failed: " + elem.getId()); return null; }); } group.releaseProhibitingMoreMembers(); } } Parallel UPDATE (3/3)

Slide 39

Slide 39 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Close in interface Connection: public default void close() { closeOperation().submit(); releaseProhibitingMoreMembers(); } 39 CloseOperation is never skipped.

Slide 40

Slide 40 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 40 public static class NlsLanguageProperty implements ConnectionProperty { public static final ConnectionProperty NLS_LANGUAGE = new NlsLanguageProperty(); private NlsLanguageProperty() { } public String name() { return "NLS_LANGUAGE"; } public Class range() { return String.class; } ConnectionProperty (1/2)

Slide 41

Slide 41 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 41 public String defaultValue() { return "American"; } public boolean isSensitive() { return false; } public Operation configureOperation(OperationGroup group, Object value) { String sql = "ALTER SESSION SET NLS_LANGUAGE TO " + value; return group.operation(sql); } } ConnectionProperty (2/2)

Slide 42

Slide 42 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 42 @SqlStruct(sqlTypeName = "STUDENT", fields = { @SqlStruct.Field(sqlFieldName = "NAME", sqlTypeName = "VARCHAR(100)", javaFieldName = "name"), @SqlStruct.Field(sqlFieldName = "EMAIL", sqlTypeName = "VARCHAR(100)", javaFieldName = "email") }) public class Student { String name; String email; ... } @SqlArray(elementSqlTypeName = "STUDENT") public class Roster extends LinkedList { public Roster() {} } ARRAYs and STRUCTs

Slide 43

Slide 43 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 43 public void transfer(Connection conn, double amount, int fromAccount, int toAccount) { String sql = "update account set balance=balance+@amount where id = @account"; conn.countOperation(sql) .set("amount", -amount, AdbaType.DECIMAL) .set("account", fromAccount, AdbaType.INTEGER) .submit(); conn.countOperation(sql) .set("amount", amount, AdbaType.DECIMAL) .set("account", toAccount, AdbaType.INTEGER) .submit(); conn.commit(); } Transactions (1/2)

Slide 44

Slide 44 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 44 public void transfer(Connection conn, double amount, int fromAccount, int toAccount) { String sql = "update account set balance=balance+@amount where id = @account"; final Transaction tran = conn.transaction(); conn.countOperation(sql) .set("amount", -amount, AdbaType.DECIMAL) .set("account", fromAccount, AdbaType.INTEGER) .onError( e -> tran.setRollbackOnly() ) .submit(); conn.countOperation(sql) .set("amount", amount, AdbaType.DECIMAL) .set("account", toAccount, AdbaType.INTEGER) .onError( e -> tran.setRollbackOnly() ) .submit(); conn.commit(); } Transactions (2/2)

Slide 45

Slide 45 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 45 public void paycheck(Connection conn, Employee emp) { String sql = "call generate_paycheck(?, ?)"; CompletableFuture details = conn.outOperation(sql) .set("1", emp, AdbaType.STRUCT) .outParameter("2", AdbaType.STRUCT) .resultProcessor(m -> m.get("2", CheckDetail.class)) .submit() .toCompletableFuture(); (cont.) Local Operations (1/2)

Slide 46

Slide 46 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. 46 (cont.) conn.localOperation() .onExecution(() -> { printPaycheck(details); return null; }) .submit() .toCompletableFuture() .thenRun(() -> reportPrintSuccess(details)) .exceptionally(t -> { reportPrintFailure(details); return null; }); } Local Operations (2/2)

Slide 47

Slide 47 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. | Wrap up 47

Slide 48

Slide 48 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Key takeaways • Asynchronous • Geared toward high-throughput programs • Does not attempt to support every database feature • Does not attempt to abstract the database • Uses the builder pattern • Supports the fluent programming style 48

Slide 49

Slide 49 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Status • Now developed by the JDBC Expert Group through the Java Community Process • Targeted for a near future release of Java • Send feedback to [email protected] 49 Everything is subject to change!

Slide 50

Slide 50 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Resources • Available for download from OpenJDK http://oracle.com/goto/java-async-db • AoJ (ADBA over JDBC) [JDK 9 or later is required] https://github.com/oracle/oracle-db-examples/tree/master/java/AoJ • JavaDoc http://cr.openjdk.java.net/~lancea/8188051/apidoc/jdk.incubator.adba-summary.html 50

Slide 51

Slide 51 text

Copyright © 2018, Oracle and/or its affiliates. All rights reserved. Safe Harbor Statement The preceding is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, and timing of any features or functionality described for Oracle’s products remains at the sole discretion of Oracle. 51

Slide 52

Slide 52 text

No content