Java implementation to handle callback messages - java

I have the following situation I need to handle in my code:
public class Class1 {
IRequester requester;
public Class1(Requester impl) {
requester = impl;
}
public List doSomething() {
requester.request1(); // sends messages to a set of nodes
//do some more local processing
list = requester.request2(); // sends some more messages and returns a list
return list;
}
}
In this case request1() sends a request to a set of nodes and returns a result which will be used locally for more processing, and then the request2() is made which returns a list. This needs to be returned at the end of execution of doSomething(). request1() and request2() are done through requester which is of type IRequester
public interface IRequester {
request1();
List request2();
}
Now request1() and request2() are implemented by the class which actually does the requests. This is the class that handles the communication between the nodes.
public NetworkManager implements IRequester {
request1() {
// Create an operation
// Add callback to the operation
// schedule operation
}
request2() {
}
}
Now, my issue is that when I implement request1() here in there I need to create a procedure which will send a message to the node. This procedure can have a callback attached. When the node responds it returns the result. How do I implement this such that it returns the result at the end of my request1?

One of ways would be to use CompletableFuture to track asynchronous value.
public NetworkManager implements IRequester {
Client client; //some client that works with callbacks
CompletableFuture<String> request1() {
CompletableFuture<String> result = new CompletableFuture<>();
client.request1(someArguments, (calbackResult) -> result.complete(calbackResult));
return result;
}
}
Here result is a promise that as soon as callback is executed it will provide a value. Until that it is going to be empty.
So NetworkManager returns CompletableFuture which means that result is not ready yet or will be never ready (if callback never happens).
When Class1.doSomething tries to get result from CompletableFuture current thread is going to block until value is available or occurs a timeout.
This approach also makes code in Class1.doSomething more stable, because it is now forced to handle issues with timeouts and missing result.

Here is an example on how to wait on callback using Observer as the callback and Thread.sleep to simulate long running async task:
public Object request(){
CompletableFuture<Object> cf = new CompletableFuture<Object>();
runAsync( (o, arg) -> cf.complete(arg) );
try { return cf.get(); }
catch (Exception e) {throw new RuntimeException(e); }
}
public void runAsync(final Observer o){
new Thread( () -> {
try { Thread.sleep(3000L); }
catch (InterruptedException e) { e.printStackTrace(); }
String result = "abc";
o.update(null, result);
} ).start();
}

Since the return type of request1() is void so you cannot return value from it .
But in the implementation class of IRequester , you can pass a resultObject ,
whenever the request1() method is execute it will store the result in the result Object, and when you need to get the result , you can get it from the ResultObject
class ResultObject{
getResult(); ///return result
setResult(); ///store result
}
public NetworkManager implements IRequester {
private ResultObject callBackResult;
public ResultObject getResult(){
return callBackResult;
}
public void setResult(ResultObject value){
this.callBackResult=value;
}
request1() {
// Create an operation
this.setResult(callProcedure());
// schedule operation
}
request2() {
}
}
public class Main{
public static void main(String args){
IRequester r=new NetworkManger();
ResultObject res=new ResultObject();
r.setResult(res);
r.request1();
r.getResult();
r.request2();
}
}

Related

How do I change rx.Observable<java.util.list<T>> to java.util.list<T>

