Why does the exception wrapper still ask for try-catch even when adding throws?

I am using the SikuliX API in my personal library. The idea is to only reference my library in external projects, which includes the SikuliX parts I need.

Now SikuliX is throwing the exception FindFailed

that I need. I have tried:

public class FindFailed extends org.sikuli.script.FindFailed {
    FindFailed(String msg) { super(msg); }
}

      

It seemed to make sense. However, when trying to use an operator throws

in one of the methods:

import org.mylibrary.exceptions.FindFailed;

public static boolean clickFinishButton() throws FindFailed {
    pattern = PatternManager.loadPattern("my-image.png");

    screen.wait(pattern, 10);
    region = screen.exists(pattern);
    region.click(pattern);

    return true;
}

      

I am still getting a warning Unhandled exception type FindFailed

. Of course changing it back to original org.sikuli.script.FindFailed

will work, however using try-catch

in an external project would require me to re-add the corresponding SikuliX jar file.

What I would like to do is just wrap the exception FindFailed

that SikuliX throws and uses it internally and externally with my library.

The main purpose of all of this is to wrap my own additional methods, etc., around another API, so when I link to this library, later projects should not link to the SikuliX jar either.

- - - - My Library - - - <—————— External Project
|                      |
|        SikuliX       |
- - - - - - - - - - - - 

      

As of now, I need to do the following:

- - - - My Library - - - <—————— External Project
|                      |                |
|        SikuliX       |                |
- - - - - - - - - - - -                 v
                                  SikuliX (Again)

      


So far I have changed things in the following way, which seems to work.

public class FindFailed extends Exception {
    public FindFailed(Throwable cause) { super(cause); }
}

      

Now I am not distributing third party exclusions. And instead, I keep doing the following:

public static boolean clickNewScan() throws FindFailed {
    pattern = PatternManager.loadPattern("my-image.png");   
    region = screen.exists(pattern);
    try {
        screen.wait(pattern, 60);
        region.click(pattern);
    } catch (org.sikuli.script.FindFailed e) {
        throw new FindFailed(e);
    }
    return true;
}

      

+3


source to share


2 answers


You do this by wrapping all calls in SikuliX with your own interfaces. I don't know SikuliX

, so I'll make a toy example.

package third.party.library;

public class Foo {
    public void doSomething() throws ThirdPartyException {
        // Their code
    }
}

      

Ok, so you want to wrap this functionality regardless of their library.

package juxhin;

public interface FooBehavior {
    public void doSomething() throws MyException;
}

      

Then, when you need their behavior, you can use your own implementation:

package juxhin; // YOU write this class

public class ThirdPartyFooBehavior implements FooBehavior {
    private final Foo foo;

    public FooThirdPartyFooBehavior(Foo theirObject) {
        this.foo = theirObject;
    }

    @Override
    public void doSomething() throws MyException {
        try {
            foo.doSomething();
        } catch (ThirdPartyException e) {
            throw new MyException(e);
        }
    }
}

      



Once you wrap your library behind all your own interfaces, your classes will only depend on your own interfaces, which means you don't have to worry about their exceptions. Their library will be completely removed if you override these interfaces with an independent implementation.

Note that MyException

you shouldn't expand third.party.library.ThirdPartyException

because it won't help your problem; it has to use the constructor Exception(Throwable cause)

and remove it from the class hierarchy org.sikuli.script

.


The bottom line is that you still have to include the code included in SikuliX in some way. This is why tools like Maven exist , so adding a jar link is very easy. For example, if your jar depends on SikuliX

, then when you tell your new project to use your jar, it will automatically add the link SikuliX

without doing anything . You end up with dependency trees that automatically do all of this for you:

Maven screenshot

I personally use Maven, but there are other options like Ivy and Gradle that do the same - I'm not trying to defend any particular tool here, just advocating using any dependency tool.

+5


source


Extending from classes you don't have is never a good idea and should be avoided. Also, this will force everyone who handles your exception to still have a jar containing org.sikuli.script.FindFailed.

A better approach would be an exception like this:

public class MyFindFailedException extends Exception {
    MyFindFailedException(String message, Exception cause) {
        super(message, cause);
    }
}

      



And then use it like this:

public static boolean clickFinishButton() throws MyFindFailedException {
  try {
    pattern = PatternManager.loadPattern("my-image.png");

    screen.wait(pattern, 10);
    region = screen.exists(pattern);
    region.click(pattern);

    return true;
  } catch (FindFailed e) {
    throw new MyFindFailedException("something went wrong", e);
  }
}

      

+1


source







All Articles