I have a work project where I am having multiple threads call a utility function I created that sends a post form to an internal API we have.
I use the callAPI method here which is in a utility class, which is public, final and static :
public static int callAPI(String url, TaskListener listener, String operation, String id, String password, String sUser){
Client client = ClientBuilder.newClient();
Form form = new Form();
form.param("case", id);
form.param("user", sUser);
form.param("password", password);
listener.getLogger().println("*******************************************************");
listener.getLogger().println("Sending API Service Request");
Response response = client.target(url)
.path(operation)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
}
I then have this run method in my Runnable class:
#Override
public void run(){
listener.getLogger().println("Thread Started.\n");
int runId = Utility.callAPI(wUrl, listener, operation, password, sUser);
listener.getLogger().println("call completed");
}
So what actually prints in Jenkins console output:
*******************************************************
Sending API Service Request
Thread Started.
This means I know my run() method is being called and so my thread is starting. I know it can see my runAPI method in the utility.
Now all I can gather is that this line:
Response response = client.target(url)
.path(operation)
.request(MediaType.APPLICATION_JSON)
.post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
sends a request and from there the thread exits before it finishes off the rest of the run() method.
I've tried:
putting a thread sleep loop
putting the call in a while loop
It has been awhile since I've done any Java programming or threading. This is something very simple that I know I am forgetting.
ALSO I HAVE CHANGED A LOT OF MY CODE AND HAVE ONLY SHOWN THE CRITICAL PARTS BEING THIS IS PART OF A WORK PROJECT AND I DIDNT WANT TO TAKE CHANCES.
Related
I have two Singles (getChannels and getEPGs), both running in parallel. In most cases, getChannels is completed before getEPGs and I can connect the EPG's to the channels. However, I would like to handle the cases where getEPGs are completed before the getChannels.
In other words,
Both Singles are running parallel.
To connect the EPG, the channels must have been loaded.
If the getEPGs is completed before the getChannels, it must wait for the getChannels, and only then a method will be invoked
If the getEPGs fails, the app flow will continue regardless.
How can I accomplish this without relying on callbacks and while loops? I guess that there should be a reactive way to handle this case. Thanks in advance.
#GET
Single<ResponseBody> getChannels(#Url String url);
#Streaming
#GET
Single<ResponseBody> getEPGs(#Url String url);
getChannels [.............................]
getEPGs [..........................................]
Define your functions into a repository and access them through a viewModel.
public class Repository {
#GET
return Single<ResponseBody> getChannels(#Url String url);
#Streaming
#GET
return Single<ResponseBody> getEPGs(#Url String url);
}
Now ViewModel class.
public class SiteListViewModel extends BaseViewModel {
private CompositeDisposable mDisposable;
private Repository mRepository;
public void getData() {
mDisposable.add(
mRepository.getChannels().subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(obj -> {"CALL SECOND FUNCTION OVER HERE"
},throwable -> Log.e("Error", e.printStackTrace()))
);
}
}
2. To connect the EPG, the channels must have been loaded.
Okay,
ResponseBody channels = getChannels.blockingGet();
3. If the getEPGs is completed before the getChannels, it must wait for the getChannels, and only then a method will be invoked
Okay, wait for channels and call a method:
ResponseBody channels = getChannels.blockingGet();
aMethod(channels);
4. If the getEPGs fails, the app flow will continue regardless.
the above statements indeed ignores the result of getEPGs().
So strictly speacing, all your conditions can be expressed simply: wait for getChannels() and ignore getEPGs(). That conditions are fully satisfied by the proposed 2 lines of code.
I'm using Jersey for the application's REST API, consider the function below
#POST
public String writeSomething() {
someVeryIntensiveTaskWhichTaking("5 seconds");
Log.info("get request fulfilled") // don't want the logging to happen if user cancelled on UI
return "ok";
}
Assume this POST request is doing some intensive task and might takes up to 5 seconds. Then on the UI, the user decided to cancel the POST request via XMLHttpRequest.abort() at 2 second,
is there any way to track this abortion and prevent some action being done? something like checking IsClientConnected?
Update #1
Thanks to peeskillet's tips, but i still unable to get the callback being triggered upon the XHR's abortion. The below is my code
#POST
public String writeSomething(#Suspended final AsyncResponse asyncResponse) {
asyncResponse.register(new ConnectionCallback() {
public void onDisconnect(AsyncResponse asyncResponse) {
System.out.println("This is canceled, do whatever you want"); // this is not triggered after XHR aborted
}
});
someVeryIntensiveAsynTaskWhichTaking("5 seconds", asyncResponse); // this asyn function will trigger asyncResponse.resume() upon completion
}
1) Hi I am new gwt. I want to execute one servlet to another servlet. for example i want to execute servlet2 from servlet1 one. I can execute sevlet1 using RPC call so from servlet1 i want to execute servlet2 which have doPost method i want to execute.
2) I want to use task queue on GAE. so can understood the task queue by reading https://cloud.google.com/appengine/docs/java/taskqueue/overview-push. In this document Enqueue is servlet which create task and worker is another servlet which executes Task Queue code. So how can call enqueue servlet without using html code.
any help?
Thanks in advance
(From a servlet on the server)
To call the call enqueue servlet without using html code, you use a RequestDispatcher and forward the request.
String enqueueURL = "/enqueue";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(destination);
dispatcher.forward(request, response);
To sent a List to another servlet, use request.setAttribute
request.setAttribute("myList", list);
To obtain it in a different servlet, use request.getAttribute
List value = (List)request.getAttribute("myList")
From a design perspective, if your servlet is functioning as a Controller such as in a Model-View-Controller system, then it's use is appropriate.
(from GWT client side code)
Method A]
Simply make an RPC call and in the method that handles it put your queue code:
public class MyServiceImpl extends RemoteServiceServlet implements
MyService {
public void myMethod(String key) {
Queue queue = QueueFactory.getDefaultQueue();
byte[] buf;
TaskOptions taskOptions= TaskOptions.Builder.withUrl("/tasks/worker").method(Method.POST);
taskOptions.payload(buf);
queue.add(taskOptions);
}
}
If you need help converting the List to a byte[], see this or something like it (i.e. coverting a Java Object to an byte[] array ..don't forget to include a cast to get it back into a List)
Method B]
To call a servlet from client code in GWT, simply use a RequestBuilder
import com.google.gwt.http.client.*;
...
String url = "http://www.myurl.com/enqueue";
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST, URL.encode(url));
try {
Request request = builder.sendRequest(null, new RequestCallback() {
public void onError(Request request, Throwable exception) {
// Couldn't connect to server (could be timeout, SOP violation, etc.)
}
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
// Process the response in response.getText()
} else {
// Handle the error. Can get the status text from response.getStatusText()
}
}
});
} catch (RequestException e) {
// Couldn't connect to server
}
See GWT Docs on RequestBuilder
Servlets only be communication between the client and the server. Your server should do whatever it needs to to marshal your information and then pass it to the business layer of your application.
So, really, having servlet1 call servlet2 is the wrong approach.
Both servlets would return the result of the same method in your business layer. This makes your code infinitely easier to test and maintain.
For example, if you want to enqueue the same request from two different servlets, you could create a QueueManager like
public class QueueManager {
public static void startWorker(String key){
Queue queue = QueueFactory.getDefaultQueue();
queue.add(TaskOptions.Builder.withUrl("/worker").param("key", key));
}
}
Then call it from your servlet by
QueueManager.startWorker(aKey);
This is a design question and I am asking for some ideas.
I have a rest method and it will trigger long-time tasks (10~15 minutes)
As the function takes long time, I run it as a thread,
this can avoid method timeout, but how can I know if the thread went wrong?
Runnable loader = new Runnable() {
public void run() {
//tasks
}
};
(new Thread(loader)).start();
Update: the rest service like this
#path()
beginload(){
//let thread run and return info first
//how can i know if this thread went wrong?
(new Thread(loader)).start();
return "need 15 minutes";
}
Conceptually there has to be a way for the service to communicate a failure to the client. There are multiple ways you can do this. Here are three examples:
After the client calls the service, the service immediately returns a job ID. The client can use the job ID later to query the service for the status (including error). For example, when you launch instances at AWS EC2, it takes a while for EC2 to service the request, so the launch request returns a so-called "reservation ID" that you can use in subsequent operations (like querying for status, terminating the launch, etc.).
Pro: Usable in a wide variety of cases, and easy enough to implement.
Con: Requires polling. (I.e. more chatty.)
The client offers a callback URI that the service invokes upon job completion. The callback URI can either be configured into the service, or else passed along as a request parameter. (Don't hardcode the callback URI in the service since services shouldn't depend on their clients.)
Pro: Still pretty simple, and avoids polling.
Con: Client has to have URI for the service to call, which may not be convenient. (E.g. the client may be a desktop app rather than a service, firewall may prevent it, etc.)
The client pushes a notification into a message queue, and the client listens to that queue.
Pro: Avoids polling, and client doesn't need endpoints to call.
Con: More work to set up (requires messaging infrastructure).
There are other possibilities but those are typical approaches.
Do you need to differentiate between different requests? If several tasks to perform, you need an ID.
You can do something like the following:
private static final ExecutorService es = Executors.newFixedThreadPool(10);
private static final Map<Long, Future<Void>> map = new HashMap<>();
#GET
#Path("/submit")
public Response submitTask() {
long id = System.currentTimeMillis();
Future<Void> future = es.submit(new Callable<Void>() {
public Void call() throws Exception {
// long task
// you must throw exception for bad task
return null;
}
});
map.put(id, future);
return Response.ok(id, MediaType.TEXT_PLAIN).build();
}
#GET
#Path("/status/{id}")
public Response submitTask(#PathParam("id") long id) {
Future<Void> future = map.get(id);
if (future.isDone()) {
try {
future.get();
return Response.ok("Successful!", MediaType.TEXT_PLAIN).build();
} catch (InterruptedException | ExecutionException e) {
// log
return Response.ok("Bad task!", MediaType.TEXT_PLAIN).build();
}
}
return Response.ok("Wait a few seconds.", MediaType.TEXT_PLAIN).build();
}
This can give you an idea. Remember purge the map of old tasks.
If you want to get the return value of your thread and throw/catch possible exception, consider use Callable rather than Runnable, and it can be used along with ExecutorService which provide more functionality.
Callable : A task that returns a result and may throw an exception.
Implementors define a single method with no arguments called call.
public interface Callable<V> {
V call() throws Exception;
}
My server aperiodically receives join requests from new clients. Upon receiving a new join request, the server runs a service that can be finished real quick. I implement the service as a Java class (called JC) implementing the Runnable interface. I have parameters within the JC class.
At the caller side, I like to have only one instance (or static) of the JC. My question is how to trigger the run() method in the JC every time. Please show me some code. Thanks.
Hope following edits make sense, which is my current implementation.
In the Server that wants to trigger thread executing:
public class Server {
private static RealService mm = new RealService();
private static void update(){
new Thread(mm).start();
}
}
In the Service class:
public class RealService implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
// Do something
}
}
You're question is not really clear here, but I would suggest reading about TimerTask in Java
You could use a socket to listen for incoming requests, the server can spawn a new thread each time there is a request. Once the thread completes, you should intimate the client.
You could read about how a concurrent server works.