Declaration
#GET("api/Game/SearchGames")
Observable<List<GameModel>> searchGames();
This is the network call
public static Observable<List<GameModel>> searchGames () {
VersusAPI client = VersusServiceGenerator.createService(VersusAPI.class);
Observable<List<GameModel>> ob = client.searchGames();
return ob;
}
Here is where I implement.
mAdapterMyGames = new RecyclerViewAdapter(searchGames());
searchGames() returns rx.Observable<java.util.list<GameModel>>. How do I change that to only java.util.list<GameModel>?
You don't properly understand what is an Observable.
It is an object, to which You can subscribe() to get the result of it's operation. Usually, only when subscribing to an Observable it starts and you can get the result inside Subscriber's onNext() function.
So in your case:
Subscribe to this Observable.
Look for the result inside this subscriber's onNext function.
searchGames().subscribe(new new Subscriber<List<GameModel>>() {
#Override
public void onNext(List<GameModel> gameModels) {
//TODO make sth useful with models
}
#Override
public void onCompleted() { }
#Override
public void onError(Throwable e) { }
)

RxJava and list of `Single` observable

I'm new in RxJava so I still have many doubts.
I'm creating this:
#Override
public Single<Result> saveUser(final User user) {
return Single.create(new Single.OnSubscribe<Result>() {
#Override
public void call(final SingleSubscriber<? super Result> singleSubscriber) {
if(user.isValid()){
save(user);
//Set result ok
singleSubscriber.onSuccess(result);
} else {
//This sets an error.
singleSubscriber.onError(error);
}
}
});
}
Depending of the success of the operation, the Single emits it's data and who is subscribed receives the data.
The problem now is that at some point I need to store a list of users. Something like:
public void saveUsers(List<User> listOfUsers){
for (User user : listOfUsers) {
saveUser(user);
}
}
How can I create an Single so I can be subscribed to the initial Single
I would rather create flatmap out of observable list.
public void saveUsers(List<User> listOfUsers){
Observable.from(listOfUsers).flatMap((User user)->{
if(user.isValid()){
save(user);
//Set result ok
return Observable.just(result);
}else
return Observable.error(new RuntimeException("..."));
}).retry(2);
}
If you make your saveUsers method blocking, call Observable#toBlocking.

Callbacks in Java, similar to Javascript

I'm trying to write a callback system in Java that works similar to that of Javascripts, what I'm doing is I'm sending information across the network that has a "callback id" attached to it. When the client receives this data back from the server, it should locate the callback for that id form a collection and call it with the retrieved data.
Here's the current system I've written up while trying to achieve this:
public class NetworkCallback {
private int id;
private Callable callback;
public NetworkCallback(Callable callback) {
this.callback = callback;
}
public NetworkCallback setId(int id) {
this.id = id;
return this;
}
public int getId() {
return id;
}
public boolean execute(JSONObject data) {
try {
callback.call(); // data?
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
These were stored in a special container a created that would retain index, it's basically just an array with some helper classes. When the client gets information back it will search for the callback and then execute it.
void onMessageReceived(byte[] data) {
JSONObject json = JSONHelper.fromByteArray(data);
int callbackId = json.getInt("cbid");
if(callbackId != 0) {
callbacks.fetch(callbackId).execute(json);
}
}
The issue with this I noticed before even attempting to run the code, pondered for awhile, and ran out of things to think about. The callable class doesn't accept parameters. So, for example, say I wanted to pass a method as a callback like the following:
psuedo
method(param JSONObject data) {
print data
}
Granted this method isn't going to be the same every time it's called, so it will be created on the fly. An example in javascript of what I'm trying to achieve can be found below:
Javascript example of what I want
(function caller() {
called(function(data) {
console.log("Data: " + data);
});
})();
function called(callback) {
callback(Math.random());
}
You will want to use a Consumer for this. A consumer basically is an object on which you can call accept(data), which executes the callback.
An example:
public class Test {
public static void main(String[] args) {
Consumer consumer = new Consumer() {
#Override
public void accept(Object o) {
System.out.println(o.toString());
}
};
new Test().doSomething("Test", consumer);
}
public void doSomething(Object data, Consumer<Object> cb) {
cb.accept(data);
}
}
This prints "Test" in the console.

JavaRx on ErrorReturn return the different type

Observable is tied to a type. When onError I don't want to return the same type but different Object. Example Response object with status=400. How to achieve this?
public class Test{
#Autowired
private Server server;
public Response getResponse(String id){
Observable<Person> personObservable = server.get(id);
ExecutorService executorService = Executors.newFixedThreadPool(100);
List<Person> persons = new ArrayList<Person>();
personObservable.onErrorReturn(new Func1<Throwable, Person>() {
#Override
public Person call(Throwable throwable) {
//I would like to return a HttpResponseObject taking the message
//from throwable error information how to do it?
// How to use Transform() in this case ?
return null;
}
}).subscribeOn(Schedulers.from(executorService)).subscribe(new Action1<Person>() {
// If i use subscribe() will it be not async?
// I think subscribe still run on the main thread so is this
// subscribeOn use fine ?
#Override
public void call(Person person) {
// Is this fine to use the list outside the observable ?
persons.add(person);
}
});
Response r = new Response;
r.addPersons(persons);
return r;
}
}
Use onErrorResumeNext:
Observable<Person> personObservable = ...;
return personObservable
.toList()
.map(persons -> new Response(persons))
.onErrorResumeNext(error -> new Response(error.getMessage())
.toBlocking().single();

Returning a value from Runnable

The run method of Runnable has return type void and cannot return a value. I wonder however if there is any workaround of this.
I have a method like this:
public class Endpoint {
public method() {
Runnable runcls = new RunnableClass();
runcls.run()
}
}
The method run is like this:
public class RunnableClass implements Runnable {
public JaxbResponse response;
public void run() {
int id = inputProxy.input(chain);
response = outputProxy.input();
}
}
I want to have access to response variable in method. Is this possible?
Use Callable<V> instead of using Runnable interface.
Example:
public static void main(String args[]) throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(3);
Set<Future<Integer>> set = new HashSet<>();
for (String word : args) {
Callable<Integer> callable = new WordLengthCallable(word);
Future<Integer> future = pool.submit(callable);
set.add(future);
}
int sum = 0;
for (Future<Integer> future : set) {
sum += future.get();
}
System.out.printf("The sum of lengths is %s%n", sum);
System.exit(sum);
}
In this example, you will also need to implement the class WordLengthCallable, which implements the Callable interface.
public void check() {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Integer> result = executor.submit(new Callable<Integer>() {
public Integer call() throws Exception {
return 10;
}
});
try {
int returnValue = result.get();
} catch (Exception exception) {
//handle exception
}
}
Have a look at the Callable class. This is usually submited via an executor service
It can return a future object which is returned when the thread completes
Yes, there are workaround. Just use queue and put into it value which you want to return. And take this value from another thread.
public class RunnableClass implements Runnable{
private final BlockingQueue<jaxbResponse> queue;
public RunnableClass(BlockingQueue<jaxbResponse> queue) {
this.queue = queue;
}
public void run() {
int id;
id =inputProxy.input(chain);
queue.put(outputProxy.input());
}
}
public class Endpoint{
public method_(){
BlockingQueue<jaxbResponse> queue = new LinkedBlockingQueue<>();
RunnableClass runcls = new RunnableClass(queue);
runcls.run()
jaxbResponse response = queue.take(); // waits until takes value from queue
}
}
If you add a field to RunnableClass you can set it in run and read it in method_. However, Runnable is a poor (the Java keyword) interface as it tells you nothing about the (the concept) interface (only useful line of the API docs: "The general contract of the method run is that it may take any action whatsoever."). Much better to use a more meaningful interface (that may return something).
One way is, we have to use Future - Callable approach.
Another way is, Instead of returning value, you can hold in object
Example:
class MainThread {
public void startMyThread() {
Object requiredObject = new Object(); //Map/List/OwnClass
Thread myThread = new Thread(new RunnableObject(requiredObject)).start();
myThread.join();
System.out.println(requiredObject.getRequiredValue());
}
}
class RunnableObject implements Runnable {
private Object requiredObject;
public RunnableObject(Object requiredObject) {
this.requiredObject = requiredObject;
}
public void run() {
requiredObject.setRequiredValue(xxxxx);
}
}
Because object scope is in the same scope so that you can pass object to thread and can retrieve in the main scope. But, most important thing is, we have to use join() method. Because main scope should be waiting for thread completion of its task.
For multiple thread case, you can use List/Map to hold the values from threads.
Try the following
public abstract class ReturnRunnable<T> implements Runnable {
public abstract T runForResult();
#Override
public void run() {
runForResult();
}
}
Take a look at the callable interface, perhaps this suites your needs. You can also try to get the value of the response field by calling a setter-method inside of your run() method
public void run() {
int id;
id =inputProxy.input(chain);
response = outputProxy.input();
OuterClass.setResponseData(response);
}

Categories

Resources