How to make a Callback function for webservice in Java? - java

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.

Related

Efficient Way to Pass an Object Parameter in Java Method

I'm just looking some another efficient way to pass an object parameter to method.
So I have some method like this:
private void dashboardMenu() {
Dashboard dashboard = new Dashboard();
body.removeAll();
body.add(dashboard);
dashboard.setSize(body.getWidth(), body.getHeight());
dashboard.setVisible(true);
}
private void dataMenu() {
Data data = new Data();
body.removeAll();
body.add(data);
data.setSize(body.getWidth(), body.getHeight());
data.setVisible(true);
}
And I want an efficient method to call between this two method with object parameter (dashboard = new Dashboard(), and data = new Data()).
What I think it should be like this for example:
private void dasboardMenu() {
navigateMenu(Type object);
}
private void dataMenu() {
navigateMenu(Type object);
}
private void navigateMenu(Type object) {
object menu = new object();
body.removeAll();
body.add(menu);
menu.setSize(body.getWidth(), body.getHeight());
menu.setVisible(true);
}
Is it possible to do that?
Please give me an example. I don't even know what keyword should I do.
How about this (assuming your Dashboard and Data are Swing Components)?
private void dashboardMenu() {
navigateMenu(new Dashboard());
}
private void dataMenu() {
navigateMenu(new Data());
}
private void navigateMenu(JComponent c) {
body.removeAll();
body.add(c);
c.setSize(body.getWidth(), body.getHeight());
c.setVisible(true);
}

Async in Java Jersey

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.

How to Monitor an existing Java class with JMX?

I have an existing Java class as follows and I want to monitor number of method invocations for each method in this class using JMX. How do I do it? I tried google but I can't see the big picture on how the whole thing is connected. It would be great if I can see see some code examples
Public class RPCServer {
public void storeSchema() { // want to count number of method invocations
System.out.println("storeSchema");
}
public void getSchema() { // want to count number of method invocations
System.out.println("getSchema");
}
public void storeRow() { // want to count number of method invocations
System.out.println("storeRow");
}
public void getRow() { //want to count number of method invocations
System.out.println("getRow");
}
}
I you want to see how many time some methods are executed through JMX, I propose this solution
First you need an interface for your class. Only the methods of this interface are visible for JMX:
public interface RPCServerInterface {
int countMethodInvocation(String method);
}
Then in the class you store how many time each function is call.
public class RPCServer implements RPCServerInterface{
private int row;
private Map<String,Integer> countByMethod = new HashMap<String,Integer>();
// +1 to the number of time of execution of this method
private void sumMethodInvocation(String method) {
if ( countByMethod.containsKey(method) ) {
int n = countByMethod.get(method);
countByMethod.put(method, n+1);
} else {
countByMethod.put(method,1);
}
}
// how many time the method has been invoked
#Override
public int countMethodInvocation(String method){
return countByMethod.containsKey(method)?countByMethod.get(method):0;
}
public void setRow(int i) {
// register each time is executed
this.sumMethodInvocation("setRow");
this.row = i;
}
public int getRow() {
// register each time is executed
this.sumMethodInvocation("getRow");
return row;
}
}}
}
Then you have to register your Bean:
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
RPCServer rpcServer = new RPCServer();
ObjectName objectName = new ObjectName("org.foo.RPCServer.jmx:type=RPCServerInterface");
StandardMBean standardMBean = new StandardMBean(rpcServer,RPCServerInterface.class);
mBeanServer.registerMBean(standardMBean, objectName);
The path org.foo.RPCServer.jmx is arbitrary.
Then your run jconsole and you find the process you are running.
Then you can run the command countMethodInvocation and you can get the number of execution time.
Like this:
This tutorial can be useful:
what-is-jmx-mbean-jconsole-tutorial

Callback function pointer jna

So i have native function in C declared as int NgSetEvent (int event, long callback). long Callback represent the callback function pointer. Callback prototype is declared as int oncodeline(int code, int documentid, char *string). The callback should be registered with method NgSetEvent. The problem is how to get pointer to that function which should be long or Nativelong? I have tried a lot of different aproaches but none of them gave a result. Callback was never invoked.
I have tried to do like it says in Turn a Callback into a Pointer in JNA, but with no success. i don't know what to try anymore.
Any help will be appreciated.
OnCodeline
public interface OnCodeline extends Callback {
int oncodeline (int code, int documentid, byte[] string);
}
OnCodelineStruct
public class OnCodelineStruct extends Structure {
public OnCodeline onc;
#Override
protected List getFieldOrder() {
return Arrays.asList(new String[] { "onc" });
}
}
Main class
OnCodelineStruct onCodelinStruct;
onCodelinStruct = new OnCodelineStruct();
onCodelinStruct.onc = new OnCodeline() {
#Override
public int oncodeline(int code, int documentid, byte[] string) {
System.out.println("This IS a CALLBACK!");
return 0;
}
};
sbDll.NgSetEvent(0, onCodelinStruct.getPointer().getNativeLong(0));

GWT AsyncCallback Does Not Populate Static Member

I have an AsyncCallback call that contacts my GWT-RPC service and retrieves some data. I am trying to store that data into a class which has a static method to store the results of the query. However, I noticed that the data is not being populated in the static data member. If I "slow down" the AsyncCallback call by putting an SC.logWarn(...) in the AsyncCallback call, then the static data member gets populated properly.
final AsyncCallback<Set<MyData>> dataCallback =
new AsyncCallback<Set<MyData>>()
{
#Override
public void onSuccess(Set<MyData> aDataType)
{
for (MyData data : aDataType)
{
String someData = aDataType.getData();
Record rec = new Record();
rec.setAttribute("data", someData);
getDataSource().addData(rec);
}
LocalUiCache.setLocalCache(new ResultSet(getDataSource()));
}
};
MyDataService.RPC.getInstance().getData(dataCallback);
...
public class LocalUiCache
{
private static ResultSet localCache;
/**
* #return the localCache
*/
public static ResultSet getLocalCache()
{
return localCache;
}
/**
* #param aLocalCache the localCache to set
*/
public static void setLocalCache(ResultSet aLocalCache)
{
localCache = aLocalCache;
}
}
I'm not sure at this, but I suppose that SmartGWT doesn't reloads your changes fast.
You can try to tweak dataSource cache or call explicitly invalidate method.
Other suggestion will surely work, but it's 'dirty hack'. You can put in async callback scheduled call:
new Timer() {
public void run() {
LocalUiCache.setLocalCache(new ResultSet(getDataSource()));
}
}.schedule(50);

Categories