# About the Async HTTP Client
The "moleculer-java-httpclient" is an asynchronous HTTP client API, specially designed for Java-based Moleculer Ecosystem. The client is suitable for handling large numbers of REST requests, and it can receive WebSocket messages from a Netty/J2EE-based Moleculer application. The built-in Heartbeat function automatically checks if a connection has been lost. If a connection is lost, the client automatically rebuilds the connection.
# Download
Maven
<dependencies>
<dependency>
<groupId>com.github.berkesa</groupId>
<artifactId>moleculer-java-httpclient</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
Gradle
dependencies {
implementation group: 'com.github.berkesa', name: 'moleculer-java-httpclient', version: '1.0.0'
}
# Examples
# Blocking usage
Blocking is not recommended, but you can use the "waitFor" method to wait for the server response if necessary. The Tree object is practically a JSON structure. Its contents can be retrieved using "get" function calls, as in a "Map" object.
Tree rsp = client.get("http://host/rest").waitFor();
# Invoking a REST service
In the example below, we call a REST service that provides a JSON response to a JSON request.
// Create HTTP client (connection pool and timeout handler)
HttpClient client = new HttpClient();
client.start();
// Build JSON request
Tree req = new Tree();
req.put("key1", "value1");
req.put("key2", 123);
req.put("key3", true);
client.post("http://host/path", req).then(rsp -> {
// Success (process JSON response)
String value4 = rsp.get("key4", "defaultValue");
}).catchError(err -> {
// Failed
err.printStackTrace();
});
# Invoking with custom parameters
client.get("http://host/rest", params -> {
// Set parameters of the request
params.addHeader("HttpHeader", "value");
params.setCharset(StandardCharsets.ISO_8859_1);
}).then(rsp -> {
// Parsing response ("rsp" is a "Tree" object)
System.out.println(rsp.get("key", "defaultValue"));
});
# Receiving WebSocket messages
In the following case, the client connects to the server immediately. The heartbeat timer checks the connection every minute.
client.ws("http://localhost:3000/ws/jmx", payload -> {
// Message received!
System.out.println("RECEIVED: " + payload);
});
# WebSocket connection events
In the example below, you can create your own event listeners for the WebSocket connection and also specify connection parameters.
WebSocketConnection ws =
client.ws("http://localhost:3000/ws/jmx", new WebSocketHandler() {
public void onOpen(WebSocket webSocket) {
// WebSocket connection opened
}
public void onMessage(Tree payload) {
// Receiving message
System.out.println("RECEIVED:\r\n" + payload);
}
public void onError(Throwable t) {
// Error occured
}
public void onClose(WebSocket webSocket, int code, String reason) {
// WebSocket connection closed
}
}, params -> {
// Set connection parameters
params.setHeader("HttpHeaderName", "value");
params.setHeartbeatInterval(120); // 2 mins
}, false);
// Connect to server
ws.connect();
// Close connection
ws.disconnect();
# Redirecting response
The 'transferTo' method is used to redirect the response to an OutputStream, WritableByteChannel or PacketStream.
// Create OutputStream
FileOutputStream out = new FileOutputStream("/target.txt");
client.get("http://host/path", params -> {
// Redirect response into OutputStream
params.transferTo(out);
}).then(rsp -> {
// Transfer finished
});
# Receiving "raw" response
As a result of the "returnAsByteArray" method, the client API will not attempt to process the response as JSON, but will return it in raw byte-array format.
client.get("http://host/path", params -> {
// Do not parse the response
params.returnAsByteArray();
}).then(rsp -> {
// Get response body
byte[] bytes = rsp.asBytes();
});
# Status code and headers
The "returnStatusCode" and "returnHttpHeaders" methods cause the client API to copy the status code and http headers into the "meta" block of the response Tree.
client.get("http://host/path", params -> {
// Instructs the client to copy the values
// into the "meta" block
params.returnStatusCode();
params.returnHttpHeaders();
}).then(rsp -> {
// Get status code
Tree meta = rsp.getMeta();
int status = meta.get("$status", 0);
// Get headers
for (Tree header: meta.get("$headers")) {
String headerName = header.getName();
String headerValue = header.asString();
}
});
# Upload a file
The "setBody" method is used to send files or Stream content to the server.
// Source file to upload
File file = new File("/source.bin");
client.post("http://host/path", params -> {
// Set body
params.setBody(file);
}).then(rsp -> {
// File uploaded
});
# Streaming with PacketStreams
PacketStreams provide low-level push-to-data delivery. It allows you to redirect responses of other Moleculer Actions directly to the HTTP request stream (or you can open an online media stream to the server for live microphone audio recording, etc.).
// The "broker" is a Moleculer Service Broker
ServiceBroker broker = new ServiceBroker();
// ...
broker.start();
// Create PacketStream
PacketStream stream = broker.createStream();
// Start sending...
client.post("http://host/path", stream);
stream.sendData("packet1".getBytes());
stream.sendData("packet2".getBytes());
stream.sendData("packet3".getBytes());
stream.sendClose();