I have some code that:
1- Received some data through a REST call (POST);
2- Performed some logic according to that data;
3- Returned the result.
For the sake of this question let's pretend it was a simple calculator webapi that allowed its clients to perform additions and subtractions. It looked like this:
#Path("/calculator")
public class Calculator {
#POST
#Path("addition")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response add(String request){
//Getting A and B from request
...
//Calculating result
int res = a + b;
//Creating response payload
JSONObject res = new JSONObject.put("result",res);
return Response.status(Response.Status.OK).entity(res.toString()).build();
}
#POST
#Path("subtract")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response sub(String request){
//Getting A and B from request
...
//Calculating result
int res = a - b;
//Creating response payload
JSONObject res = new JSONObject.put("result",res);
return Response.status(Response.Status.OK).entity(res.toString()).build();
}
}
Everything was fine until i realized that i couldn't perform more that one calculation in parallel because all the requests accessed a unique resource that can only be used by one of them at a time.
So, for the sake of this example, let's pretend we have a single calculator and that all requests' computations must be performed by that same calculator processor.
In my mind i think i would need something like a "CalculatorProcessor" that received requests from all the calculator webapi clients that:
1- Receives request;
2- Queues request;
3- Dequeues request;
4- Performs calculation;
5- Returns result using callback.
This is something that is kinda trivial for me in native Java, but i don't have a single clue on how i should this in a Java Jersey's context.
For instance...
How can i get back to the Calculator.add() and Calculator.sub() methods so i can send the http request response?
Can someone please enlighten me please?
Here's my java implementation for such a component:
import java.util.concurrent.ConcurrentLinkedQueue;
//IMPLEMENTS SINGLETON PATTERN
public class Calculator {
private static Calculator instance = null;
private ConcurrentLinkedQueue<Request> queue = null;
private Runnable processor = null;
//PRIVATE CONSTRUCTOR
private Calculator() {
queue = new ConcurrentLinkedQueue<>();
}
//GET CALCULATOR INSTANCE
static public Calculator getInstance() {
if (instance == null) {
instance = new Calculator();
}
return instance;
}
//REQUEST COMPUTATION
public synchronized void requestComputation(CalculatorCallback c, SupportedOperations o, int a, int b) {
//Adds request to queue
queue.add(new Request(c, o, a, b));
//Checks if there's an active processor
if (processor == null) {
//Launches a new processor if there isn't
Runnable p = new CalculatorProcessor(queue);
new Thread(p).start();
}
}
//CALLBACK INTERFACE
public interface CalculatorCallback {
void computationReady(int result);
}
//SUPPORTED OPERATIONS ENUMERATION
protected enum SupportedOperations {
ADDITION, SUBTRACTION;
}
//CLASS THAT REPRESENTS A REQUEST
private class Request {
final SupportedOperations operation;
final CalculatorCallback callback;
final int a;
final int b;
public Request(CalculatorCallback c, SupportedOperations operation, int a, int b) {
this.callback = c;
this.operation = operation;
this.a = a;
this.b = b;
}
}
//CALCULATOR PROCESSOR THREAD
class CalculatorProcessor implements Runnable {
final private ConcurrentLinkedQueue<Calculator.Request> queue;
public CalculatorProcessor(ConcurrentLinkedQueue<Calculator.Request> queue) {
this.queue = queue;
}
#Override
public void run() {
Calculator.Request current;
int result;
while (!queue.isEmpty()) {
//Gets head
current = queue.poll();
if (current.operation == Calculator.SupportedOperations.ADDITION) {
result = current.a + current.b;
} else if (current.operation == Calculator.SupportedOperations.SUBTRACTION) {
result = current.a - current.b;
} else {
throw new UnsupportedOperationException();
}
//Calls back the requester
current.callback.computationReady(result);
}
}
}
}
Here's the CalculatorClient code:
public class CalculatorClient implements Calculator.CalculatorCallback {
public static void main(String[] args) {
CalculatorClient client = new CalculatorClient();
Random random = new Random();
int a, b;
for (int i = 0; i < 1000; i++) {
a = random.nextInt(Integer.MAX_VALUE/2);
b = random.nextInt(Integer.MAX_VALUE/2);
System.out.println("Requesting "+a+" + "+b+"...");
Calculator.getInstance().requestComputation(client, Calculator.SupportedOperations.ADDITION,a,b);
}
}
#Override
public void computationReady(int result) {
System.out.println("Result is: "+result);
}
}
If you are using Jersey 2, you can use its Asynchronous processing feature. You can just pass the AsyncResponse to the calculating task, and the task will just resume the response when it is finished with the processing.
#POST
public void add(#Suspended AysncResponse response, String body) {
Calculator.getInstance().requestComputation(
client,
Calculator.SupportedOperations.ADDITION,
a,b,
response);
// you don't need to return anything from the resource method
// calling `response.resume(someResponse)` (from inside the task)
// is enough. That is why this method just returns `void`
}
The good thing about using the async feature is that if the processing takes a long time, you wouldn't be blocking the server threads as you would be if you were to try using some block mechanism like a CountDownLatch or blocking queue, or something to that effect. The server threads are immediately returned to the server so that it can handle more requests.
Related
Problem
The IBKR TWS (Trader Workstation) is a tool for managing stock orders in the stock market, by Interactive Brokers. They provide an API to automate orders, like placing orders, cancelling orders, and more.
I'm creating a program to handle executed orders in my Trader Workstation using the Interactive Brokers Java API.
I'm having trouble detecting when an order fills.
The documentation describes that the execDetails callback (which is an EWrapper method, see code below) is invoked when an order is filled, but I tried using that and the execDetails callback was never invoked (I tested this by logging the reqid int in that callback, and I never got any log).
I have also researched about the completedOrder callback, which I'm not sure if that's the callback that will be invoked when an order is filled, because I tested both callbacks with a simple log, and nothing was outputting in the console.
I don't understand the reqExecutions function and whether I need that. I have already read the documentation on this callback, and I don't understand what I'm doing wrong. I want to know I how can detect when an order fills, or executes in the TWS using their API.
Code
Here is my current code:
import com.ib.client.*;
import java.util.*;
public class Main implements EWrapper {
private static EClientSocket clientSocket;
private static EJavaSignal readerSignal;
public static void main(String[] args) throws InterruptedException, IOException {
readerSignal = new EJavaSignal();
clientSocket = new EClientSocket(this, readerSignal);
clientSocket.eConnect("127.0.0.1", 7497, 0);
}
clientSocket.placeOrder(orderidE, contractFill("CUSIP", "USD", tickSymbol, "STK", "SMART"), orderFill(lmtPriceDouble, actionString, "LMT", "GTC", orderQuantity, account, 0));
//Order executes successfully after sometime
public static Order orderFill(double lmtPrice, String action, String orderType, String tif, int totalQuantity, String account, int clientId){
Order order = new Order();
order.m_lmtPrice = lmtPrice;
order.m_action = action;
order.m_orderType = orderType;
order.m_tif = tif;
order.m_totalQuantity = totalQuantity;
order.m_account = account;
order.m_clientId = clientId;
return order;
}
public static Contract contractFill(String secIdType, String currency, String symbol, String secType, String exchange){
Contract contract = new Contract();
contract.m_secIdType = secIdType;
contract.m_currency = currency;
contract.m_symbol = symbol;
contract.m_secType = secType;
contract.m_exchange = exchange;
return contract;
}
/*Implemented EWrapper methods
...
*/
#Override
public void execDetails(int reqId, Contract contract, Execution execution) {
System.out.println(execution + " " + contract + " " + reqId);
}
#Override
public void execDetailsEnd(int reqId) {
System.out.println(reqId);
}
/*Implemented EWrapper methods
...
*/
#Override
public void completedOrder(Contract contract, Order order, OrderState orderState) {
System.out.println(contract);
System.out.println(order);
System.out.println(orderState);
}
#Override
public void completedOrdersEnd() {
System.out.println("cOE");
}/*Implemented rest of EWrapper methods
...
*/
}
I am placing the orders by hand while this code is running, and the order fills fairly quickly (while the code is running), so the code should detect it, but (my problem -->)none of the callbacks are being invoked.
What am I supposed to be doing to detect order executions?
(Note: I'm placing the orders by hand and by code in the TWS as of now).
Here is code that works, I tested with api 9.81.
Note that if you're using clientID 0 then you should also get callbacks from trades place in TWS. I've never tried, but the docs are clear.
import com.ib.client.*;
import java.io.IOException;
import java.util.*;
public class MainIB implements EWrapper {
private EClientSocket clientSocket;
private EJavaSignal readerSignal;
public static void main(String[] args) throws IOException {
new MainIB().connect();
System.in.read();//press enter to exit
System.exit(0);
}
private void connect() {
readerSignal = new EJavaSignal();
clientSocket = new EClientSocket(this, readerSignal);
clientSocket.eConnect("127.0.0.1", 7497, 0);
//Create a reader to consume messages from the TWS. The EReader will consume the incoming messages and put them in a queue
EReader reader = new EReader(clientSocket, readerSignal);
reader.start();
//Once the messages are in the queue, an additional thread can be created to fetch them
Thread processer = new Thread(() -> {
while ( clientSocket.isConnected() ) {
readerSignal.waitForSignal();
try {
reader.processMsgs();
} catch (IOException ex) {}
}
});
processer.setDaemon(true);
processer.start();
}
public Order orderFill(double lmtPrice, String action, String orderType, String tif, int totalQuantity, String account, int clientId){
Order order = new Order();
order.lmtPrice(lmtPrice);
order.action(action);
order.orderType(orderType);
order.tif(tif);
order.totalQuantity(totalQuantity);
//order.account(account);
//order.clientId(clientId);
return order;
}
public Contract contractFill(String secIdType, String currency, String symbol, String secType, String exchange){
Contract contract = new Contract();
//contract.secIdType(secIdType);
contract.currency(currency);
contract.symbol(symbol);
contract.secType(secType);
contract.exchange(exchange);
return contract;
}
#Override
public void error(int id, int errorCode, String errorMsg) {
System.out.println(errorCode + " " + errorMsg);
}
#Override
public void nextValidId(int i) {
int orderidE = i;
clientSocket.placeOrder(orderidE++, contractFill("", "CAD", "USD", "CASH", "IDEALPRO"),
orderFill(0, "SELL", "MKT", "GTC", 100000, "", 0));
}
#Override
public void orderStatus(int i, String status, double d, double d1, double d2, int i1, int i2, double d3, int i3, String string1, double d4) {
System.out.println("status " + status);
}
#Override
public void execDetails(int reqId, Contract contract, Execution execution) {
System.out.println(execution + " " + contract + " " + reqId);
}
/*Implemented rest of EWrapper methods
...
*/
}
Here is bit of my api.Day.0.log file
t:ms <-> msg# # desc
9:064 -> 15-1-DU123456- 15 my account #
9:065 -> 9-1-2- 9 next valid id
9:065 -> 4-2--1-2104-Market da 4 errors(or info)
9:065 -> 4-2--1-2104-Market da
9:072 <- 3-45-2-0-USD-CASH--0. <- 3 means an order I sent
9:671 -> 5-34-2-15016062-USD-C 5 order status
9:722 -> 11--1-2-15016062-USD- 11 exec
9:724 -> 5-34-2-15016062-USD-C more status
9:727 -> 5-34-2-15016062-USD-C
9:728 -> 59-1-0000e215.60b94f1 59 commission report
I'm getting a list of data from Binance that returns a response, how do I access the values of the response body?
private Closeable candleStick(){
BinanceApiWebSocketClient client = BinanceApiClientFactory.newInstance().newWebSocketClient();
return client.onCandlestickEvent("btcusdt", CandlestickInterval.FIVE_MINUTES, new BinanceApiCallback<com.binance.api.client.domain.event.CandlestickEvent>() {
#Override
public void onResponse(com.binance.api.client.domain.event.CandlestickEvent response) {
System.out.println(response);
}
});
}
The response has values like response.getHigh(), response.getLow(), etc. How do I access these values in another method. It
private String show() throws IOException {
Double high = candleStick().getHigh() //didn't work as the method returns a closeable object.
}
It's a callback based API, so instead of your System.out.println(...) you should update some data structure in your app to add/show the new values.
Just a simple example:
public class CandleStickDataSource {
private final BinanceApiWebSocketClient client;
private final Closeable socket;
private final List<Double> highs = new ArrayList<>();
private final List<Double> lows = new ArrayList<>();
private Double lastHigh;
private Double lastLow;
public CandleStickDataSource(String ticker, CandlestickInterval interval) {
this.client = BinanceApiClientFactory.newInstance().newWebSocketClient();
this.socket = client.onCandlestickEvent(ticker, interval, new BinanceApiCallback<CandlestickEvent>() {
#Override
public void onResponse(CandlestickEvent response) {
lastHigh = Double.valueOf(response.getHigh());
lastLow = Double.valueOf(response.getLow());
highs.add(lastHigh);
lows.add(lastLow);
}
}); // don't forget to call close() on this somewhere when you're done with this class
}
public List<Double> getHighs() { return highs; }
public List<Double> getLows() { return lows; }
public Double getLastHigh() { return lastHigh; }
public Double getLastLow() { return lastLow; }
}
So somewhere else in your app where you want to get access to the data:
CandleStickDataSource data = new CandleStickDataSource("btcusdt", CandlestickInterval.FIVE_MINUTES); // Create this first. This is now reusable for any ticker and any interval
and then whenever you want to see the data
data.getHighs(); // history
data.getLows();
data.getLastHigh(); // or getLastLow() for latest values
I am testing Hystrix CircuitBreaker implementation. This is how command class looks like:
public class CommandOne extends HystrixCommand<String>
{
private MyExternalService service;
public static int runCount = 0;
public CommandGetPunterUnpayoutExternalBets(MyExternalServoce service)
{
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("AAA"))
.andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties.Setter().
.withMetricsRollingStatisticalWindowInMilliseconds(10000))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withCircuitBreakerEnabled(true)
.withCircuitBreakerErrorThresholdPercentage(20)
.withCircuitBreakerRequestVolumeThreshold(10)
.withExecutionTimeoutInMilliseconds(30)
.withCircuitBreakerSleepWindowInMilliseconds(100000)));
this.service = service;
}
#Override
protected String run()
{
run++;
return service.callMethod();
}
#Override
protected String getFallback()
{
return "default;
}
}
Command is called like this:
public class AnotherClass
{
private MyExternalServoce service;
public String callCmd()
{
CommandOne command = new CommandOne(service);
return command.execute();
}
}
In test I perform next steps:
#Test
public void test()
{
AnotherClass anotherClass = new AnotherClass();
// stubbing exception on my service
when(service.callMethod()).thenThrow(new RuntimeException());
for (int i = 0; i < 1000; i++)
{
anotherClass.callCmd();
}
System.out.println("Run method was called times = " + CommandOne.runCount);
}
What I expect with the configuration of command given: MyExternalService.callMethod() should be called 10 times (RequestVolumeThreshold) and after that not being called 100000 ms (long time). In my test case I expect that CommandOne.runCount = 10.
But in reality I am getting from 150 to 200 calls of MyExternalService.callMethod() (CommandOne.runCount = (150-200). Why does it happening? What I did wrong?
According to Hystrix docs health snapshot will be taken once per 500ms ( by default ). Which means that everything what happens with hystrix during first 500ms will not affect circuit breaker status. In your example you got random value of runCount because each time your machine executed random value of requests per 500 ms, and only after that time interval circuit state was updated and closed.
Please take a look on a bit simplified example:
public class CommandOne extends HystrixCommand<String> {
private String content;
public static int runCount = 0;
public CommandOne(String s) {
super(Setter.withGroupKey
(HystrixCommandGroupKey.Factory.asKey("SnapshotIntervalTest"))
.andCommandPropertiesDefaults(
HystrixCommandProperties.Setter()
.withCircuitBreakerSleepWindowInMilliseconds(500000)
.withCircuitBreakerRequestVolumeThreshold(9)
.withMetricsHealthSnapshotIntervalInMilliseconds(50)
.withMetricsRollingStatisticalWindowInMilliseconds(100000)
)
);
this.content = s;
}
#Override
public String run() throws Exception {
Thread.sleep(100);
runCount++;
if ("".equals(content)) {
throw new Exception();
}
return content;
}
#Override
protected String getFallback() {
return "FAILURE-" + content;
}
}
#Test
void test() {
for (int i = 0; i < 100; i++) {
CommandOne commandOne = new CommandOne();
commandOne.execute();
}
Assertions.assertEquals(10, CommandOne.runCount);
}
In this example I've added:
withMetricsHealthSnapshotIntervalInMilliseconds(50) to allow hystrix to take snapshots each 50ms.
Thread.sleep(100); to make requests a bit slower, without it they will be faster then 50 ms and we will face initial issue.
Despite of all these modifications I've seen some random failures. After this I came to conclusion that testing hystrix like this is not a good idea. Instead of it we could use:
1) Fallback/Success flow behavior by manually setting open/close circuit state.
2) Configuration tests
I'm using a Odoo service to get my data of web. In main class I have a method to read a data:
public void OdooRead() {
OdooService.getCustomers(odoo, "myCallbackFunction");
}
So, I did create a other class to make this service:
public class OdooService {
public static final String[] odooAllFields = {"id","name","customer_account_number","customer_group_id","segment_id","subsegment_id","economic_group_id","type_stablishment_id","street","street2","final_user","final_taxpayer","cnpj_cpf","inscr_est","ccm","cnae","phone","phone_extension","mobile","fax","email","email_extra","website","lang"};
public static List<Customer> getCustomers(OdooClient client, "myCallbackFunction") {
List<Customer> list = new ArrayList<>();
ODomain domain = new ODomain();
OdooFields odooFields = new OdooFields();
odooFields.addAll(odooAllFields);
String sorting = "id ASC";
int offset = 0;
int limit = 0;
client.searchRead("res.partner", domain, odooFields, offset, limit, sorting, new IOdooResponse() {
#Override
public void onResult(OdooResult result) {
// HERE I WANTS CALL THE CALLBACK FUNCTION TO MAIN!
}
});
return list;
}
}
So, when the method returns the result of search on web, I wants send a callback function to main, with the list of results as parameter. And while this, the main class runs normally, and when method finish I refresh user interface.
I am trying to take data from one class, put it in a singleton, and then proceed to access that data in another class.
Here is my singleton:
public class DataTransferrer {
private static DataTransferrer instance = null;
private ArrayList<Transients> transientList;
private DataTransferrer(){
transientList = new ArrayList<>();
}
public static synchronized DataTransferrer getInstance(){
if(instance == null) {instance = new DataTransferrer();}
return instance;
}
public ArrayList<Transients> getTransients(){return this.transientList;}
public void setTransients(ArrayList<Transients> t){transientList = t;}
public void printAll(){
for(Transients t : transientList){
Log.d("DEBUG DA",t.getDa().toString());
}
}
}
Here is my method that adds data to an arrayList which is then set to the arrayList within the singleton to then be used elsewhere:
public class JSONParser {
// URL to get contacts JSON
private static String url = "http://pi.cs.oswego.edu/~lpatmore/getAllTransients.php";
ArrayList<Transients> transientList;
private Transients t;
public JSONParser(){
transientList = new ArrayList<>();
}
public void execute(){
new GetTransients().execute();
}
/**
* Async task class to get json by making HTTP call
*/
private class GetTransients extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... arg0) {
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall(url);
Log.d(TAG, "Response from url: " + jsonStr);
if (jsonStr != null) {
try {
Log.d(TAG, "NOT NULL DEBUG");
JSONObject jsonObj = new JSONObject(jsonStr);
// Getting JSON Array node
JSONArray transients = jsonObj.getJSONArray("result");
// looping through All Transients
for (int i = 0; i < transients.length(); i++) {
JSONObject c = transients.getJSONObject(i);
String author = c.getString("author");
String transientId = c.getString("transientId");
String dateAlerted = c.getString("dateAlerted");
String datePublished = c.getString("datePublished");
float right_asencsion = (float) c.getDouble("right_asencsion");
float declination = (float) c.getDouble("declination");
t = new Transients(author, transientId, dateAlerted, datePublished, right_asencsion, declination);
// adding trans to trans list
transientList.add(t);
}
DataTransferrer.getInstance().setTransients(transientList);
DataTransferrer.getInstance().printAll();
} catch (final JSONException e) {
Log.e(TAG, "Json parsing error: " + e.getMessage());
}
} else {
Log.e(TAG, "Couldn't get json from server.");
}
return null;
}
}
}
And I try to access it in another class like:
for(int i = 0; i < DataTransferrer.getInstance().getTransients().size(); i++){
System.out.println("DEBUG ADDED TRANSIENT");
Float ra = DataTransferrer.getInstance().getTransients().get(i).getR();
Float dec = DataTransferrer.getInstance().getTransients().get(i).getD();
transients.add(new Transient("Transient", names[i], GeocentricCoordinates.getInstance(ra, dec)));
}
Whenever I debug it checking to see in the other class, I am trying to access the arraylist, but in the other class it's like there was never an array list added to getTransients() method.
I tested this exact setup in Eclipse and it works perfectly but not in Android Studio.
I tested this exact setup in Eclipse and it works perfectly but not in
Android Studio.
Basically, you have got multithreading issue i.e., your DataTransferrer class is NOT threadsafe which is causing the issue i.e., there is a race condition between multiple threads and your singleton instance is NOT actually singleton (multiple objects are being created for DataTransferrer class).
So when you calling setTransients() from one thread, it is actually storing the Transients in one instance of DataTransferrer and then when you are trying retrieve the Transients from a different thread it is using different instance (object) of DataTransferrer.
You can create threadsafe singleton instance for your DataTransferrer class as shown below:
public class DataTransferrer {
private static final DataTransferrer instance = new DataTransferrer();
private ArrayList<Transients> transientList = new ArrayList<>();
//private constructor, so instantiation NOT allowed
private DataTransferrer() {}
public static synchronized DataTransferrer getInstance(){
return instance;
}
public ArrayList<Transients> getTransients(){
return this.transientList;
}
public void setTransients(ArrayList<Transients> t){
transientList = t;
}
public void printAll(){
for(Transients t : transientList){
Log.d("DEBUG DA",t.getDa().toString());
}
}
}
Also, note that in the above code, the instance will be created eagerly during the startup (initializing) time and when you call setTransients and getTransients that same instance (singleton) will be used. Instead of eager creation, if you need to create the instance lazily, you can look here.