Retrofit 2.0 value from asynch thread - java

I am new into threads. And the question is: Is this correct way to extract values from async Retrofit thread. And why dont I get "0 code exit"?
Here is main code
import com.google.gson.GsonBuilder;
import iceandfire.Callbacks.RootCallback;
import iceandfire.Models.Root;
import iceandfire.Utils.IceFireClient;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class Main implements RootCallback
{
public static void main(String [] args)
{
RequestRoot(new Main());
//this imitates UI thread
Thread thread = new Thread()
{
public void run()
{
int counter = 5;
while (counter >= 0)
{
System.out.println("I am not retrofit Call");
counter -= 1;
try
{
Thread.sleep(1000); // 1 second
} catch (Exception e)
{
e.printStackTrace();
}
}
}
};
thread.start();
}
public static void RequestRoot(final RootCallback rootCallback)
{
Retrofit.Builder retroBuilder = new Retrofit.Builder()
.baseUrl("https://anapioficeandfire.com/")
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = retroBuilder.build();
IceFireClient client = retrofit.create(IceFireClient.class);
Call<Root> kall = client.root();
kall.enqueue(new Callback<Root>()
{
#Override
public void onResponse(Call<Root> call, Response<Root> response)
{
Root bloodyRoot = response.body();
rootCallback.onSuccess(bloodyRoot);
}
#Override
public void onFailure(Call<Root> call, Throwable t)
{
}
});
}
#Override
public void onSuccess(Root bloodyRoot)
{
System.out.println( new GsonBuilder().setPrettyPrinting().create().toJson(bloodyRoot).toString());
}
}
And callback
package iceandfire.Callbacks;
import iceandfire.Models.Root;
public interface RootCallback
{
void onSuccess(Root bloodyRoot);
}
What I expect is: 5x messages "I am not Retrofit call";Json that I get from iceandfireapi/root at any random time before, after, or between previous messages. And the last but not least ending of everything:"Process finished with exit code 0"
But what I get is an infinite loop: 5x messages, Json and NO exit message.
P.S. Timer thread is used to "imitate" some UI things. While retrofit is doing requests.

Related

get result from websocket async call in sync call with concurrency classes

