diff --git a/src/main/java/com/github/sttk/sabi/DataHub.java b/src/main/java/com/github/sttk/sabi/DataHub.java index d817061..291384d 100644 --- a/src/main/java/com/github/sttk/sabi/DataHub.java +++ b/src/main/java/com/github/sttk/sabi/DataHub.java @@ -94,6 +94,14 @@ public record FailToCastDataConn(String name, String castToType) {} */ public record RuntimeExceptionOccurred() {} + /** + * Represents an error reason that occurred when failing to cast the {@code DataHub} instance + * itself to the expected data access interface type for a {@link Logic}. + * + * @param castFromType The actual type of the {@code DataHub} instance that failed to cast. + */ + public record FailToCastDataHub(String castFromType) {} + private final DataHubInner inner = new DataHubInner(); /** Constructs a new {@code DataHub} instance. */ @@ -161,4 +169,68 @@ void rollback() { void end() { inner.end(); } + + /** + * Executes the provided application {@link Logic} without transactional boundaries. The {@code + * DataHub} instance is treated as the data access object {@code D} to the {@link Logic}'s {@code + * run} method. + * + * @param The type of the data access object, which typically is {@code DataHub} or an + * interface implemented by {@code DataHub} that {@link Logic} expects. + * @param logic The application logic to execute. + * @throws Err if an {@link Err} or {@link RuntimeException} occurs during logic execution or if + * the {@code DataHub} cannot be cast to the expected data access type. + */ + public void run(Logic logic) throws Err { + D data; + try { + @SuppressWarnings("unchecked") + D d = (D) this; + data = d; + } catch (Exception e) { + throw new Err(new FailToCastDataHub(this.getClass().getName())); + } + try { + this.begin(); + logic.run(data); + } catch (Err | RuntimeException e) { + throw e; + } finally { + this.end(); + } + } + + /** + * Executes the provided application {@link Logic} within a transactional context. The {@code + * DataHub} instance is treated as the data access object {@code D} to the {@link Logic}'s {@code + * run} method. If the logic completes successfully, a commit operation is attempted. If any + * {@link Err}, {@link RuntimeException}, or {@link Error} occurs, a rollback operation is + * performed. + * + * @param The type of the data access object, which typically is {@code DataHub} or an + * interface implemented by {@code DataHub} that {@link Logic} expects. + * @param logic The application logic to execute transactionally. + * @throws Err if an {@link Err}, {@link RuntimeException}, or {@link Error} occurs during logic + * execution, pre-commit, or commit. The original exception is re-thrown after rollback. + */ + public void txn(Logic logic) throws Err { + D data; + try { + @SuppressWarnings("unchecked") + D d = (D) this; + data = d; + } catch (Exception e) { + throw new Err(new FailToCastDataHub(this.getClass().getName())); + } + try { + this.begin(); + logic.run(data); + this.commit(); + } catch (Err | RuntimeException | Error e) { + this.rollback(); + throw e; + } finally { + this.end(); + } + } } diff --git a/src/main/java/com/github/sttk/sabi/Sabi.java b/src/main/java/com/github/sttk/sabi/Sabi.java index 796bf07..17bd782 100644 --- a/src/main/java/com/github/sttk/sabi/Sabi.java +++ b/src/main/java/com/github/sttk/sabi/Sabi.java @@ -34,14 +34,6 @@ * } */ public final class Sabi { - /** - * Represents an error reason that occurred when failing to cast the {@code DataHub} instance - * itself to the expected data access interface type for a {@link Logic}. - * - * @param castFromType The actual type of the {@code DataHub} instance that failed to cast. - */ - public record FailToCastDataHub(String castFromType) {} - private Sabi() {} /** @@ -71,72 +63,4 @@ public static void uses(String name, DataSrc ds) { public static AutoCloseable setup() throws Err { return DataHubInner.setupGlobals(); } - - /** - * Executes the provided application {@link Logic} without transactional boundaries. The {@code - * DataHub} instance in the parameters is passed as the data access object {@code D} to the {@link - * Logic}'s {@code run} method. - * - * @param The type of the data access object, which typically is {@code DataHub} or an - * interface implemented by {@code DataHub} that {@link Logic} expects. - * @param logic The application logic to execute. - * @param hub An instance of a DataHub subclass that inherits the data interface for logic - * arguments. - * @throws Err if an {@link Err} or {@link RuntimeException} occurs during logic execution or if - * the {@code DataHub} cannot be cast to the expected data access type. - */ - public static void run(Logic logic, DataHub hub) throws Err { - D data; - try { - @SuppressWarnings("unchecked") - D d = (D) hub; - data = d; - } catch (Exception e) { - throw new Err(new FailToCastDataHub(hub.getClass().getName())); - } - try { - hub.begin(); - logic.run(data); - } catch (Err | RuntimeException e) { - throw e; - } finally { - hub.end(); - } - } - - /** - * Executes the provided application {@link Logic} within a transactional context. The {@code - * DataHub} instance in the parameter is passed as the data access object {@code D} to the {@link - * Logic}'s {@code run} method. If the logic completes successfully, a commit operation is - * attempted. If any {@link Err}, {@link RuntimeException}, or {@link Error} occurs, a rollback - * operation is performed. - * - * @param The type of the data access object, which typically is {@code DataHub} or an - * interface implemented by {@code DataHub} that {@link Logic} expects. - * @param logic The application logic to execute transactionally. - * @param hub An instance of a DataHub subclass that inherits the data interface for logic - * arguments. - * @throws Err if an {@link Err}, {@link RuntimeException}, or {@link Error} occurs during logic - * execution, pre-commit, or commit. The original exception is re-thrown after rollback. - */ - public static void txn(Logic logic, DataHub hub) throws Err { - D data; - try { - @SuppressWarnings("unchecked") - D d = (D) hub; - data = d; - } catch (Exception e) { - throw new Err(new FailToCastDataHub(hub.getClass().getName())); - } - try { - hub.begin(); - logic.run(data); - hub.commit(); - } catch (Err | RuntimeException | Error e) { - hub.rollback(); - throw e; - } finally { - hub.end(); - } - } } diff --git a/src/test/java/com/github/sttk/sabi/internal/DataAccTest.java b/src/test/java/com/github/sttk/sabi/internal/DataAccTest.java index 771d881..a269a94 100644 --- a/src/test/java/com/github/sttk/sabi/internal/DataAccTest.java +++ b/src/test/java/com/github/sttk/sabi/internal/DataAccTest.java @@ -317,7 +317,7 @@ void test() { try (var ac = Sabi.setup()) { suppressWarnings_unused(ac); try (var data = new SampleDataHub()) { - Sabi.run(new SampleLogic(), data); + data.run(new SampleLogic()); } catch (Exception e) { fail(e); } @@ -362,7 +362,7 @@ void test() { data.uses("foo", new FooDataSrc(1, "hello", logger, false)); data.uses("bar", new BarDataSrc(2, logger, false)); - Sabi.run(new SampleLogic(), data); + data.run(new SampleLogic()); } catch (Exception e) { fail(e); } @@ -394,7 +394,7 @@ void test_not_run_logic_if_fail_to_setup_local_data_src() { data.uses("foo", new FooDataSrc(1, "hello", logger, true)); data.uses("bar", new BarDataSrc(2, logger, false)); - Sabi.run(new SampleLogic(), data); + data.run(new SampleLogic()); } catch (Err e) { switch (e.getReason()) { case DataHub.FailToSetupLocalDataSrcs r -> { @@ -437,7 +437,7 @@ void test() { try (var data = new SampleDataHub()) { data.uses("foo", new FooDataSrc(2, "Hello", logger, false)); - Sabi.run(new SampleLogic(), data); + data.run(new SampleLogic()); } catch (Exception e) { fail(e); } @@ -482,7 +482,7 @@ void test() { try (var ac = Sabi.setup()) { suppressWarnings_unused(ac); try (var data = new SampleDataHub()) { - Sabi.txn(new SampleLogic(), data); + data.txn(new SampleLogic()); } catch (Exception e) { fail(e); } @@ -533,7 +533,7 @@ void test() { data.uses("foo", new FooDataSrc(1, "Hello", logger, false)); data.uses("bar", new BarDataSrc(2, logger, false)); - Sabi.txn(new SampleLogic(), data); + data.txn(new SampleLogic()); } catch (Exception e) { fail(e); } @@ -571,7 +571,7 @@ void test_not_run_logic_if_fail_to_setup_local_data_src() { data.uses("foo", new FooDataSrc(1, "Hello", logger, true)); data.uses("bar", new BarDataSrc(2, logger, false)); - Sabi.txn(new SampleLogic(), data); + data.txn(new SampleLogic()); } catch (Err e) { switch (e.getReason()) { case DataHub.FailToSetupLocalDataSrcs r -> { @@ -600,7 +600,7 @@ void test_not_run_logic_in_txn_and_rollback() { data.uses("foo", new FooDataSrc(1, "Hello", logger, false)); data.uses("bar", new BarDataSrc(2, logger, false)); - Sabi.txn(new FailingLogic(), data); + data.txn(new FailingLogic()); } catch (Err e) { assertThat(e.getReason()).isEqualTo("ZZZ"); } catch (Exception e) { @@ -643,7 +643,7 @@ void test() { try (var data = new SampleDataHub()) { data.uses("foo", new FooDataSrc(2, "Hello", logger, false)); - Sabi.txn(new SampleLogic(), data); + data.txn(new SampleLogic()); } catch (Exception e) { fail(e); }