Using multithreading get response from different urls - java

I am making an ajax call to a Java servlet which gets response from different urls and manipulate the data before sending back. Now as there are many urls, to speed up the process rather than sequential processing I have used CountDownLatch and made a class for each url response(which I will use for multithreading). I am not able to understand how to send data back from each response class to the main servlet so that I can manipulate and send back the data to ajax call.
Here's the doget() of my servlet which is called through ajax call.
private static CountDownLatch _latch;
private static int N = 2;
_latch = new CountDownLatch(N);
try {
new Thread(new FirstUrl(_latch)).start();
new Thread(new SecondUrl(_latch)).start();
_latch.await();
}
catch (InterruptedException e) {
e.printStackTrace();
}
Here are the url response classes.
public class SecondUrl implements Runnable {
private CountDownLatch _latch = null;
public SecondUrl(CountDownLatch _latch) {
this._latch = _latch;
}
public void run() {
URI uri;
try {
uri = new URI("http://url1.com");
JSONTokener tokener = new JSONTokener(uri.toURL().openStream());
JSONObject root = new JSONObject(tokener);
_latch.countDown();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Similarly, there is another class with a different url. How to send the JSONObject result back to servlet, so that I can manipulate it.
I am new to multithreading so I might be wrong about any approach. Feel free to point out. Thanks.

Make use of the Callable instead of Runnable. Look at Future interface.

One (of the many) way (to pass result back from your threads) is to pass to your threads a reference to a ArrayBlockingQueue that is initialized in your main thread. The result can be added to the queue. In the main thread, you can either process as the data becomes available or process at the end (after you finish you _latch.await()).

try using a synchronized method to 'join' result in each individual thread, Using Runnable is fine.
And you don't need a second class for SecondUrl. you can use a single class and you can pass the url as a parameter to the class.

Related

Java: gRPC with FutureStub and ListenableFuture

I'm learning gRPC with Java and as an example I've defined three request types (cuboid, sphere and cylinder) and a single response type (String) where I put message about the calculated volume of a specific geometry. I followed this example, which use blocking stub on the client side and the program runs correctly. However, I want to try the asynchronous approach, so here is my client side code, written with newFutureStub and ListenableFuture:
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost",8080)
.usePlaintext()
.build();
GeometryServiceGrpc.GeometryServiceFutureStub stub = GeometryServiceGrpc.newFutureStub(channel);
ListenableFuture<Response> cuboidResp = stub.calcCuboidVol(CuboidVolumeRequest.newBuilder()
.setLength(2)
.setWidth(3)
.setHeight(4)
.build());
cuboidResp.addListener(() -> {
try {
System.out.println(cuboidResp.get().getResponse());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}, command -> {
command.run();
});
ListenableFuture<Response> sphereResp = stub.calcSphereVol(SphereVolumeRequest.newBuilder()
.setRadius(2)
.build());
sphereResp.addListener(() -> {
try {
System.out.println(sphereResp.get().getResponse());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}, command -> {
command.run();
});
ListenableFuture<Response> cylinderResp = stub.calcCylinderVol(CylinderVolumeRequest.newBuilder()
.setRadius(2)
.setHeight(3)
.build());
cylinderResp.addListener(() -> {
try {
System.out.println(cylinderResp.get().getResponse());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}, command -> {
command.run();
});
channel.shutdown();
}
Since we must use ListenableFuture I attach its method addListener() to each return instance of a specific geometry method (the Response message has a single string field called response). Basically, the desired result is just to print the calculations once they're ready and that's why a System.out.println is called in the runnable part. Although the program gets executed successfully, nothing is printed. But if check a specific geometry, then all results appear to the console. Example:
if(!cylinderResp.isDone()) {
try {
cylinderResp.get().getResponse();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
Does this means that the program terminates before the asynchronous part is completed? And is the executable part (commnad) written correctly (I searched and found out that this part can be executed by a ExecutorService if we want the code to be run on different thread(s) - not a requirement in my case)?
Does this means that the program terminates before the asynchronous part is completed? Yes, that's right, you should wait it execute complete by call cylinderResp.get() or channel.awaitTermination(5, TimeUnit.SECONDS);
And is the executable part (commnad) written correctly, If you want run task in specify thread pool you should add a ExecutorService, or it will executed by default thread pool.
For completely asynchronous you should use StreamObserver.
For more detail of how to use gRPC in Java you can reference my code helloworlde/grpc-java-sample

JMeter does not execute Java code correctly if it's ran as .jar file from command line

I'm designing JMeter scenario which implies executing a certain .jar file via OS Process Sampler element. My Java code has while loop which basically checks a certain mailbox for a letter with a certain subject. Loop waits until finds one (emails are always delivered with roughly 3 minutes delay), parses it and writes some data to .txt file.
If I run this .jar directly from cmd then the code works as expected. But if I run it via JMeter OS Process Sampler then it never creates a file for me. I do see that email is delivered to inbox, so expect it to be parsed and .txt created.
At first I suspected that JMeter finishes Java scenario without waiting for while loop to execute. Then I put OS Process Sampler in a separate Thread and added a huge delay for this thread in order to wait and make 100% sure that email is delivered and Java only need to parse it but it does not help.
View Results Tree never shows any errors.
Here is my OS Process Sampler: https://www.screencast.com/t/LomYGShJHAkS
This is what I execute via cmd and it works as expected: java -jar mailosaurJavaRun.jar email533.druzey1a#mailosaur.in
And here is my code (it does not looks good but it works):
public class Run {
public static void main(String[] args) {
MailosaurHelper ms = new MailosaurHelper();
String arg1 = ms.getFirstLinkInEmail(args[0]);
BufferedWriter output = null;
try {
File file = new File("url.txt");
output = new BufferedWriter(new FileWriter(file));
output.write(arg1);
} catch ( IOException e ) {
e.printStackTrace();
} finally {
if ( output != null ) {
try {
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class MailosaurHelper {
protected final String API_KEY = "b3e4d2b193b5eb2";
protected final String MAILBOX_ID = "d1uzey1a";
public MailboxApi getEmailBox() {
return new MailboxApi(MAILBOX_ID, API_KEY);
}
public String getFirstLinkInEmail(String email) {
MailosaurHelper ms = new MailosaurHelper();
String link = "";
if (link.equals("") || link.isEmpty()) {
try {
Thread.sleep(3000);
link = ms.getAllEmailsByReceipent(email)[0].html.links[0]
.toString();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return link;
}
public Email[] getAllEmailsByReceipent(String recepient) {
try {
int ifArrayIsEmpty = getEmailBox().getEmailsByRecipient(recepient).length;
while (ifArrayIsEmpty == 0) {
try {
Thread.sleep(3000);
ifArrayIsEmpty = getEmailBox().getEmailsByRecipient(
recepient).length;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (MailosaurException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Email[] listOfEmails = null;
try {
listOfEmails = getEmailBox().getEmailsByRecipient(recepient);
} catch (MailosaurException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return listOfEmails;
}
The bottom line is that I need to parse Mailosaur email, retrieve URL from it and use it further. Any other suggestion on how to do that using Jmeter/Java/Mailosaur are appreciated.
You don't need cmd in here, but if you're adamant to stick with it - use /C key when you call it.
Then, are your sure you're looking for your file in the right place?
According to documentation:
By default the classes in the java.io package always resolve relative
pathnames against the current user directory. This directory is named
by the system property user.dir, and is typically the directory in
which the Java virtual machine was invoked.
Check it thoroughly, BTW - you should see it in your sampler result.

Execute AsyncTask every three seconds

I built one AsyncTask class that returns a specific value. This value changes frequently, so, I need to call my AsyncTask class multiple times to show the value updated.
I'm getting on a different class the result from the AsyncTask.
try {
output = new task().execute(getconversationid).get();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
And when the result from the AsyncTask updates, I call my other Class again to update everything.
private void call() {
new GetContacts().execute(id);
}
...
mobilemessages = contacts.length();
...
myNum = Integer.parseInt(output);
if(myNum != mobilemessages) {
call();
}
My question is how can i set a Timer or a Handler to update my class call(task) every three seconds?
Thank you.
Use Thread.sleep(3000); 3000 is in milliseconds.
Try{
Thread.sleep(3000);
}catch(Exception ex){
}

Java Smack FileTransfer

Okay, I got the following code from the web, and it does work:
#Override
public void fileTransferRequest(FileTransferRequest request) {
// Check to see if the request should be accepted
final IncomingFileTransfer transfer = request.accept();
runnningFileTransfer = transfer;
try
{
final File file = new File("/Users/Akku/Downloads/in2" + request.getFileName());
transfer.recieveFile(file);
t = new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
transfer.recieveFile(file);
System.out.println("DONE?");
} catch (XMPPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.run();
This code runs, and in the case of my 10MB test file it takes quite a lot of time. Sadly, I need to know if the transfer is finished or what the progress is. Funnily, I also got this part (which just sleeps and checks for progress) from the web, when I append it, the file transfer does not work anymore:
while(!transfer.isDone())
{
if(transfer.getStatus().equals(Status.error))
{
System.out.println("ERROR"+transfer.getError() + " EX: " + transfer.getException());
}
else
{
System.out.println("Written: "+transfer.getAmountWritten());
System.out.println("STATUS"+transfer.getStatus());
System.out.println("PROGRESS"+transfer.getProgress());
}
try
{
Thread.sleep(10000);
System.out.println("Waiting...");
}
catch (Exception e)
{
e.printStackTrace();
}
}
Any hint why this might happen? I guess it's something Java, because the above snippet works flawlessly.
The case that works should be throwing an exception. You call receive twice on the transfer object. The second call should produce an exception when it tries to create the file again. The second call, along with the thread creation is not necessary in this case as the transfer() method is asynchronous and has it's own internal threading.
It is hard to say why it doesn't work with your status check, since you don't show where you are doing this check. My suspicion is that you are calling it on the read thread and thus blocking the reading of new packets. Your loop checking for the transfer status should be running in its own thread.

how can i call a throwable method inside a runnable, for creating a new thread

while trying to create a progressbar in android i came across this problem.
i am following this example : http://developer.android.com/reference/android/widget/ProgressBar.html
my problem is that one of my methods i want to call has to be inside a try and catch
how do i do that inside of a runnable?
Runnable SendThread = new Runnable()
{
try
{
GetAndConvertImagesToPdf();
mProgStatus = 30;
mProgress.setProgress(mProgStatus);
title.setText(R.string.sendingTitle);
}
catch (DocumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
};
i get this error:
"Syntax error on token try, delete this token"
how can i resolve this?
thank you
u put the try in the class body its not in any method or block
this is more like it
Runnable SendThread = new Runnable() {
public void run() {
try {
GetAndConvertImagesToPdf();
mProgStatus = 30;
mProgress.setProgress(mProgStatus);
title.setText(R.string.sendingTitle);
}
catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Sorry I am not able to answer your question but I have one advice,Try to explore about AsyncTask it will help you to run a background thread and it will let you update your UI thread as well at same time. however good luck for your current question.
link : http://developer.android.com/reference/android/os/AsyncTask.html
Happy Coding!

Categories