In my Spring project I'm using websocket client (org.java_websocket.client.WebSocketClient) It's worked as fine, main problem is in my code I can to get result with onMessage method but it's Asyc and I need result in Sync caller, other websocket clients are similar behavior too
Async is basically working concept in websocket
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.extensions.IExtension;
import org.java_websocket.handshake.ServerHandshake;
import org.java_websocket.protocols.IProtocol;
import org.java_websocket.protocols.Protocol;
public class EmptyClient extends WebSocketClient {
private final static Draft_6455 draft = new Draft_6455(Collections.<IExtension>emptyList(), Collections.<IProtocol>singletonList(new Protocol("my-protocol")));
private String request = null, response = null;
public EmptyClient(String serverUri, String request) throws URISyntaxException {
super(new URI(serverUri), draft);
this.request = request;
setConnectionLostTimeout(3000);
connect();
}
#Override
public void onOpen(ServerHandshake handshakedata) {
send(request);
System.out.println("new connection opened");
}
#Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("closed with exit code " + code + " additional info: " + reason + " remote:" + remote);
}
#Override
public void onMessage(String message) {
this.response = message;
close();
}
#Override
public void onMessage(ByteBuffer message) {
System.out.println("received ByteBuffer");
}
#Override
public void onError(Exception ex) {
System.err.println("an error occurred:" + ex);
}
public String getResponse() {
return response;
}
public static void main(String[] args) throws URISyntaxException, ExecutionException, InterruptedException {
String res = new EmptyClient("ws://123.abc:8888/", "{\"command\":\"create\",\"id\":\"1234\"}").getResponse();
System.out.println("response : "+res);
}
}
at the frist I think I could to use Future<T> and ExecutorService but main problem is Future itself is Async and result by onMessage method is Async too
let me to show you how is changed my previous code :
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.extensions.IExtension;
import org.java_websocket.handshake.ServerHandshake;
import org.java_websocket.protocols.IProtocol;
import org.java_websocket.protocols.Protocol;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class EmptyClient extends WebSocketClient {
private final static Draft_6455 draft = new Draft_6455(Collections.<IExtension>emptyList(), Collections.<IProtocol>singletonList(new Protocol("my-protocol")));
private String request = null, response = null;
private ExecutorService executor = Executors.newSingleThreadExecutor();
public EmptyClient(String serverUri, String request) throws URISyntaxException {
super(new URI(serverUri), draft);
this.request = request;
setConnectionLostTimeout(3000);
connect();
}
#Override
public void onOpen(ServerHandshake handshakedata) {
send(request);
System.out.println("new connection opened");
}
#Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("closed with exit code " + code + " additional info: " + reason + " remote:" + remote);
executor.shutdown();
}
#Override
public void onMessage(String message) {
this.response = message;
close();
}
#Override
public void onMessage(ByteBuffer message) {
System.out.println("received ByteBuffer");
}
#Override
public void onError(Exception ex) {
System.err.println("an error occurred:" + ex);
}
public Future<String> getResponse() {
return executor.submit(() -> {
return response;
});
}
public static void main(String[] args) throws URISyntaxException, ExecutionException, InterruptedException {
Future<String> res = new EmptyClient("ws://123.abc:8888/", "{\"command\":\"create\",\"id\":\"1234\"}").getResponse();
System.out.println(res.isDone() + res.get());
}
}
I can not to use Future as return type of onMessage method because it's belong to WebSocketClient class that I used
we know by get method from Future class is right way to get result, if any method by Furter was exist that I could to call it in onMessage method when response is exposed then get method returned actual Furtur<String> Object but there is nothing to do, maybe another concurrency class or mixed technique are better to use
hence I call EmptyClient class in sync method and I need that result to produce something else, how can I to resolve it ? maybe other Concurrency API classes and or locker is there to use

Java Websocket closes immediately

I am trying to use TooTallNate's Java-Websocket to connect to OkCoin. I found this simple code example somewhere, but I can't get it to work. The connection is immediately closed and so the call mWs.send(...) throws a WebsocketNotConnectedException. I can't figure out why; so far I have found a number of similar questions, none of which have an answer.
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.json.JSONObject;
import java.net.URI;
import java.net.URISyntaxException;
public class TestApp {
public static void main(String[] args) {
try {
URI uri = new URI("wss://real.okcoin.cn:10440/websocket/okcoinapi");
final WebSocketClient mWs = new WebSocketClient(uri) {
#Override
public void onMessage(String message) {
JSONObject obj = new JSONObject(message);
}
#Override
public void onOpen(ServerHandshake handshake) {
System.out.println("opened connection");
}
#Override
public void onClose(int code, String reason, boolean remote) {
System.out.println("closed connection");
}
#Override
public void onError(Exception ex) {
ex.printStackTrace();
}
};
mWs.connect();
JSONObject obj = new JSONObject();
obj.put("event", "addChannel");
obj.put("channel", "ok_btccny_ticker");
mWs.send(obj.toString());
} catch (URISyntaxException e) {
System.err.println("URI not formatted correctly");
}
}
}
Use mWs.connectBlocking() instead of mWs.connect() with this it will not close automatically.
See

Netty server with open http connections limit

