Since JavaMail version 1.6.0 classes Store and Folder (amongst Transport) should implement AutoClosable interface.
I did not find any examples of someone using JavaMail API with auto-closable.
After a few tests I am not sure how to exactly use this feature as I have discovered a strange(?) behavior.
I am using the dependency com.sun.mail:javax.mail:1.6.0
@Test
public static void test() {
Session session = ...;
Intger countOfMessages;
try(Store store = session.getStore("imap");) {
store.connect("<host>", "<user>", "<password>");
try(Folder folder = store.getFolder("inbox");) {
folder.open(Folder.READ_ONLY);
count = folder.getMessages().
}
}
Assert.assertEquals(0, count);
}
So far everything works fine.
But if I change the name of the folder to some incorrect value (store.getFolder("_no_folder_with_this_name_")
) then I get a
javax.mail.FolderNotFoundException: _no_folder_with_this_name_ not found
which is perfectly fine but this exception has a suppressed exception
Suppressed: java.lang.IllegalStateException: This operation is not allowed on a closed folder
I do see why this exception is thrown. The try(Folder folder = store.getFolder(...)
throws the FolderNotFoundException, therefor the opening of the folder never happens and in the close method the folder is not open. But personally I would not expect this suppressed exception. As a second test I tried to leave the inner try block empty (try(Folder folder = store.getFolder("inbox");) {}
) so that the folder is not going to be opened. Even in this situation the IllegalStateException is thrown.
Prior to version 1.6.0 I used a finally statement to close a folder by myself.
finally {
if(folder != null) {
try {
if(folder.isOpen()) {
folder.close(false);
}
}
catch(MessagingException me) { LOG.warn(...); }
if(store != null) {
try {
store.close();
}
catch(MessagingException me) { LOG.warn(...); }
}
}
Am I doing something wrong or is this behavior a bug?
Try to restructure the code as:
@Test
public static void test() {
Session session = ...;
Intger countOfMessages;
Store store = session.getStore("imap");
store.connect("<host>", "<user>", "<password>");
try (store) {
//try(Store s = store) //For pre JDK9
Folder folder = store.getFolder("inbox");
folder.open(Folder.READ_ONLY);
try (folder) {
count = folder.getMessages();
}
}
Assert.assertEquals(0, count);
}
The close method balances with the connect and open. Calling getStore/getFolder doesn't mean there is an active connection. If would be cleaner if we made autoclosable calls less hostile.