Skip to content

mgtsai/promises-aplus-java

Repository files navigation

promises-aplus-java

Implementation of Promises/A+ in Java, plus various language sugars for programming. Java 6 or higher is required.

Features

  • Supports Promises/A+ specification, including thenable interface
  • One of three separated interface sets can be chosen for coding
    • Untyped: Promise class without Java Generics
    • Typed: Promise class with Java Generics
    • Light-weight: Short naming, and uses Throwable-only promise rejected reasons, suitable for cleaner codes
  • Supports Java 8 Lambda
  • Supports pre-built multi-argument (up to 5 arguments) fulfilled values (or rejected reasons) passing amount .then() method chaining
  • Can specify certain callbacks running on the specific java.util.concurrent.Executor context, which generally be different threads, even can be RPC calls by implementing the Executor interface
  • Utility methods convenient to switch between synchronous and asynchronous programming models
  • (Not supported yet) Supports asynchronous sequential/parallel flow controls, such as if-then-else, switch-case, while, for, ...
  • (Not supported yet) Promise causality logging for deep debugging/inspecting runtime execution sequences

Brief examples

Using Untyped Interface Set

import static promises.Promises.pf;
...
pf(null)                        // Returns fulfilled promises.Promise with null value
.then(dummy -> {
    ...
    return "msg";
})                              // Return type: promises.Promise
.then(
    (String msg) -> {           // Since promises.Promise has no type parameter, this lambda should specify the explicit argument type: String 
        ...
        return 123;
    },
    (reason, exception) -> {    // Type of argument 'exception': Throwable
        ...
        return 456;
    }
)                               // Return type: promises.Promise
.then((Integer num) -> {        // Since promises.Promise has no type parameter, this lambda should specify the explicit argument type: Integer
    ...
});

Using Typed Interface Set

import static promises.typed.Promises.pf;
import static promises.typed.Promises.v;
...
pf(null)                        // Returns fulfilled promises.typed.Promise<Object, Object> with null value
.then(dummy -> {
    ...
    return v("msg");
})                              // Return type: promises.typed.Promise<String, Object>
.then(
    msg -> {                    // Type of argument 'msg': String
        ...
        return v(123);
    },
    (reason, exception) -> {    // Type of argument 'reason': Object
        ...
        return v(456);
    }
)                               // Return type: promises.typed.Promise<Integer, Object>
.then(num -> {                  // Type of argument 'num': Integer
    ...
});

Using Light-weight Interface Set

For simplicity, light-weight promise objects do not contain rejection reasons (only contain Throwable objects) to avoid specifying reason type parameter.

import static promises.lw.Promises.pf;
import static promises.lw.Promises.v;
...
pf(null)                        // Returns fulfilled promises.lw.P<Object> with null value
.then(dummy -> {
    ...
    return v("msg");
})                              // Return type: promises.lw.P<String>
.then(
    msg -> {                    // Type of argument 'msg': String
        ...
        return v(123);
    },
    exception -> {              // Contains throwable-only argument for rejection
        ...
        return v(456);
    }
)                               // Return type: promises.lw.P<Integer>
.then(num -> {                  // Type of argument 'num': Integer
    ...
});

Multi-argument callbacks

import static promises.typed.Promises.pf;
import static promises.typed.Promises.r;
import static promises.typed.Promises.v;
import static promises.typed.Promises.wf;
import static promises.typed.Promises.wr;
...
pf(null)
.then(dummy -> {
    ...
    if (correct)
        return v("msg", 123);               // Fulfilled with ("msg", 123)
    else
        return r(404, "Not found", null);   // Rejected with (404, "Not found"), null Throwable
})
.then(
    wf((msg, num) -> {                      // Types of arguments: (String, Integer)
        ...
    }),
    wr((code, err, exception) -> {          // Types of arguments: (Integer, String, Throwable)
        ...
    })
);

Waits for promises being resolved (fulfilled or rejected)

import static promises.typed.Promises.pf;
...
pf(null)
.then(...)
.then(...)
...
.then(...)
.await(60, TimeUnit.SECONDS);       // Waits for the overall promise chain being resolved
                                    // When the chaining promise is fulfilled, the value would be returned
                                    // When the chaining promise is rejected, promises.PromiseRejectedException containing rejected reason/exception would be thrown
                                    // After 60 seconds without resolving, java.util.concurrent.TimeoutException would be thrown

Executes a synchronous method (i.e. JDBC operations) on an Executor (Thread)

import static promises.typed.Promises.async;
import static java.sql.Connection;
import static java.sql.PreparedStatement;
import static java.sql.ResultSet;
import static java.util.concurrent.Executor;
import static java.util.concurrent.Executors;
...
Executor exec = Executors.newSingleThreadExecutor(thread);

async(exec, () -> {
    ...
    Connection conn = dataSource.getConnection();
    PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
    stmt.setString(1, "UserName");
    ResultSet rs = stmt.executeQuery();
    ...
    return "msg";
})
.then(
    msg -> {                    // When the synchronous callback successfully returns, the promise would be fulfilled with the returned value
        ...
    },
    (reason, exception) -> {    // When an exception is thrown in the synchronous callback, the promise would be rejected with the thrown exception
        ...
    }
);

About

Implementation of Promises/A+ in Java

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages