0

I'm new to Java's AutoClosable interface (but not new to Java). I'm trying to force client code which requests an instance of WebDriver to close the driver after it finishes using it (by calling driver.quit())

I want a way to force any method that instantiates instance of WebDriver to close it.

So I created a new class that implements AutoClosable:

public class WebDriverLauncher implements AutoCloseable {

WebDriver driver;

public WebDriverLauncher()
{
    driver = new FirefoxDriver();
}

public WebDriver getDriver()
{
    return driver;
}



@Override
public void close() throws Exception {
    driver.quit();

    }

}

Now instead of instantiating WebDriver directly (WebDriver driver = new FirefoxDriver()) I'm instantiating instance of this class and have it return an instance of WebDriver such as in the following example:

public WebDriver launchDriver()
{
    WebDriverLauncher webDriverLauncher = new WebDriverLauncher();

    WebDriver driver = webDriverLauncher.getDriver();

    return driver;
}

When I do this I receive a warning/error: Resource leak: 'webDriverLauncher' is never closed

Since I cannot close the resource within this method because the resource (i.e, WebDriver) is being used in the caller method I want to force the caller of launchDriver() to close the driver.

So instead I decided to have the method return an instance of WebDriverLauncher - such as in the following example:

public WebDriverLauncher launchDriver()
{
     WebDriverLauncher webDriverLauncher = new WebDriverLauncher();
     return webDriverLauncher;
}

This way the caller will have access to driver (by calling webDriverLauncher .getDriver() ) and be warned to close the resource (so I thought).

However, when I tried this, the warning message disappeared entirely. In other words, I no longer see the warning to close resource - neither in the launchDriver() class/method nor in the caller/client class (As I mentioned, I want the warning to appear so whoever calls this method is warned to close resource)

What I'm trying to understand is the following:

1) Why isn't the warning propagated up to the caller class (if the resource has never been closed)?

2) Why does the warning disappear when I return webDriverLauncher but not when I return driver?

3) Is there a way to modify the code to force the warning to propagated up the caller? (so as to warn the caller of this method to close the resource)

4) If this cannot be done, what can be done to force the client to close WebDriver?

Thanks!

S.O.S
  • 848
  • 10
  • 30
  • 1
    read the javadocs *The close() method of an AutoCloseable object is called automatically when exiting a try-with-resources block* – Scary Wombat May 11 '18 at 02:03
  • What's wrong with avoiding `AutoCloseable` and just using `driver.quit();`? – JeffC May 11 '18 at 04:24
  • ScaryWombat: which one of the 3 questions did you answer? I've read the docs. @JeffC I'm calling this method from dozens of other methods and each method passes driver to many different functions.. by the time the programmer is done with WebDriver he may forget to close it.. so I want to enforce it.. and I want it to be enforced in one central location.. – S.O.S May 11 '18 at 15:40
  • If you are using JUnit or TestNG you can create a method that closes the driver instance and label it with an attribute AfterClass, AfterMethod, etc. That should do what you want without the `AutoClosable`. If you don't want to do that or can't, it's a training issue. Make sure everyone knows to close the driver and provide a single method they can call. Do code reviews and add that to the checklist of things to validate before they can check in. – JeffC May 11 '18 at 15:44
  • @JeffC Thanks! I will look into JUnit and TestNG. I'm already issuing a warning to close browser when someone hovers over the function. However, I thought I might be able **enforce** this somehow using `AutoClosable` but apparently this is not possible.. – S.O.S May 11 '18 at 15:50

2 Answers2

1

I am late for this question. But here is my take: If we want to force client to use resource carefully, we can restrict the resource creation (private constructor plus disable reflection access by enabling property -Djava.security.manager for jar) and allow clients to only provide method to be called on that resource to the Resource factory.

public class MyResource implements AutoCloseable {
    public static class ResourceFactory {
        public static void useResourceSafely(Consumer<MyResource> work) {
            try(MyResource res = new MyResource()) {
                work.accept(res);
            }
            catch(Exception e) {
                e.printStackTrace();
                //you may even check for Suppressed exceptions
            }
        }
    }

    private MyResource() {
        System.out.println("Resource created");
    }
    public void doWork() {
        System.out.println("resource in use");
    }
    @Override
    public void close() throws Exception {
        System.out.println("Closing myResource");
        
    }
}

Client code may look like this:

public static void main(String[] args) throws Exception {
    ResourceFactory.useResourceSafely(s -> {
        s.doWork();
        System.out.println("Check 1");
        s.doWork();
        System.out.println("Check 2");
    });
}

This might not be recommended way, but just an attempt to do so.

Quirin F. Schroll
  • 1,302
  • 1
  • 11
  • 25
mkRuby009
  • 63
  • 2
  • 9
-1

Using Try-with-resources statement

 try (WebDriverLauncher webDriverLauncher = new WebDriverLauncher(){
     //Your Code Here
 }//webDriverLauncher.close() will be called after here weather throw any exception in try...catch block or not.

In other worlds, AutoClosable interface is a constraint to determine which type can be used in Try-with-resources statement

Hello World
  • 129
  • 7
  • 1
    Sorry but this does not answer the question. I know about try with resource.. Please re-read the 3 specific question in OP. Thanks! – S.O.S May 11 '18 at 15:51