I am trying to create a folder if it does not exist and then copy a message from another folder to the destination folder. I am finding some strange behaviour that I can not understand. Given the following excerpt:
// messages is an array of Message instances.
// Source is the source folder
// destination is a string of the destination folder.
Folder dest = null;
try {
dest = store.getFolder(destination);
if (!dest.exists()) {
dest.create(Folder.HOLDS_MESSAGES | Folder.HOLDS_FOLDERS);
// Since folder's are not meant to cache I thought I'd get it again
// though this does not work either.
//dest.close(false);
//dest = store.getFolder(destination);
}
dest.open(Folder.READ_WRITE);
// Fails here
source.copyMessages(messages, dest);
source.setFlags(messages, new Flags(Flags.Flag.DELETED), true);
} catch (MessagingException ex) {
throw new MailProcessorException(ex.getMessage(), ex);
} finally {
if (dest != null) {
try {
dest.close(false);
} catch (MessagingException ex) {
System.err.println("Couldn't close destination folder.");
}
}
}
The following behaviour is examined:
If the folder does not exist:
The folder gets created
An exception is thrown at source.copyMessages.
If the folder does exist:
The messages are copied as expected.
Messages are marked for deletion.
I am using JavaMail 1.4.6, also tried with 1.6.5.
This is really strange. Looking at your code and reading the docs, there should be no way that this is happening...
Could it be some problem with the mail server? Some databases use consistency models (see http://en.wikipedia.org/wiki/Eventual_consistency for example) that don't always act the way you'd naively expect. Is there a chance you can try your code on a different mail server? Or, try to put a really long (30 seconds?) Thread.sleep(...) before your copyMessages(...) call and see if that fixes it.
If it does, what is happening is that your server creates the folder in one request, but this creation takes a while to reach the part of the server code that is handling the message copying. Then, unfortunately, I'm not sure if there is much you can do other than a retry if the copying fails or the artificial delay (which sucks).
Aside: The docs seem to say, that you can skip the dest.open(Folder.READ_WRITE); if you like.
Related
I am using Serialization to get persistent storage for my library managing app (I know it is not the right way, but it's the way my professor wants it).
I am using the following code inside my main();
controlador.getBiblioteca().getGestorMaterial().setListaLibros((Modelo.ColeccionLibros) controlador.getSerializador().abrirArchivo("libros.dat"));
My Serializador class has the abrirArchivo("FileName.dat") function (openFile in English).
That function looks like this:
public Object abrirArchivo(String nombreDelArchivo) {
Object retorno = null;
try {
lectorArchivos = new ObjectInputStream(new FileInputStream(
nombreDelArchivo));
retorno = lectorArchivos.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return retorno;
}
Now I am trying to check if the program gets a FileNotFoundException for any of the files. If it does, it should just not deserialize the file and go for the next one: that would just mean there is no book in my library yet.
The problem is, if the line runs, it seems to set my book list using setListaLibros() to null. And whenever I try to access that list, i get a NullPointerException. The list was already initialized as an empty list though, so I just need to leave it alone as long as the "libros.dat" file is not found.
What is the right way to get that done?
I don't know if I understand the problem well. However, as I can see in your code, when an exception FileNotFoundException happens, "retorno" will keep null. That's the reason why you get setListaLibros(null).
And then your list will became null. If you don't want that behavior, you should initialize "retorno" with an empty list instead of null.
You could add a line before this: controlador.getBiblioteca().getGestorMaterial().setListaLibros((Modelo.ColeccionLibros) controlador.getSerializador().abrirArchivo("libros.dat")); which checks if the file exists. If it does not, then it prompts the user. This way, the user knows something went wrong and can act accordingly.
Alternatively, you can make a change in your setListLibros method wherein, if the argument passed is null, then you do not do any assignment.
Personally, I would go with the first option.
As a side note, please break down your code, something like so: controlador.getBiblioteca().getGestorMaterial().setListaLibros((Modelo.ColeccionLibros) controlador.getSerializador().abrirArchivo("libros.dat")) can get hard to read and debug.
There is an aspect that the other answers are not mentioning: why are there no serialized objects when your library is empty?!
What I mean is: you could distinguish between "program runs the first time" (and obviously no serialized data exists) or "program ran before; and thus it fully configures itself from serialized data.
Meaning: "being empty" can be a valid state of a library, too. So another option would be to not use a "special value" (aka "no file with data") to represent that information ... but (de)serialize an empty list.
You could check if the file exist like:
String fileName;
File f1 = new File(fileName);
if (f1.exists()) {
//Do the work
}
Don't know if it is clear from title, I'll explain it deeper.
First of all limitations: Java 1.5 IBM.
This is the situation:
I have spring web service that receives request with pdf document in it. I need to put this pdf into the some input directory that AFP application (not of the importance) monitors. This AFP application takes that pdf, do something with it and returns it to some output directory that I need to monitor. Monitoring of output directory would take some time, probably 30 seconds. Also, I know what is exact file name that I expect to appear in output directory. If nothing appears in 30 seconds than I would return some fault response.
Because of my poor knowledge of web services and multithreading I don't know in which possible problems I can fall into.
Also, searching the internet I realize that most of people recommend watchservice for directory monitoring, but this is introduced in Java 7.
Any suggestion, link, idea would be helpful.
So, the scenario is simple. In a main method, the following actions are done in order:
call the AFP service;
poll the directory for the output file;
deal with the output file.
We suppose here that outputFile is a File containing the absolute path to the generated file; this method returns void, adapt:
// We poll every second, so...
private static final int SAMPLES = 30;
public void dealWithAFP(whatever, arguments, are, there)
throws WhateverIsNecessary
{
callAfpService(here);
int i = 0;
try {
while (i < SAMPLES) {
TimeUnit.SECONDS.sleep(1);
if (outputFile.exists())
break;
}
throw new WhateverIsNecessary();
} catch (InterruptedException e) {
// Throw it back if the method does, otherwise the minimum is to:
Thread.currentThread().interrupt();
throw new WhateverIsNecessary();
}
dealWithOutputFile(outputFile);
}
In my experience and after repeated tests I've done and deep web researches, I've found that major java libraries (either "Apache Commons" or Google.coomons or Jcifs) doesn't predict the case of “cyclic copy” of a file onto a destination differently mapped (denoted with different RootPath according with newer java.nio package Path Class) that,at last end of mapping cycle,resolves into the itself origin file.
That's a situation of data losing, because Outputsream method nor jnio's GetChannel method prevents itself this case:the origin file and the destination file are in reality "the same file" and the result of these methods is that the file become lost, better said the size o file become 0 length.
How can one avoid this without get off at a lower filesystem level or even surrender to a more safe Runtime.exec, delegating the stuff at the underlying S.O.
Should I have to lock the destination file (the above methods not allowing this), perhaps with the aid of the oldest RandomAccessFile Class ?
You can test using those cited major libraries with a common "CopyFile(File origin,File dest)" method after having done:
1) the origin folder of file c:\tmp\test.txt mapped to to x: virtual drive via a cmd's [SUBST x: c:\tmp] thus trying to copy onto x:\test.txt
2) Similar case if the local folder c:\tmp has been shared via Windows share mechanism and the destination is represented as a UNC path ending with the same file name
3) Other similar network situations ...
I think there must be another better solution, but my experience of java is fairly few and so I ask for this to you all. Thanks in advance if interested in this “real world” discussion.
Your question is interesting, never thought about that. Look at this question: Determine Symbolic Links. You should detect the cycle before copying.
Perhaps you can try to approach this problem slightly differently and try to detect that source and destination files are the same by comparing file's metadata (name, size, date, etc) and perhaps even calculate hash of the files content as well. This would of course slow processing down.
If you have enough permissions you could also write 'marker' file with random name in destination and try to read it at the source to detect that they're pointing to the same place. Or try to check that file already exist at destination before copying.
I agree that it is unusual situations, but you will agree that files are a critical base of every IT system. I disagree that manipulating files in java is unusual: in my case I have to attach image files of products through FileChooser and copy them in ordered way to a repository ... but real world users (call them customers who buy your product) may fall in such situations and if it happens, one can not 'blame the devil of bad luck if your product does something "less" than expected.
It is a good practice learning from experience and try to avoid what one of Murphy's Laws says, more' or less: "if something CAN go wrong, it WILL go wrong sooner or later.
Is perhaps also for one of those a reason I believe the Java team at Sun and Oracle has enhanced the old java.io package for to the newest java.nio. I'm analyzing a the new java.nio.Files Class which I had escaped to attention, and soon I believe I've found the solution I wanted and expected. See you later.
Thank for the address from other experienced members of the community,and thanks also to a young member of my team, Tindaro, who helped me in the research, I've found the real solution in Jdk 1.7, which is made by reliable, fast, simple and almost definitively will spawn a pity veil on older java.io solutions. Despite the web is still plenty full of examples of copying files in java using In/out Streams I'll warmely suggest everyone to use a simple method : java.nio.Files.copy(Path origin, Path destination) with optional parameters for replacing destination,migrate metadata file attributes and even try a transactional move of files (if permitted by the underlying O.S.).
That's a really good Job, waited for so long!
You can easily convert code from copy(File file1, File file2) by appending a ".toPath()" to the File instance (e.g. file1.toPath(), file2.toPath().
Note also that the boolean method "isSameFile(file1.toPath(), file2.toPath())", is already used inside the above copy method but easily usable in every case you want.
For every case you can't upgrade to 1.7 using community libraries from Apache or Google is still suggested, but for reliable purpose, permit me to suggest the temporary workaround I've found before:
public static boolean isTheSameFile(File f1, File f2) {//throws Exception{
// minimum prerequisites !
if(f1.length()!=f2.length()) return false;
if (!file1.exists() || !file2.exists()) { return false; }
if (file1.isDirectory() || file2.isDirectory()){ return false; }
//if (file1.getCanonicalFile().equals(file2.getCanonicalFile())); //don't rely in this ! can even still fail
//new FileInputStream(f2).getChannel().lock();//exception, can lock only on OutputStream
RandomAccessFile rf1=null,rf2=null; //the only practicable solution on my own ... better than parse entire files
try {
rf1 = new RandomAccessFile(f1, "r");
rf2=new RandomAccessFile(f2, "rw");
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
}
try {
rf2.getChannel().lock();
} catch (IOException e) {
return false;
}
try {
rf1.getChannel().read(ByteBuffer.allocate(1));//reads 1 only byte
} catch (IOException e) {
//e.printStackTrace(); // if and if only the same file, the O.S. will throw an IOException with reason "file already in use"
try {rf2.close();} catch (IOException e1) {}
return true;
}
//close the still opened resources ...
if (rf1.getChannel().isOpen())
try {rf1.getChannel().close();} catch (IOException e) {}
try {
rf2.close();
} catch (IOException e) {
return false;
}
// done, files differs
return false;
}
I need to check for file creation permissions for specific directory.
I've tried:
try {
AccessController.checkPermission(new FilePermission("directory_path", "write"));
// Have permission
} catch (SecurityException e) {
// Doesn't have permission
}
... but this always throws SecurityException (as far as I've understood this checks not underlying fs permissions but some JVM settings that should be configured explicitly).
Another possible way was to use something like this:
File f = new File("directory_path");
if(f.canWrite()) {
// Have permission
} else {
// Doesn't have permission
}
... but this returns true even if I cannot create file in specified directory (For example I cannot create file in "c:\" when I run my app under user without admin privileges, but f.canWrite() returns true).
In the end I've done hack similar to this:
File f = new File("directory_path");
try {
File.createTempFile("check", null, f).delete();
// Have permission
} catch (IOException e) {
// Doesn't have permission
}
... but this may serve only as a temporary solution since I need to get such permissions for almost all folders on client's fs.
Does anybody know how to get REAL file creation permissions nicely, without causing performance issues and hacks described above?
The best way to test the availability/usability of any resource is to try to use it. In this case, new FileOutputStream(new File(dir, name)). It will throw an IOException if the directory isn't writable, or the file already exists and isn't writable, etc etc etc. The operating system already has to do all those checks when you execute that code: there is no point in trying to duplicate it all, and even if you get it 100% right, which is unlikely, you are still introducing a timing window in which the previously 'true' condition can become 'false' due to asynchronous activity. You have to catch exceptions from the file creation anyway, and write code in the catch block to handle them: why write all that twice?
after creating a file and populating it with that with a thread if the file is in a USB java can't delete it, when I try on disk it deletes the file ok !
Here is the part of the code that create and after an exception when try to delete the file.
if(canExport && fileCreated)
{
//Create the file
this.file.createNewFile();
//Export the data
this.run();
if(possible == false){ // in case writing fails delete the file created.
file.delete();
Export novaTentativa = new Export(plan);
novaTentativa.fileCreator(plan);
}
}
The file is created when the this.file.createNewFile() acts.
When this.run() runs, there is a lot of methods to populate the data and handle exceptions, if one exception is caught it sets the global variable possible to false so I know the file is created but empty in the USB, after that I try to delete it with file.delete();
You mention that you're trying to delete the file "after an exception" - consequently, your approach is on the wrong track and isn't going to work as-is.
If an exception is thrown by earlier methods (e.g. the createNewFile() call), then that exception will immediately propagate upwards, so your file.delete() call won't get a chance to execute. You'd need to wrap the earlier statements in a try block, and put the delete call in the corresponding catch or finally block in order for it to execute when an exception was thrown.
Here's an example of what you might try to do:
if(canExport && fileCreated)
{
//Create the file
this.file.createNewFile();
try
{
this.run();
}
catch (IOException e)
{
try
{
file.delete();
}
catch (IOException ignore) {} // don't want to mask the real exception
// Rethrow the actual exception from run() so callers can handle it
throw e;
}
}
An alternative approach rather than catching IOExceptions would be to have a finally block (which is always run) and then check a condition there, such as your possible flag.
Note as well that I start the try block after the call to createNewFile() - if an exception is thrown in the create file call then the file won't exist to delete at all!
As a file note, adding "a lot of code that asks for the thread to start over" in your error-handling block is probably not the best design. It would be more appropriate to simply consider recovering from IO situations here, and let the exception bubble up to the top and cause the thread/runnable to die. The logic around restarting tasks and/or resurrecting threads would be better positioned with the class that started the threads in the first place (e.g. a thread pool/task executor/etc.). Scattering the logic throughout the code will make it harder to see what any individual class is doing (not to mention that having a class marshall resources to resurrect itself just seems wrong from an OO standpoint).
Try explicitly stating the drive letter, path and folder to access the USB device to create write and read or delete the file. If that does not work then it is possible only a specific operating system utility or proprietory utility can delete the file.
How certain are you that you closed the file when the write failed? I'll bet money that you are missing a finally block somewhere in this.run(). That would result in exactly the behavior you describe - delete() will fail if the file is open (you should check it's return code - File.delete() doesn't throw exceptions if it is unable to delete the file).
If you want to test this, replace this.run() with a super, crazy simple implementation that writes 100 bytes to the file, sets 'possible' to false, then returns. If the file still won't delete, post the code you are using for this simplified version of run() and maybe someone can spot what's going on.