jakarta-mailautocloseable

JavaMail-Folder AutoClosable exception


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?


Solution

  • 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.