diff --git a/cj-btc-jsonrpc/src/main/java/org/consensusj/bitcoin/jsonrpc/BitcoinClient.java b/cj-btc-jsonrpc/src/main/java/org/consensusj/bitcoin/jsonrpc/BitcoinClient.java index 5fab27af1..d8e58e2a6 100644 --- a/cj-btc-jsonrpc/src/main/java/org/consensusj/bitcoin/jsonrpc/BitcoinClient.java +++ b/cj-btc-jsonrpc/src/main/java/org/consensusj/bitcoin/jsonrpc/BitcoinClient.java @@ -31,7 +31,7 @@ import org.consensusj.bitcoin.json.pojo.bitcore.AddressRequest; import org.consensusj.bitcoin.json.pojo.bitcore.AddressUtxoInfo; import org.consensusj.bitcoin.jsonrpc.internal.BitcoinClientThreadFactory; -import org.consensusj.jsonrpc.JsonRpcClientJavaNet; +import org.consensusj.jsonrpc.DefaultRpcClient; import org.consensusj.jsonrpc.JsonRpcError; import org.consensusj.jsonrpc.JsonRpcErrorException; import org.consensusj.jsonrpc.JsonRpcException; @@ -104,7 +104,7 @@ * This is still a work-in-progress and the API will change. * */ -public class BitcoinClient extends JsonRpcClientJavaNet implements ChainTipClient { +public class BitcoinClient extends DefaultRpcClient implements ChainTipClient { private static final Logger log = LoggerFactory.getLogger(BitcoinClient.class); private static final int THREAD_POOL_SIZE = 5; diff --git a/cj-btc-rx-jsonrpc/src/main/java/org/consensusj/bitcoin/rx/jsonrpc/service/TxOutSetService.java b/cj-btc-rx-jsonrpc/src/main/java/org/consensusj/bitcoin/rx/jsonrpc/service/TxOutSetService.java index 1348dc55b..e7aab5907 100644 --- a/cj-btc-rx-jsonrpc/src/main/java/org/consensusj/bitcoin/rx/jsonrpc/service/TxOutSetService.java +++ b/cj-btc-rx-jsonrpc/src/main/java/org/consensusj/bitcoin/rx/jsonrpc/service/TxOutSetService.java @@ -8,8 +8,9 @@ import org.consensusj.bitcoin.json.pojo.ChainTip; import org.consensusj.bitcoin.json.pojo.TxOutSetInfo; import org.consensusj.bitcoin.rx.jsonrpc.RxBitcoinClient; -import org.consensusj.jsonrpc.AbstractRpcClient; +import org.consensusj.jsonrpc.DefaultRpcClient; import org.consensusj.jsonrpc.AsyncSupport; +import org.consensusj.jsonrpc.DefaultRpcClient; import org.consensusj.rx.jsonrpc.RxJsonRpcClient; import org.reactivestreams.Publisher; import org.slf4j.Logger; @@ -71,7 +72,7 @@ private void onNewBlock(ChainTip tip) { } // TODO: Ignoring all IOError is too broad - AbstractRpcClient.TransientErrorFilter errorFilter = AsyncSupport.TransientErrorFilter.of( + DefaultRpcClient.TransientErrorFilter errorFilter = AsyncSupport.TransientErrorFilter.of( (t) -> t instanceof IOError, // Ignore if IOError (t) -> log.warn("Ignoring transient error: ", t) // Log if ignored ); diff --git a/cj-eth-jsonrpc/src/main/java/org/consensusj/ethereum/jsonrpc/EthereumClient.java b/cj-eth-jsonrpc/src/main/java/org/consensusj/ethereum/jsonrpc/EthereumClient.java index 3721ee4eb..b91f1f29c 100644 --- a/cj-eth-jsonrpc/src/main/java/org/consensusj/ethereum/jsonrpc/EthereumClient.java +++ b/cj-eth-jsonrpc/src/main/java/org/consensusj/ethereum/jsonrpc/EthereumClient.java @@ -1,8 +1,8 @@ package org.consensusj.ethereum.jsonrpc; +import org.consensusj.jsonrpc.DefaultRpcClient; import org.consensusj.jsonrpc.JsonRpcMessage; import org.consensusj.jsonrpc.JsonRpcStatusException; -import org.consensusj.jsonrpc.JsonRpcClientHttpUrlConnection; import java.io.IOException; import java.math.BigInteger; @@ -16,7 +16,7 @@ * See also: * https://github.com/ethereum/go-ethereum/wiki/Management-APIs */ -public class EthereumClient extends JsonRpcClientHttpUrlConnection { +public class EthereumClient extends DefaultRpcClient { public static final URI DEFAULT_LOCALHOST = URI.create("http://localhost:8545"); /** diff --git a/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/BaseJsonRpcTool.java b/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/BaseJsonRpcTool.java index c9f2c28ba..7578d1336 100644 --- a/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/BaseJsonRpcTool.java +++ b/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/BaseJsonRpcTool.java @@ -9,7 +9,7 @@ import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import org.consensusj.jsonrpc.AbstractRpcClient; +import org.consensusj.jsonrpc.DefaultRpcClient; import org.consensusj.jsonrpc.CompositeTrustManager; import org.consensusj.jsonrpc.JsonRpcClientJavaNet; import org.consensusj.jsonrpc.JsonRpcMessage; @@ -87,7 +87,7 @@ public void run(CommonsCLICall call) { jsonRpcVersion = JsonRpcMessage.Version.V1; } SSLContext sslContext = sslContext(call.line); - AbstractRpcClient client = call.rpcClient(sslContext); + DefaultRpcClient client = call.rpcClient(sslContext); CliParameterParser parser = new CliParameterParser(jsonRpcVersion, client.getMapper()); JsonRpcRequest request = parser.parse(args); JsonRpcResponse response; @@ -163,7 +163,7 @@ public static class CommonsCLICall extends JsonRpcClientTool.Call { protected final BaseJsonRpcTool rpcTool; public final CommandLine line; public final boolean verbose; - private AbstractRpcClient client; + private DefaultRpcClient client; public CommonsCLICall(BaseJsonRpcTool parentTool, PrintWriter out, PrintWriter err, String[] args) { super(out, err, args); @@ -202,7 +202,7 @@ public CommonsCLICall(BaseJsonRpcTool parentTool, PrintWriter out, PrintWriter e } @Override - public AbstractRpcClient rpcClient(SSLContext sslContext) { + public DefaultRpcClient rpcClient(SSLContext sslContext) { if (client == null) { URI uri; String urlString; @@ -223,13 +223,13 @@ public AbstractRpcClient rpcClient(SSLContext sslContext) { rpcUser = split[0]; rpcPassword = split[1]; } - client = new JsonRpcClientJavaNet(sslContext, rpcTool.jsonRpcVersion, uri, rpcUser, rpcPassword); + client = new DefaultRpcClient(sslContext, rpcTool.jsonRpcVersion, uri, rpcUser, rpcPassword); } return client; } @Override - public AbstractRpcClient rpcClient() { + public DefaultRpcClient rpcClient() { SSLContext sslContext; try { sslContext = SSLContext.getDefault(); diff --git a/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/JsonRpcClientTool.java b/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/JsonRpcClientTool.java index c009a5277..ba2d8449d 100644 --- a/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/JsonRpcClientTool.java +++ b/consensusj-jsonrpc-cli/src/main/java/org/consensusj/jsonrpc/cli/JsonRpcClientTool.java @@ -1,6 +1,6 @@ package org.consensusj.jsonrpc.cli; -import org.consensusj.jsonrpc.AbstractRpcClient; +import org.consensusj.jsonrpc.DefaultRpcClient; import javax.net.ssl.SSLContext; import java.io.OutputStreamWriter; @@ -51,8 +51,8 @@ public Call(PrintWriter out, PrintWriter err, String[] args) { this.args = args; } - abstract public AbstractRpcClient rpcClient(); - abstract public AbstractRpcClient rpcClient(SSLContext sslContext); + abstract public DefaultRpcClient rpcClient(); + abstract public DefaultRpcClient rpcClient(SSLContext sslContext); } class ToolException extends RuntimeException { diff --git a/consensusj-jsonrpc-gvy/src/main/groovy/org/consensusj/jsonrpc/groovy/DynamicRpcClient.groovy b/consensusj-jsonrpc-gvy/src/main/groovy/org/consensusj/jsonrpc/groovy/DynamicRpcClient.groovy index 03013af01..ca035eb7c 100644 --- a/consensusj-jsonrpc-gvy/src/main/groovy/org/consensusj/jsonrpc/groovy/DynamicRpcClient.groovy +++ b/consensusj-jsonrpc-gvy/src/main/groovy/org/consensusj/jsonrpc/groovy/DynamicRpcClient.groovy @@ -1,6 +1,6 @@ package org.consensusj.jsonrpc.groovy -import org.consensusj.jsonrpc.JsonRpcClientJavaNet +import org.consensusj.jsonrpc.DefaultRpcClient import org.consensusj.jsonrpc.JsonRpcMessage import com.fasterxml.jackson.databind.JavaType; @@ -16,7 +16,7 @@ import com.fasterxml.jackson.databind.JavaType; * This client and the {@link DynamicRpcMethodFallback} trait are provided for those looking for something simple, * flexible, dynamic, and Groovy. */ -class DynamicRpcClient extends JsonRpcClientJavaNet implements DynamicRpcMethodFallback { +class DynamicRpcClient extends DefaultRpcClient implements DynamicRpcMethodFallback { DynamicRpcClient(URI server, String rpcuser, String rpcpassword) { this(JsonRpcMessage.Version.V2, server, rpcuser, rpcpassword) diff --git a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AsyncSupport.java b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AsyncSupport.java index ede2b9855..5a9c745c5 100644 --- a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AsyncSupport.java +++ b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AsyncSupport.java @@ -12,7 +12,7 @@ /** * Helper methods for creating asynchronous calls using {@link CompletableFuture}. Since the - * synchronous methods in {@link AbstractRpcClient} throw checked exceptions this interface + * synchronous methods in {@link DefaultRpcClient} throw checked exceptions this interface * provides wrapper support to make it easier to convert them to async calls. */ public interface AsyncSupport { @@ -129,7 +129,7 @@ static TransientErrorFilter none() { /** * Handler to transpose to a "future maybe". Use with {@link CompletableFuture#handle(BiFunction)} - * followed by {@code .thenCompose(Function.identity())} (or if JDK 12+ {@link CompletableFuture#exceptionallyCompose(Function)}) + * followed by {@code .thenCompose(Function.identity())} (or if JDK 12+ {@code CompletableFuture#exceptionallyCompose(Function)}) * to swallow transient errors. * @param result T * @param t An error, possibly transient diff --git a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AbstractRpcClient.java b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/DefaultRpcClient.java similarity index 82% rename from consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AbstractRpcClient.java rename to consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/DefaultRpcClient.java index 961152443..8d6838789 100644 --- a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/AbstractRpcClient.java +++ b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/DefaultRpcClient.java @@ -7,7 +7,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.SSLContext; +import java.lang.reflect.Type; import java.time.Duration; +import java.net.URI; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -15,24 +18,16 @@ import java.util.function.Function; import java.util.function.Supplier; -// TODO: Rather than implementing transport (HttpUrlConnection vs. java.net.http) with subclasses use composition -// In other words, the constructor should take a transport implementation object. +// TODO: the constructor should take a JsonRpcTransport implementation object. +// We now have DefaultRpcClient which is currently hard-coded to use the JavaNet transport (1-line change + recompile to switch) + // We're overusing inheritance in this hierarchy. We are breaking Effective Java, Item 18: Favor composition over inheritance. // We're using inheritance to configure: // A. The set of JSON-RPC methods that are supported, e.g. `getblockcount()` (which creates potential conflicts with `send()` etc) // B. The JSON mapping implementation. Which for now and the foreseeable future is Jackson only. -// C. The transport implementation. // -// As we want to support both HttpUrlConnection vs. java.net.http while transitioning to java.net.http, we don't want to force -// subclasses like `BitcoinClient` to choose one or the other. So making (C) transport implementation a separate, composable object -// is the FIRST STEP. Later we can look at separating (A) and (B). My first thoughts on how to do this is: -// (1) Create a JsonRpcClientTransport interface. -// (2) Rename `AbstractRpcClient` to `DefaultJsonRpcClient`, make it concrete and have it take a JsonRpcClientTransport instance as -// a constructor parameter. -// (3) Create two implementations of `JsonRpcClientTransport` based upon `JsonRpcClientHttpUrlConnection` and `JsonRpcClientJavaNet`. -// (4) Optional. Maybe look at extracting a class with some common "mapper" functions between the two transport implementations +// TODO: Maybe look at extracting a class with some common "mapper" functions between the two transport implementations // -// To separate (C) the easiest way is probably via a constructor parameter. // The proper separation for (A) is probably a complete separation. There should be no required inheritance to implement // a client with a set of methods. Internally the client would have a transport and a mapper and those could optionally be made available // via some accessor methods if the client application deems necessary. @@ -42,22 +37,21 @@ // (1) Map Java method name and parameters to a JSON-RPC request (either map to set of Java Objects _or_ all the way to JSON) // (2) Map from received JSON-RPC response to JsonRpcResponse -- this response mapper function is configured as part of making the request. // -// The SECOND STEP is to abstract the specifics of Jackson from the (two) transport implementations. Basically methods/functions to +// To abstract the specifics of Jackson from the (two) transport implementations. Basically methods/functions to // map from request to string/stream and to map from string/stream to response. The java.net.http implementation has already defined // some functional interfaces for this, so coming up with an interface that both the java.net.http implementation and the HttpUrlConnection // implementation can use will lead to this "SECOND STEP" // -// Update: Now that JsonRpcClient is a generic with , we have loosened the Jackson coupling somewhat. The sendRequestForResponse -// and sendRequestForResponseAsync methods from JsonRpcClient have been moved to the JsonRpcTransport class which the JavaNet and HttpUrlConnection -// flavors implement. The AbstractRpcClient constructor should be passed an instance of either transport class and forward methods calls for -// sendRequestForResponseAsync (and sendRequestForResponse ?) to the transport. +// Now that JsonRpcClient is a generic with , we have loosened the Jackson coupling somewhat. +// /** - * Abstract Base class for a strongly-typed, Jackson-based JSON-RPC client. This abstract class implements the constructors, static fields, and - * getters, but leaves the core {@code sendRequestForResponse} method as {@code abstract} to be implemented by subclasses - * allowing implementation with alternative HTTP client libraries. + * A strongly-typed, Jackson-based JSON-RPC client. {@link JsonRpcClient} provides many convenience send `default` methods in a + * JSON-library-independent way. DefaultRpcClient provides the needed implementation support for Jackson. This class implements + * the constructors, static fields, and getters, but delegates the core + * {@link JsonRpcTransport#sendRequestForResponseAsync(JsonRpcRequest, Type)} method to a {@link JsonRpcTransport} implementation component. */ -public abstract class AbstractRpcClient implements JsonRpcClient { - private static final Logger log = LoggerFactory.getLogger(AbstractRpcClient.class); +public class DefaultRpcClient implements JsonRpcClient { + private static final Logger log = LoggerFactory.getLogger(DefaultRpcClient.class); /** * The default JSON-RPC version in JsonRpcRequest is now '2.0', but since most * requests are created inside {@code RpcClient} subclasses, we'll continue to default @@ -68,13 +62,22 @@ public abstract class AbstractRpcClient implements JsonRpcClient { protected final JsonRpcMessage.Version jsonRpcVersion; protected final ObjectMapper mapper; private final JavaType defaultType; + private final JsonRpcTransport transport; - public AbstractRpcClient(JsonRpcMessage.Version jsonRpcVersion) { + public DefaultRpcClient(JsonRpcMessage.Version jsonRpcVersion, URI server, final String rpcUser, final String rpcPassword) { + this(JsonRpcTransport.getDefaultSSLContext(), jsonRpcVersion, server, rpcUser, rpcPassword); + } + public DefaultRpcClient(SSLContext sslContext, JsonRpcMessage.Version jsonRpcVersion, URI server, final String rpcUser, final String rpcPassword) { this.jsonRpcVersion = jsonRpcVersion; mapper = new ObjectMapper(); // TODO: Provide external API to configure FAIL_ON_UNKNOWN_PROPERTIES mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); defaultType = mapper.getTypeFactory().constructType(Object.class); + // TODO: Right now you can manually switch between JsonRpcClientJavaNet and JsonRpcClientHttpUrlConnection by + // commenting out one line or the other and recompiling. There needs to be a new constructor which will + // allow the default (JsonRpcClientJavaNet) to be overridden. + transport = new JsonRpcClientJavaNet(mapper, sslContext, server, rpcUser, rpcPassword); + //transport = new JsonRpcClientHttpUrlConnection(mapper, sslContext, server, rpcUser, rpcPassword); } @Override @@ -82,6 +85,16 @@ public JsonRpcMessage.Version getJsonRpcVersion() { return jsonRpcVersion; } + @Override + public URI getServerURI() { + return transport.getServerURI(); + } + + @Override + public CompletableFuture> sendRequestForResponseAsync(JsonRpcRequest request, JavaType responseType) { + return transport.sendRequestForResponseAsync(request, responseType); + } + /** * Convenience method for requesting an asynchronous response with a {@link JsonNode} for the result. * @param request The request to send diff --git a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnection.java b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnection.java index 8d81df1b0..f4e1feb3d 100644 --- a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnection.java +++ b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnection.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,16 +30,17 @@ * using intermediate `Map` or `JsonNode` types. * */ -public class JsonRpcClientHttpUrlConnection extends AbstractRpcClient { +public class JsonRpcClientHttpUrlConnection implements JsonRpcTransport { private static final Logger log = LoggerFactory.getLogger(JsonRpcClientHttpUrlConnection.class); + private final ObjectMapper mapper; private final URI serverURI; private final String username; private final String password; private static final String UTF8 = StandardCharsets.UTF_8.name(); private final SSLSocketFactory sslSocketFactory; - public JsonRpcClientHttpUrlConnection(SSLContext sslContext, JsonRpcMessage.Version jsonRpcVersion, URI server, final String rpcUser, final String rpcPassword) { - super(jsonRpcVersion); + public JsonRpcClientHttpUrlConnection(ObjectMapper mapper, SSLContext sslContext, URI server, final String rpcUser, final String rpcPassword) { + this.mapper = mapper; this.sslSocketFactory = sslContext.getSocketFactory(); log.debug("Constructing JSON-RPC client for: {}", server); this.serverURI = server; @@ -46,18 +48,6 @@ public JsonRpcClientHttpUrlConnection(SSLContext sslContext, JsonRpcMessage.Vers this.password = rpcPassword; } - /** - * Construct a JSON-RPC client from URI, username, and password - * - * @param jsonRpcVersion version for {@code jsonrpc} field in messages - * @param server server URI should not contain username/password - * @param rpcUser username for the RPC HTTP connection - * @param rpcPassword password for the RPC HTTP connection - */ - public JsonRpcClientHttpUrlConnection(JsonRpcMessage.Version jsonRpcVersion, URI server, final String rpcUser, final String rpcPassword) { - this(JsonRpcTransport.getDefaultSSLContext(), jsonRpcVersion, server, rpcUser, rpcPassword); - } - /** * Get the URI of the server this client connects to * @return Server URI @@ -182,4 +172,9 @@ private HttpURLConnection openConnection() throws IOException { return connection; } + + private JavaType responseTypeFor(Class resultType) { + return mapper.getTypeFactory(). + constructParametricType(JsonRpcResponse.class, resultType); + } } diff --git a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientJavaNet.java b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientJavaNet.java index dec91b1ce..7756cf764 100644 --- a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientJavaNet.java +++ b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcClientJavaNet.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,8 +22,10 @@ /** * Incubating JSON-RPC client using {@link java.net.http.HttpClient} */ -public class JsonRpcClientJavaNet extends AbstractRpcClient { +public class JsonRpcClientJavaNet implements JsonRpcTransport { private static final Logger log = LoggerFactory.getLogger(JsonRpcClientJavaNet.class); + + private final ObjectMapper mapper; private final URI serverURI; private final String username; private final String password; @@ -30,13 +33,13 @@ public class JsonRpcClientJavaNet extends AbstractRpcClient { private static final String UTF8 = StandardCharsets.UTF_8.name(); - public JsonRpcClientJavaNet(JsonRpcMessage.Version jsonRpcVersion, URI server, final String rpcUser, final String rpcPassword) { - this(JsonRpcTransport.getDefaultSSLContext(), jsonRpcVersion, server, rpcUser, rpcPassword); + public JsonRpcClientJavaNet(ObjectMapper mapper, URI server, final String rpcUser, final String rpcPassword) { + this(mapper, JsonRpcTransport.getDefaultSSLContext(), server, rpcUser, rpcPassword); } - public JsonRpcClientJavaNet(SSLContext sslContext, JsonRpcMessage.Version jsonRpcVersion, URI server, final String rpcUser, final String rpcPassword) { - super(jsonRpcVersion); + public JsonRpcClientJavaNet(ObjectMapper mapper, SSLContext sslContext, URI server, final String rpcUser, final String rpcPassword) { log.debug("Constructing JSON-RPC client for: {}", server); + this.mapper = mapper; this.serverURI = server; this.username = rpcUser; this.password = rpcPassword; @@ -46,10 +49,6 @@ public JsonRpcClientJavaNet(SSLContext sslContext, JsonRpcMessage.Version jsonRp .build(); } - public JsonRpcClientJavaNet(URI server, final String rpcUser, final String rpcPassword) { - this(JsonRpcMessage.Version.V2, server, rpcUser, rpcPassword); - } - /** * {@inheritDoc} */ @@ -219,4 +218,9 @@ private void log(String s, Throwable t) { log.warn("exception: ", t); } } + + private JavaType responseTypeFor(Class resultType) { + return mapper.getTypeFactory(). + constructParametricType(JsonRpcResponse.class, resultType); + } } diff --git a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcTransport.java b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcTransport.java index 72b528b39..6832fcb32 100644 --- a/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcTransport.java +++ b/consensusj-jsonrpc/src/main/java/org/consensusj/jsonrpc/JsonRpcTransport.java @@ -10,8 +10,6 @@ import java.util.concurrent.ExecutionException; import java.util.function.Supplier; -// TODO: Have JsonRpcClientJavaNet and JsonRpcClientHttpUrlConnection directly implement this class -// and AbstractRpcClient become DefaultRpcClient and take a transport instance in its constructor. /** * Defines the interface for a network-layer implementation of a JSON-RPC client. */ @@ -74,8 +72,6 @@ default R syncGet(CompletableFuture future) throws IOException, JsonRpcEx } } - - /** * Encode username password as Base64 for basic authentication *

@@ -100,5 +96,4 @@ static SSLContext getDefaultSSLContext() { throw new RuntimeException(e); } } - } diff --git a/consensusj-jsonrpc/src/test/groovy/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnectionSpec.groovy b/consensusj-jsonrpc/src/test/groovy/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnectionSpec.groovy index c749d2680..c7d75d184 100644 --- a/consensusj-jsonrpc/src/test/groovy/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnectionSpec.groovy +++ b/consensusj-jsonrpc/src/test/groovy/org/consensusj/jsonrpc/JsonRpcClientHttpUrlConnectionSpec.groovy @@ -12,11 +12,11 @@ class JsonRpcClientHttpUrlConnectionSpec extends Specification { def "constructor works correctly" () { when: - def client = new JsonRpcClientHttpUrlConnection(JsonRpcMessage.Version.V2, "http://localhost:8080".toURI(), "user", "pass") + def client = new JsonRpcClientHttpUrlConnection(null, JsonRpcTransport.getDefaultSSLContext(), "http://localhost:8080".toURI(), "user", "pass") then: client.serverURI == "http://localhost:8080".toURI() - client.getJsonRpcVersion() == JsonRpcMessage.Version.V2 + //client.getJsonRpcVersion() == JsonRpcMessage.Version.V2 } @Unroll diff --git a/consensusj-rx-jsonrpc/src/main/java/org/consensusj/rx/jsonrpc/RxJsonRpcClient.java b/consensusj-rx-jsonrpc/src/main/java/org/consensusj/rx/jsonrpc/RxJsonRpcClient.java index 4e8ded5f0..75410bb1b 100644 --- a/consensusj-rx-jsonrpc/src/main/java/org/consensusj/rx/jsonrpc/RxJsonRpcClient.java +++ b/consensusj-rx-jsonrpc/src/main/java/org/consensusj/rx/jsonrpc/RxJsonRpcClient.java @@ -3,7 +3,7 @@ import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.core.Maybe; import io.reactivex.rxjava3.core.Single; -import org.consensusj.jsonrpc.AbstractRpcClient; +import org.consensusj.jsonrpc.DefaultRpcClient; import org.consensusj.jsonrpc.AsyncSupport; import org.reactivestreams.Publisher; import org.slf4j.Logger; @@ -18,7 +18,7 @@ /** * RxJava support for calling JSON-RPC clients. Extend/implement this interface to inherit {@code default} methods - * {@link #call(ThrowingSupplier)}, {@link #defer(Supplier)}, and {@link #pollOnceAsPublisher(Supplier, AbstractRpcClient.TransientErrorFilter)}. + * {@link #call(ThrowingSupplier)}, {@link #defer(Supplier)}, and {@link #pollOnceAsPublisher(Supplier, DefaultRpcClient.TransientErrorFilter)}. */ public interface RxJsonRpcClient extends AsyncSupport { Logger log = LoggerFactory.getLogger(RxJsonRpcClient.class); @@ -59,7 +59,7 @@ static Single defer(Supplier> supplier) { * @return A publisher of a "cold" stream of items (temporarily Flowable, but will change to Publisher, then Flow.Publisher) * @param result type */ - default Flowable pollOnceAsPublisher(Supplier> supplier, AbstractRpcClient.TransientErrorFilter filter) { + default Flowable pollOnceAsPublisher(Supplier> supplier, DefaultRpcClient.TransientErrorFilter filter) { return Flowable.defer(() -> Flowable.fromCompletionStage(supplier.get() .handle(filter::handle) .thenCompose(Function.identity())))