Java connection with Threads - java

I want to create an App, it can show the newest movies datas, with trailers from Movie Database
I try to connect url, with threads to search the trailers. But its load only the first 38 connect succes, but i need 60. I have no idea why.
Is anyone has?
P.S.: I am sorry my English
private Thread loadTrailers = new Thread(){
#Override
public void run(){
int counter = 0;
String str = new String("");
BufferedReader br = null;
try { // try open source site
URL url = new URL("https://api.themoviedb.org/3/movie/"+id+"/videos?api_key="+myApikey);
br = new BufferedReader(new InputStreamReader(url.openConnection().getInputStream())); // problem with openConnection()
if(br != null){
if((str = br.readLine()) != null){
String[] moviedatas = str.split("\"id\"");
for(int i = 1; i < moviedatas.length && counter < 3;++i){
Pattern isTrailer = Pattern.compile(".*Trailer.*");
Matcher matc_tr = isTrailer.matcher(moviedatas[i]);
if(matc_tr.matches()){
Pattern getKey = Pattern.compile(".*key\":\"(.*)\",\"name.*");
Matcher key = getKey.matcher(moviedatas[i]);
if(key.matches()){
links.add("https://www.youtube.com/watch?v="+key.group(1));
counter++;
}
}
}
}
}
} catch (MalformedURLException e) {
System.err.println("Invalid URL!");
} catch (IOException e) {
System.err.println("Connection failed from trailers.");
} finally {
try {
if(br != null)
br.close();
} catch (IOException e) {
System.err.println("File close not success.");
}
}
}
};

Related

Java - Improve method (try/catch)

I have a method for retrieving some coordinates from a very slow page.
My method works fine but i cant help to feel like it can be greatly improved, specially the try/catch clauses.
The method looks like this:
public void getCoordinates(){
EventQueue.invokeLater(() -> loadingLabel.updateCoordinates(true));
consolePanel.getConsole().append("\nRetrieving coordinates from server\n");
shapes.clear();
URL url = null;
try {
url = new URL("http://TestServlet/");
} catch (MalformedURLException e) {
e.printStackTrace();
consolePanel.getConsole().append(e.toString());
}
try {
URLConnection connection = url.openConnection();
connection.setConnectTimeout(1000);
try (InputStream dataSource = url.openStream()) {
BufferedReader inputStream = new BufferedReader(new InputStreamReader(
dataSource, StandardCharsets.ISO_8859_1));
double xCoordinate;
double yCoordinate;
String line;
while ((line = inputStream.readLine()) != null) {
if(!line.startsWith("#")) {
consolePanel.getConsole().append(line + "\n");
String[] text = line.split(",");
xCoordinate = Double.parseDouble(text[0]);
yCoordinate = Double.parseDouble(text[1]);
xCoordinate = Math.abs(xCoordinate)/4;
yCoordinate = Math.abs(yCoordinate)/4;
String name = text[2];
shapes.add(this.mapPanelState.getNewShape(xCoordinate, yCoordinate, 10, name));
}
}
}
} catch (IOException e) {
e.printStackTrace();
consolePanel.getConsole().append(e.toString());
}
EventQueue.invokeLater(this::repaint);
EventQueue.invokeLater(() -> loadingLabel.updateCoordinates(false));
}
Any help to improve on it would be much appreciated.
Your error handling is the same for both catch clauses. So you may easily merge those.
public void getCoordinates() {
try {
URL url = new URL("http://TestServlet/");
URLConnection connection = url.openConnection();
connection.setConnectTimeout(1000);
try (InputStream dataSource = url.openStream()) {
BufferedReader inputStream = new BufferedReader(new InputStreamReader(dataSource, StandardCharsets.ISO_8859_1));
double xCoordinate;
double yCoordinate;
String line;
while ((line = inputStream.readLine()) != null) {
if (!line.startsWith("#")) {
consolePanel.getConsole().append(line + "\n");
String[] text = line.split(",");
xCoordinate = Double.parseDouble(text[0]);
yCoordinate = Double.parseDouble(text[1]);
xCoordinate = Math.abs(xCoordinate) / 4;
yCoordinate = Math.abs(yCoordinate) / 4;
String name = text[2];
shapes.add(this.mapPanelState.getNewShape(xCoordinate, yCoordinate, 10, name));
}
}
}
} catch (Exception e) {
e.printStackTrace();
consolePanel.getConsole().append(e.toString());
}
EventQueue.invokeLater(this::repaint);
EventQueue.invokeLater(() -> loadingLabel.updateCoordinates(false));
}
Here is my improvement:
try {
URL url = new URL("http://TestServlet/");
URLConnection connection = url.openConnection();
connection.setConnectTimeout(1000);
try (InputStream dataSource = url.openStream()) {
BufferedReader inputStream = new BufferedReader(new InputStreamReader(
dataSource, StandardCharsets.ISO_8859_1));
/*
your logic here
*/
}
} catch (MalformedURLException e) {
e.printStackTrace();
//consolePanel.getConsole().append("URL is malformed! Try with a valid one");
} catch (IOException e) {
e.printStackTrace();
//consolePanel.getConsole().append("....");
} catch (Exception e) {
// runtime exceptions
}
If your action does not change whether it's a MalformedURLException, IOException etc., the following catch block is enough:
catch (Exception e) {
e.printStackTrace();
//consolePanel.getConsole().append(e.toString());
}