I'm new to Netty and I wrote based on an example I found a Netty http server, that keeps http connections open to send server-sent-events to the browser client.
Problem is that it only accepts up to about ~5 connections and after that blocks new connections. I googled and found most answers said to set SO_LOGBACK to a higher value. Tried different values and while I saw no difference. I even set it to MAX_INTEGER value and still had only 5 connections.
Server code (Using Netty version 4.1.6.Final):
package server;
import static io.netty.buffer.Unpooled.copiedBuffer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpVersion;
public class NettyHttpServer {
private ChannelFuture channel;
private final EventLoopGroup masterGroup;
public NettyHttpServer() {
masterGroup = new NioEventLoopGroup(100);
}
public void start() {
try {
final ServerBootstrap bootstrap = new ServerBootstrap().group(masterGroup)
.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer < SocketChannel > () {
#Override
public void initChannel(final SocketChannel ch) throws Exception {
ch.pipeline().addLast("codec", new HttpServerCodec());
ch.pipeline().addLast("aggregator", new HttpObjectAggregator(512 * 1024));
ch.pipeline().addLast("request", new ChannelInboundHandlerAdapter() {
#Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg)
throws Exception {
System.out.println(msg);
registerToPubSub(ctx, msg);
}
#Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.writeAndFlush(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.INTERNAL_SERVER_ERROR,
copiedBuffer(cause.getMessage().getBytes())));
}
});
}
}).option(ChannelOption.SO_BACKLOG, Integer.MAX_VALUE)
.childOption(ChannelOption.SO_KEEPALIVE, true);
channel = bootstrap.bind(8081).sync();
// channels.add(bootstrap.bind(8080).sync());
} catch (final InterruptedException e) {}
}
public void shutdown() {
masterGroup.shutdownGracefully();
try {
channel.channel().closeFuture().sync();
} catch (InterruptedException e) {}
}
private void registerToPubSub(final ChannelHandlerContext ctx, Object msg) {
new Thread() {
#Override
public void run() {
while (true) {
final String responseMessage = "data:abcdef\n\n";
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
copiedBuffer(responseMessage.getBytes()));
response.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/event-stream");
response.headers().set(HttpHeaders.Names.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
response.headers().set("Cache-Control", "no-cache");
ctx.writeAndFlush(response);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
}
public static void main(String[] args) {
new NettyHttpServer().start();
}
}
Client js code (I run it more than 5 times from my browser in different tabs, and the not all of them get:
var source = new EventSource("http://localhost:8081");
source.onmessage = function(event) {
console.log(event.data);
};
source.onerror= function(err){console.log(err); source.close()};
source.onopen = function(event){console.log('open'); console.log(event)}
You need to let the browser know that you are done sending the response, and for that you have three options.
Set a content length
Send it chunked
Close the connection when you are done
You aren't doing any of those. I suspect your browser is still waiting for the full response to each request you send, and is using a new connection for each request in your testing. After 5 requests your browser must be refusing to create new connections.
Another thing I noticed is that you are creating a new thread for each request in your server, and never letting it die. That will cause problems down the line as you try to scale. If you really want that code to run in a different thread then I suggest looking at overloaded methods for adding handlers to the pipeline; those should let you specify a thread pool to run them in.

Multiple messages on a Grizzly Websocket Connection

We are using Websockets from the Grizzly project and had expected that the implementation would allow multiple incoming messages over a connection to be processed at the same time. It appears that this is not the case or there is a configuration step that we have missed. To validate this I have created a modified echo test that delays in the onMessage after echoing the text. When a client sends multiple messages over the same connection the server always blocks until onMessage completes before processing a subsequent message. Is this the expected functionality?
The simplified server code is as follows:
package com.grorange.samples.echo;
import java.util.concurrent.atomic.AtomicBoolean;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.websockets.DataFrame;
import org.glassfish.grizzly.websockets.WebSocket;
import org.glassfish.grizzly.websockets.WebSocketAddOn;
import org.glassfish.grizzly.websockets.WebSocketApplication;
import org.glassfish.grizzly.websockets.WebSocketEngine;
public class Echo extends WebSocketApplication {
private final AtomicBoolean inMessage = new AtomicBoolean(false);
#Override
public void onClose(WebSocket socket, DataFrame frame) {
super.onClose(socket, frame);
System.out.println("Disconnected!");
}
#Override
public void onConnect(WebSocket socket) {
System.out.println("Connected!");
}
#Override
public void onMessage(WebSocket socket, String text) {
System.out.println("Server: " + text);
socket.send(text);
if (this.inMessage.compareAndSet(false, true)) {
try {
Thread.sleep(10000);
} catch (Exception e) {}
this.inMessage.set(false);
}
}
#Override
public void onMessage(WebSocket socket, byte[] bytes) {
socket.send(bytes);
if (this.inMessage.compareAndSet(false, true)) {
try {
Thread.sleep(Long.MAX_VALUE);
} catch (Exception e) {}
this.inMessage.set(false);
}
}
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.createSimpleServer("http://0.0.0.0", 8083);
WebSocketAddOn addOn = new WebSocketAddOn();
addOn.setTimeoutInSeconds(60);
for (NetworkListener listener : server.getListeners()) {
listener.registerAddOn(addOn);
}
WebSocketEngine.getEngine().register("", "/Echo", new Echo());
server.start();
Thread.sleep(Long.MAX_VALUE);
}
}
The simplified client code is:
Yes, it's expected.
The way to go is to pass message processing, inside onMessage, to a different thread.

Get different results using main and junit in java

When I tested a simple producer/consumer example, I got a very strange result as below.
If I used main() to test the following code, I'll get the correct and expected result.
But I only can get the 1st directory correctly, the remaining works were dropped by the JUnit.
What is the exact reason?
Working code:
import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.junit.Test;
public class TestProducerAndConsumer {
public static void main(String[] args) {
BlockingQueue<File> queue = new LinkedBlockingQueue<File>(1000);
new Thread(new FileCrawler(queue, new File("C:\\"))).start();
new Thread(new Indexer(queue)).start();
}
}
Bad Code:
import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.junit.Test;
public class TestProducerAndConsumer {
#Test
public void start2() {
BlockingQueue<File> queue = new LinkedBlockingQueue<File>(1000);
new Thread(new FileCrawler(queue, new File("C:\\"))).start();
new Thread(new Indexer(queue)).start();
}
}
Other function code:
import java.io.File;
import java.util.Arrays;
import java.util.concurrent.BlockingQueue;
public class FileCrawler implements Runnable {
private final BlockingQueue<File> fileQueue;
private final File root;
private int i = 0;
public FileCrawler(BlockingQueue<File> fileQueue, File root) {
this.fileQueue = fileQueue;
this.root = root;
}
#Override
public void run() {
try {
craw(root);
} catch (InterruptedException e) {
System.out.println("shit!");
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
private void craw(File file) throws InterruptedException {
File[] entries = file.listFiles();
//System.out.println(Arrays.toString(entries));
if (entries != null && entries.length > 0) {
for (File entry : entries) {
if (entry.isDirectory()) {
craw(entry);
} else {
fileQueue.offer(entry);
i++;
System.out.println(entry);
System.out.println(i);
}
}
}
}
public static void main(String[] args) throws InterruptedException {
FileCrawler fc = new FileCrawler(null, null);
fc.craw(new File("C:\\"));
System.out.println(fc.i);
}
}
import java.io.File;
import java.util.concurrent.BlockingQueue;
public class Indexer implements Runnable {
private BlockingQueue<File> queue;
public Indexer(BlockingQueue<File> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
while (true) {
indexFile(queue.take());
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void indexFile(File file) {
System.out.println("Indexing ... " + file);
}
}
Junit's presumably allowing the JVM & threads to terminate, once the test is finished -- thus your threads do not complete working.
Try waiting for the threads to 'join':
Thread crawlerThread = new Thread(new FileCrawler(queue, new File("C:\\")));
Thread indexerThread = new Thread(new Indexer(queue));
crawlerThread.start();
indexerThread.start();
//
// wait for them to finish.
crawlerThread.join();
indexerThread.join();
This should help.
.. The other thing that can go wrong, is that log output (via Log4J) can sometimes be truncated at the end of execution; flushing & pausing can help. But I don't think that will affect you here.

Categories