how to restart file uploading when an exception occurs - java

I am working on a java application in which I am facing a problem. When I send a file to a server and an exception is thrown, the file is not sent. How can I retry sending the file?
public void uploadtxtFile(String localFileFullName, String fileName, String hostDir)
throws Exception {
File file = new File(localFileFullName);
if (!(file.isDirectory())) {
if (file.exists()) {
FileInputStream input = null;
try {
input = new FileInputStream(new File(localFileFullName));
if (input != null) {
hostDir = hostDir.replaceAll("//", "/");
logger.info("uploading host dir : " + hostDir);
//new
// TestThread testThread=new TestThread(hostDir,input);
// Thread t=new Thread(testThread);
//
// try{
// t.start();
//
// }catch(Exception ex){
// logger.error("UPLOADE start thread create exception new:" + ex);
// }
// // new end
DBConnection.getFTPConnection().enterLocalPassiveMode();
// the below line exeption is come
boolean bool = DBConnection.getFTPConnection().storeFile(hostDir, input);
//input.close();//new comment
if (bool) {
logger.info("Success uploading file on host dir :"+hostDir);
} else {
logger.error("file not uploaded.");
}
} else {
logger.error("uploading file input null.");
}
}catch(CopyStreamException cs)
{ logger.error("Copy StreamExeption is come "+cs);
} catch(Exception ex)
{
logger.error("Error in connection ="+ex);//this is catch where I handle the exeption
}finally {
// boolean disconnect= DBConnection.disConnect();
input.close();
}
} else {
logger.info("uploading file is not exists.");
}
}
}
This is the code and I want to restart the file uploading but I don't have any idea. I tried it using the thread but the exception is thrown again. I also tried to use a while loop, but it loops infinitely and also shows the exception as well as another exception.
Below is the thread code that I use:
public void run() {
System.out.println("Enter Thread TestThread");
DBConnection.getFTPConnection().enterLocalPassiveMode();
// System.out.println("Error in DBConnection ");
//here server timeout error is get
boolean bool1=false;
boolean bool=true;
try {
bool = DBConnection.getFTPConnection().storeFile(hostDir1, input1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//disconnect();
try {
input1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bool) {
System.out.println("File is Uploded");
} else {
while(bool!=true){
try {
DBConnection.getFTPConnection().enterLocalPassiveMode();
bool1=DBConnection.getFTPConnection().storeFile(hostDir1, input1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//disconnect();
try {
input1.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("file not uploaded."+bool1);
bool=bool1;
}
}
}
}
}
Can any one have a solution to how to upload the file to the server?
The exception is shown below:
Software caused connection abort: recv failed
Software caused connection abort: socket write error
org.apache.commons.net.io.CopyStreamException: IOException caught while copying.

Add a static class as below in a class from where you are calling the method which need to be retried:
static class RetryOnExceptionStrategy {
public static final int DEFAULT_RETRIES = 3;
public static final long DEFAULT_WAIT_TIME_IN_MILLI = 2000;
private int numberOfRetries;
private int numberOfTriesLeft;
private long timeToWait;
public RetryOnExceptionStrategy() {
this(DEFAULT_RETRIES, DEFAULT_WAIT_TIME_IN_MILLI);
}
public RetryOnExceptionStrategy(int numberOfRetries,
long timeToWait) {
this.numberOfRetries = numberOfRetries;
numberOfTriesLeft = numberOfRetries;
this.timeToWait = timeToWait;
}
/**
* #return true if there are tries left
*/
public boolean shouldRetry() {
return numberOfTriesLeft > 0;
}
public void errorOccured() throws Exception {
numberOfTriesLeft--;
if (!shouldRetry()) {
throw new Exception("Retry Failed: Total " + numberOfRetries
+ " attempts made at interval " + getTimeToWait()
+ "ms");
}
waitUntilNextTry();
}
public long getTimeToWait() {
return timeToWait;
}
private void waitUntilNextTry() {
try {
Thread.sleep(getTimeToWait());
} catch (InterruptedException ignored) {
}
}
}
Now wrap your method call as below in a while loop :
RetryOnExceptionStrategy errorStrategy=new RetryOnExceptionStrategy();
while(errorStrategy.shouldRetry()){
try{
//Method Call
}
catch(Exception excep){
errorStrategy.errorOccured();
}
}
Basically you are just wrapping you method call in while loop which will
keep returnig true till your retry count is reached to zero say you started with 3.
Every time an exception occurred, the exception is caught and a method is called
which will decrement your retryCount and method call is again executed with some delay.

A general way of working with such application is:
Create a class, say, UploadWorker which extends Callable as the wrapper. Make the wrapper return any error and detail information you need when it fails.
Create a ExecutorService (basically a thread pool) for this wrapper to run in threads.
Submit your UploadWorker instance and then you get a Future. Call get() on the future to wait in blocking way or simply wait some time for the result.
In case the get() returns you the error message, submit your worker again to the thread pool.

Related

Replacing Future<Integer> with Future<Void>

I am writing an application that searches for Java files in a given directory and its subdirectories and writes all the strings from those files in reverse order to a new folder. Each directory and file is handled in a separate thread.
At the moment my program works correctly, but I want to change its behavior.
Right now, the program overwrites the files correctly and outputs the number of overwritten files to the console at the end. I want my program to just overwrite the files and display the line "All files overwritten" at the end. But I don't quite understand how I can change my code and replace Future (I think that's my problem). Here is part of the code from the Main class:
ExecutorService pool = Executors.newCachedThreadPool();
ReverseWritter reverseWritter = new ReverseWritter(dirToSearch, dirToStorePath + "//" + dirToStoreName, pool);
Future<Integer> res = pool.submit(reverseWritter);
try {
System.out.println(res.get() + " files reversed");
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();
Here's the method that overwrites the file:
public boolean reverseWrite(File file) {
if (file.isFile() && file.toString().endsWith(".java")) {
String whereTo = dirToStorePathName + "\\" + file.getName().substring(0, file.getName().indexOf(".java")) + "Reversed" + ".java";
try ( Scanner myReader = new Scanner(file); FileWriter myWriter = new FileWriter(whereTo);) {
while (myReader.hasNextLine()) {
String data = myReader.nextLine();
myWriter.write(new StringBuffer(data).reverse().toString());
myWriter.write(System.getProperty("line.separator"));
}
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
return false;
} catch (IOException e) {
System.out.println("An error occurred.");
e.printStackTrace();
return false;
}
}
return true;
}
And this is the call method (my class implements the Callable interface):
#Override
public Integer call() {
int count = 0;
try {
File[] files = dirToSearch.listFiles();
ArrayList<Future<Integer>> result = new ArrayList<>();
for (File f : files) {
if (f.isDirectory()) {
ReverseWritter reverseWritter = new ReverseWritter(f, dirToStorePathName, pool);
Future<Integer> rez = pool.submit(reverseWritter);
result.add(rez);
} else if (reverseWrite(f)) {
count++;
}
for (Future<Integer> rez : result) {
count += rez.get();
}
}
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
return count;
}
You just need to change the class to implement Callable<Void> and remove the operations which do the counting. Change the return type of call from Integer to Void.
public class ReverseWriterCallable implements Callable<Void> {
#Override
public Void call() throws Exception {
//do stuff
//don't do the counting operations
//when return type is Void you can only return null
return null;
}
}
Or implement Runnable and submit it to the executor service.
public class ReverseWriterRunnable implements Runnable {
#Override
public void run() {
//do stuff
//don't do the counting operations
}
}
Then just don't care about the result of the Future:
try {
res.get();
System.out.println("All files reversed");
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();

Stop thread execution when it calls url.openStream() in a loop

Edit: I know what Thread.interrupt() does.
while (!Thread.currentThread().isInterrupted()) does not exit when I interrupt the thread.
I also tried to catch an exception from url.openStream(); when the
thread is interrupted (desperation, maybe it was a blocking method,
which is not) and exit the loop, without any success.
The application creates a Thread that continuously reads a URL. After 3 seconds that Thread gets interrupted but unfortunately continues to execute.
How to stop the thread from executing?
Code (Main.java, MyRunnable.java):
public class Main {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable("http://ninjaflex.com/");
Thread thread = new Thread(runnable);
thread.start();
sleep(3000);
thread.interrupt();
System.out.println("Thread.interrupt() invoked.");
}
private static void sleep(long timeMilli) {
try {
Thread.sleep(timeMilli);
} catch (Exception e) {
}
}
}
public class MyRunnable implements Runnable {
private String website;
MyRunnable(String website) {
this.website = website;
}
#Override
public void run() {
URL url = createUrl();
if (url != null) {
while (!Thread.currentThread().isInterrupted()) {
sleepOneSec();
readFromUrl(url);
System.out.println("Read from " + website);
}
System.out.println("Script: Interrupted, exiting.");
}
}
private URL createUrl() {
URL url = null;
try {
url = new URL(website);
} catch (MalformedURLException e) {
System.out.println("Wrong URL?");
}
return url;
}
private void sleepOneSec() {
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("Error sleeping");
}
}
private void readFromUrl(URL url) {
InputStream in = null;
try {
in = url.openStream();
} catch (Exception e) {
System.out.println("Exception while url.openStream().");
e.printStackTrace();
} finally {
closeInputStream(in);
}
}
private void closeInputStream(InputStream in) {
try {
in.close();
} catch (IOException e) {
System.out.println("Error while closing the input stream.");
}
}
}
Basically, your MyRunnable thread is interrupted during sleep. InterreuptedException is thrown but catched. By the way, it's a bad habit to catch Exception and you should not do that.
From the javadoc: "The interrupted status of the current thread is cleared when this exception is thrown".
Therefore, your while loop will never see the flag.
Replace the call to the sleepOneSec method with a simple Thread.sleep call. Catch InterruptedException outside your while loop. This will cause the loop to exit naturally:
try {
while (true) {
Thread.sleep(1000);
readFromUrl(url);
System.out.println("Read from " + website);
}
} catch (InterruptedException e) {
System.out.println("Script: Interrupted, exiting.");
}
I removed the MyRunnable.sleepOneSec and your code started to work.

Multi-threaded read from file and execute runnable

WHAT?
I am trying to build a tool that will reads a text file and publishes the text, after doing some string transformation.
HOW?
The tool reads the file line by line and populates a LinkedBlockingQueue. At the same time I initiate multiple threads that will then take a message each from the LBQ, do some processing and publish them.
Main
private static LinkedBlockingQueue<String> lbQueue = new LinkedBlockingQueue<>();
private static Boolean keepPublisherActive = Boolean.TRUE;
public static void main(String[] args) {
try {
tool.initMessagePublish();
tool.searchUsingScanner();
} catch (Exception ex) {
logger.error("Exception in Tool Main() " + ex.toString());
throw ex;
}
}
File Reader
private void searchUsingScanner() {
Scanner scanner = null;
try {
scanner = new Scanner(new File(LOG_FILE_PATH));
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (StringUtils.isNotBlank(line)) {
lbQueue.offer(line);
}
}
} catch (Exception e) {
logger.error("Error while processing file: " + e.toString());
} finally {
try {
if (scanner != null) {
scanner.close();
}
// end thread execution
keepPublisherActive = false;
} catch (Exception e) {
logger.error("Exception while closing file scanner " + e.toString());
throw e;
}
}
}
Multi-threaded Publisher
private void initMessagePublish() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(6);
try {
while (keepPublisherActive || lbQueue.getSize() > 0) {
service.execute(messagePublisher); // messagePublisher implements Runnable
}
} catch (Exception ex) {
logger.error("Multi threaded message publish failed " + ex.toString());
throw ex;
} finally {
service.shutdown();
}
}
THE PROBLEM
The intention behind calling initMessagePublish() fist is that the publisher need not wait for all lines to be read from the file before starting to publish. It should start publishing as soon as something becomes available in the LBQ.
But with the current implementation, the control never comes out of the initMessagePublish and start searchUsingScanner. How do I solve this? Basically, the two methods should execute parallely.
Just start messagePublisher in a new Thread (Line no #5 in Main class):
new Thread(()->tool.initMessagePublish()).start();
It should solve your problem.

A `try catch //this is a workaround` in the method. How should it be rewrtten?

A project source code has a Java method for SQL handling. The method does work, but it uses a questionable workaround: try-catch block at the very end of the method for normal execution. What is the correct way to implement it?
public void run() {
if (running) {
return;
}
running = true;
while(null == Common.server || null == Common.database || !ConnectionsPool.isInitialized()) {
// Wait until the database is set before continuing...
try {
Thread.sleep(1000);
}
catch(Exception ex) {}
}
while(running) {
final Connections cs = ConnectionsPool.getConnections();
Connection c = null;
while(!entries.isEmpty()) {
if (null == c) {
c = cs.getConnection();
}
SQLLogEntry entry = entries.remove();
if (null != entry) {
try {
write(entry, c); //find usages
}
catch (SQLException ex) {
writeLogFile("Could not write entry to SQL", ex);
}
}
}
if (null != c) {
try {
c.commit();
}
catch (SQLException ex) {
writeLogFile("Could commit to SQL", ex);
try {
c.rollback();
}
catch (SQLException ex1) {
}
// log
final StringWriter err = new StringWriter();
ex.printStackTrace(new PrintWriter(err));
EditorTransactionUtil.writeLogFile(err.toString());
// for user
final String msg = "Exception: " + EditorUtil.getErrorMessage(ex.getMessage());
try {
SwingUtilities.invokeAndWait(() -> {
JOptionPane.showMessageDialog(null, msg);
});
}
catch (Throwable ex1) {
}
}
finally {
cs.returnConnection(c);
}
c = null;
}
synchronized(entries) {
try {
entries.wait(1000);
}
catch (InterruptedException ex) {
// This is a workaround to process this loop...
}
}
}
writeLogFile("SQLMsgLogger run loop stopping...");
}
Problems with this code start here.
If(running) return;
running=true;
This is clearly an attempt to make sure that only one thread executes. This is a wrong way to check concurrency. Second tread might kick in right when if check ended, but assignment didn't start yet. You need to use syncronizible interface.
As for the disposed try catch block - as Konrad pointed out it will not be executed without Thread.interrupt() call. It might be dead code left from previous versions.

Blackberry Best way to retry connection if failed?

I have the following code, i want to be able to restart the thread if an exception occurred while processing a request.
The following in the run method of a thread:
int status = httpConn.getResponseCode();
if (status == HttpConnection.HTTP_OK) {
// Is this html?
String contentType = httpConn
.getHeaderField(HEADER_CONTENTTYPE);
boolean htmlContent = (contentType != null && contentType
.startsWith(CONTENTTYPE_TEXTHTML));
InputStream input = s.openInputStream();
byte[] data = new byte[1000];
int len = 0;
int size = 0;
StringBuffer raw = new StringBuffer();
while (-1 != (len = input.read(data))) {
// Exit condition for the thread. An
// IOException
// is
// thrown because of the call to
// httpConn.close(),
// causing the thread to terminate.
if (_stop) {
httpConn.close();
s.close();
input.close();
}
raw.append(new String(data, 0, len));
size += len;
}
// raw.insert(0, "bytes received]\n");
// raw.insert(0, size);
// raw.insert(0, '[');
content = raw.toString();
if (htmlContent) {
content = prepareData(raw.toString());
}
input.close();
} else {
try{
httpConn.close();
}catch (Exception e) {
// TODO: handle exception
}
errorDialog(status+", status code");
retryFeed(getUrl(), "Network error. Retrying...");
}
s.close();
} else {
errorDialog("Sorry Insufficient Network Coverage.");
return;
}
} catch (IOCancelledException e) {
errorDialog(e.getMessage());
retryFeed(getUrl(), "Network error. Retrying...");
} catch (IOException e) {
errorDialog(e.getMessage());
retryFeed(getUrl(), "Network error. Retrying...");
}
What is the safest way to retry the connection if failed?
Thanks.
//New This is the Error thread. That check for errors in the connection... will this help? and is it the most efficient method? thanks..
/Error Thread - Thread to check errors/
private class ErrorThread extends Thread {
private static final int TIMEOUT = 3000; // EVERY 3 Seconds
private boolean hasException = false;
private String _theUrl;
/**
* Stops this thread from listening for messages
*/
private synchronized void stop()
{
hasException =false;
}
/**
* Listens for incoming messages until stop() is called
* #see #stop()
* #see java.lang.Runnable#run()
*/
public void run()
{
try
{
while (true) {
if((hasException==true))
{
// Synchronize here so that we don't end up creating a connection that is never closed.
errorDialog("Will Fetch new");
synchronized(this)
{
hasException=false;
if (!_connectionThread.isStarted()) {
fetchPage(_theUrl);
} else {
createNewFetch(_theUrl);
}
}
}
try {
//errorDialog("No exception.");
sleep(TIMEOUT);
} catch (InterruptedException e)
{
errorDialog("Exceptions"+e.toString()+e.getMessage());
System.exit(1);
//System.exit(0);/*Kill System*/
}
}
}
catch (Exception except)
{
}
}
public void setActive(boolean exception,String url)
{
this.hasException=exception;
this._theUrl=url;
}
}
If the connecrtion fails, typically, you want to close it, pause a small time, and retry. The purpose of the pause is to prevent your device from devoting excessive resources to trying to connect to a server that's having issues.

Categories

Resources