Spring Boot - Should I implement multi-threading to resolve this problem?

I've been working on some web project and one of its requests execute command line using Java Process.
This is the method.
#ResponseBody
#RequestMapping(value = "/startTest", method = RequestMethod.POST)
public String startTest(int test_id) {
...
String cmd = "..."
ProcessUtil pu = new ProcessUtil();
try {
pu.execute(cmd);
File file = new File(System.getProperty("user.dir")
+ "\\datas\\cypress\\videos\\examples\\main.spec.js.mp4");
File fileToMove = new File(
".\\\\datas\\\\results\\" + uitest.getTest_filename() + ".mp4");
file.renameTo(fileToMove);
return "success";
} catch (Exception e) {
return "fail";
}
}
And Here is the ProcessUtil.java
public class ProcessUtil {
public static void execute(String cmd) {
Process process = null;
Runtime runtime = Runtime.getRuntime();
StringBuffer successOutput = new StringBuffer();
StringBuffer errorOutput = new StringBuffer();
BufferedReader successBufferReader = null;
BufferedReader errorBufferReader = null;
String msg = null;
List<String> cmdList = new ArrayList<String>();
if (System.getProperty("os.name").indexOf("Windows") > -1) {
cmdList.add("cmd");
cmdList.add("/c");
} else {
cmdList.add("/bin/sh");
cmdList.add("-c");
}
cmdList.add(cmd);
String[] array = cmdList.toArray(new String[cmdList.size()]);
try {
process = runtime.exec(array);
successBufferReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
while ((msg = successBufferReader.readLine()) != null) {
successOutput.append(msg + System.getProperty("line.separator"));
}
errorBufferReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "UTF-8"));
while ((msg = errorBufferReader.readLine()) != null) {
errorOutput.append(msg + System.getProperty("line.separator"));
}
process.waitFor();
if (process.exitValue() == 0) {
System.out.println("success!");
System.out.println(successOutput.toString());
} else {
System.out.println("fail...");
System.out.println(successOutput.toString());
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
try {
process.destroy();
if (successBufferReader != null)
successBufferReader.close();
if (errorBufferReader != null)
errorBufferReader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
The problem that I'm facing is when I open two Windows command windows and execute simultaneously it seemingly works fine. However, when I run that 'startTest' method by requesting to my server simultaneously, it pushes my CPU and RAM to nearly 100% and results seemed odd. I don't know much about multi-threading, but I guess I should execute the command via multiple windows(I think my commands were executed in the same environment and they crashed each other...). Please give me some advice to resolve this problem... Thank you in advance.

Make a Server wait for input from two different controllers

I made a client-server application where the server has to send a list of emails to the client, which after load that into a ListView gives the possibility, through a menuBar, to delete them. In the client all these operations are made in the Data Model (I followed the MVC pattern). This is the server:
class ThreadedEchoHandler implements Runnable {
private Socket incoming;
private String nomeAccount = "";
public void run() {
try {
incoming = s.accept();
} catch (IOException ex) {
System.out.println("Unable to accept requests");
}
contenutoTextArea.append("Connected from: " + incoming.getLocalAddress() + "\n");
textarea.setText(contenutoTextArea.toString());
try {
//PHASE 1: The server receives the email
try {
BufferedReader in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
nomeAccount = in.readLine();
} catch (IOException ex) {
System.out.println("Not works");
}
//PHASE 2: I'm getting all the emails from the files
File dir = new File("src/server/" + nomeAccount);
String[] tmp = new String[100];
int i = 0;
for (File file : dir.listFiles()) {
if (file.isFile() && !(file.getName().equals(".DS_Store"))) {
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
tmp[i++] = line;
}
} catch (IOException ex) {
System.out.println("Cannot read from file");
}
}
}
//PHASE 3: The server sends the ArrayList to the client
PrintWriter out = new PrintWriter(incoming.getOutputStream(), true);
for (int j = 0; j < i; j++) {
out.println(tmp[j]); // send the strings to the client
}
} catch (IOException ex) {
System.out.println("Cannot send the strings to the client");
}
//PHASE 4: Here I loop and wait for the client choise
BufferedReader in;
String op;
try {
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
while ((op = in.readLine()) != null) {
if (op.equals("Elimina")) {
String tmp = in.readLine();
File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
file.delete();
} else if (op.equals("Invia")) {
//...
} else {
//...
}
}
} catch (IOException ex) {
System.out.println("Non so");
} finally {
try {
incoming.close();
} catch (IOException ex) {
System.out.println("Cannot closing the socket");
}
}
}
}
These are the methods of the client:
public void loadData() throws IOException, ClassNotFoundException, ParseException {
try {
s = new Socket("127.0.0.1", 5000);
ArrayList<Email> email = new ArrayList<Email>();
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
Date data;
/* PHASE 1: The client sends a string to the server */
//try {
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println(account); // send the account name to server
/* PHASE 2: The client receives the ArrayList with the emails */
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
String line;
String message[] = new String[5];
for (int j=0; (line = in.readLine()) != null;) {
message[j++] = line;
if (j==5) {
data = format.parse(message[3]);
email.add(new Email((Integer.parseInt(message[0])), message[1], account, message[2], message[4], data));
j=0;
}
}
//Casting the arrayList
emailList = FXCollections.observableArrayList(email);
//Sorting the emails
Collections.sort(emailList, (Email o1, Email o2) -> {
if (o1.getData() == null || o2.getData() == null) {
return 0;
}
return o1.getData().compareTo(o2.getData());
});
/*} finally {
s.close();*/
//}
} catch (SocketException se) {
emailList.setAll(null, null);
}
}
public void deleteMail(Email da_elim) throws IOException {
int id_del = da_elim.getID();
emailList.remove(da_elim);
PrintWriter out = new PrintWriter(s.getOutputStream(), true);
out.println("Elimina");
out.println(id_del);
}
The PHASE 1, 2, 3 of the Server are for the upload of the emails, and work with the loadData() method. Without the PHASE 4 the program works. Now, if I write that loop, the GUI of the client doesn't load and I cannot press on the DELETE button (which should make the input to innescate something (in this the elimination of the file) into that loop. Why the client doesn't load even if they are two different threads? And why without that loop it works?
EDIT: with the Listener class implemented but still doesn't works
//PHASE 4: Here I loop and wait for the client choise
BufferedReader in;
String op;
try {
in = new BufferedReader(new InputStreamReader(incoming.getInputStream()));
/*while ((op = in.readLine()) != null) {
System.out.println("OP: " + op);
if (op.equals("Elimina")) {
String tmp = in.readLine();
contenutoTextArea.append("Ho eliminato la mail ").append(tmp).append(" \n");
textarea.setText(contenutoTextArea.toString());
File file = new File("src/server/" + nomeAccount + "/" + tmp + ".txt");
file.delete();
}
}*/
Listener lis = new Listener(in, new LinkedBlockingQueue<String>());
lis.run();
System.out.println("bbbbb");
} catch (IOException ex) {
System.out.println("Unable to read messages");
} finally {
try {
incoming.close();
} catch (IOException ex) {
System.out.println("Cannot close the socket");
}
}
I think you should run jvisualvm (it's a tool installed with jdk in /bin/ location of your jdk) and look for that Thread lifecycle you create on server. Also check if your Thread don't go through the code and just ends his life skipping waiting for client.
Is this Thread somehow connected with client? Because you cannot run client App. Are they separated? Another think that came to my mind is using
Platform.runLater(()->{
});
if your client GUI is in JavaFX. Use it if you are creating GUI, changing values in fields and anything you do on your GUI. Maybe your server is waiting for user response and after that GUI is built? Which causes that you can't press DELETE button.
I'm not currently able to comment, so I can't ask for clarification, but I think I'm correctly interpreting what's wrong. "The program hangs when it enters a loop that waits for input from two controllers". Assuming I got that part right, the most likely culprit would be that buffered reader is hanging indefinitely because its not receiving input. When I first ran into this issue, I threw it inside its own "receiver" class and used a Queue to bus over anything it received to a loop in my main class. my code looked something like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
public class Listener implements Runnable
{
private BufferedReader br;
private BlockingQueue<String> q;
private boolean shouldClose = false;
public Listener(BufferedReader br, BlockingQueue<String> q)
{
this.q = q;
this.br = br;
}
public void run()
{
loop();
System.out.println("listener has stopped");
}
public void loop()
{
String line = "";
try
{
while((line = br.readLine()) != null && !shouldClose)
{
q.put(line);
}
}
catch (IOException | InterruptedException e)
{
e.printStackTrace();
}
}
public void shutdown()
{
shouldClose = true;
}
}
apologies if I've misunderstood in any way, or missed something in your code.

Android:Hotspot is not detecting all the WiFi devices connected to it (/proc/net/arp)

I am using the following code to scan the wifi devices connected to my Hotspot enabled device. It is detecting almost all the devices except one device.
following is the code snippet
public ArrayList getClientList(boolean onlyReachables, int reachableTimeout) {
BufferedReader br = null;
ArrayList<ClientScanResultSO> result = null;
try {
result = new ArrayList<ClientScanResultSO>();
br = new BufferedReader(new FileReader("/proc/net/arp"));
String line;
while ((line = br.readLine()) != null) {
String[] splitted = line.split(" +");
if ((splitted != null) && (splitted.length >= 4)) {
// Basic sanity check
String mac = splitted[3];
System.out.println("mac is***************"+ mac);
if (mac.matches("..:..:..:..:..:..")) {
boolean isReachable = InetAddress.getByName(splitted[0]).isReachable(reachableTimeout);
String name = InetAddress.getByName(splitted[0]).getHostName();
if (!onlyReachables || isReachable) {
result.add(new ClientScanResultSO(splitted[0], splitted[3], splitted[5], isReachable, name));
}
}
}
}
} catch (Exception e) {
Log.e(this.getClass().toString(), e.getMessage());
} finally {
try {
br.close();
} catch (IOException e) {
Log.e(this.getClass().toString(), e.getMessage());
}
}
return result;
}
I am unable to find the issue with it. Is "/proc/net/arp" not registering all the device details ?
can somebody help me in this...thanks!

Retry a connection on timeout in Java

I have a method (below) that pulls down and returns the source of a webpage as a String. It all works fine and dandy, but when the connection times out, the program throws an exception and exits. Is there a better method to do this that would allow it to try again on timeout, or is there a way to do it within this method?
public static String getPage(String theURL) {
URL url = null;
try {
url = new URL(theURL);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exitprint();
}
InputStream is = null;
try {
is = url.openStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exitprint();
}
int ptr = 0;
StringBuffer buffer = new StringBuffer();
try {
while ((ptr = is.read()) != -1) {
buffer.append((char)ptr);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exitprint();
}
return buffer.toString();
}
Here's a refactoring of your code that should retry the download N times. Haven't tested it though, but it should kick you off in the right direction.
public static String getPage(String theURL) {
URL url = null;
try {
url = new URL(theURL);
} catch (MalformedURLException e) {
e.printStackTrace();
exitprint();
}
for (int i = 0; i < N; i++) {
try {
InputStream is = url.openStream();
int ptr = 0;
StringBuffer buffer = new StringBuffer();
while ((ptr = is.read()) != -1)
buffer.append((char)ptr);
} catch (IOException e) {
continue;
}
return buffer.toString();
}
throw new SomeException("Failed to download after " + N + " attepmts");
}
I think AOP and Java annotations is a good option. I would recommend to use a read-made mechanism from jcabi-aspects:
#RetryOnFailure(attempts = 2, delay = 10)
public String load(URL url) {
return url.openConnection().getContent();
}
Write a wrapper function around it and allow the connect exception to propogate out. Then you can loop calling your existing function while you receive connect exception upto some max retries.
This is better than embedding a for loop in your existing function because it logically separates retry logic from mainline code. And it's easier to read and understand as a result.
Instead of
try {
is = url.openStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exitprint();
}
you can try set longer timeout and you can still handle timeout exception by catching it
try {
URLConnection con= url.openConnection();
con.setConnectTimeout(5000);
con.setReadTimeout(50000);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
in.close();
} catch (SocketTimeoutException e) {
//here you can still handle timeout like try again under certain conditions
}
You could put the whole thing in a while loop:
while (true) {
try {
...
} catch (IOException e) {
continue;
}
return buffer.toString();
}
The return statement will break you out of the loop. You might also want to keep track of the number of attempts and stop after 5-10, for politeness, but that's the basic shape of it.
Edit
The better version, based on comments:
int retries = 10;
for (int i = 0 ; i < retries ; i++) {
try {
...
} catch (IOException e) {
continue;
}
return buffer.toString();
}

Categories

Resources