Android Room Dao throw checked exception - java

I have a checked exception that I would want my Room DAO method to be able to throw. How can I achieve that?
Here is what I have tried:
public class MyCheckedException extends Exception{
}
#Dao
public abstract class FooDao {
#Transaction
public void methodThatThrowsCheckedException() throws MyCheckedException {
throw new MyCheckedException();
}
}
I am getting build error error: unreported exception MyCheckedException; must be caught or declared to be thrown FooDao_Impl.super.methodThatThrowsCheckedException();.
Edit:
Some additional info: This is how the generated methodThatThrowsCheckedException method looks like
#Override
public void methodThatThrowsCheckedException() {
__db.beginTransaction();
try {
FooDao_Impl.super.methodThatThrowsCheckedException();
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
Is there anyway that I can make the generated code have this as the method signature instead? public void methodThatThrowsCheckedException() throws MyCheckedException

Related

Use a non-mandatory Exception to cause succeed on a junit test in java

I'm looking for a way to cause a succeed through an custom exception without expecting it all the time in junit4. Is this possible with a testrule or something, without touching every single testcase?
I know these options exist but then the exception is expected and the test fails, if no exception is thrown. I want the test to continue even if no exception is thrown and just use the exception to end the test in some special cases through aspectj.
#Test(TestSuccessException.class)
public void testCase() {
...
}
public class TestClass{
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void someTest() {
thrown.expect(MyRuntimeException.class);
...
}
}
As far as the junit4 source code looks, there isn't a way to achieve this.
The only way I found is by customizing the runner itself.
So something like this:
public class CustomTestRunner extends Runner {
private Class testClass;
public CustomTestRunner(Class testClass) {
super();
this.testClass = testClass;
}
#Override
public Description getDescription() {
return Description.EMPTY;
}
#Override
public void run(RunNotifier notifier) {
// Load all methods with #Test annotation from the given class and fire the execution
try {
Object testObject = testClass.getConstructor().newInstance();
for (Method method : testClass.getMethods()) {
if (method.isAnnotationPresent(Test.class)) {
fire(notifier, testObject, method);
}
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void fire(RunNotifier notifier, Object testObject, Method method) throws IllegalAccessException, InvocationTargetException {
notifier.fireTestStarted(Description
.createTestDescription(testClass, method.getName()));
try {
// Call the test method
method.invoke(testObject);
} catch (InvocationTargetException e) {
// method.invoke wraps the original exception with InvocationTargetException
// The original exception is accessible via getCause()
// Check if the type of the original exception is the custom "early exist" exception
// If it doesn't match, throw the exception again; otherwise, ignore and mark the test as successful
if (!(e.getCause() instanceof EndTestEarlyException)) {
throw e;
}
}
notifier.fireTestFinished(Description
.createTestDescription(testClass, method.getName()));
}
}
You can use this by annotating the Test class as follows:
#RunWith(CustomTestRunner.class)
class MyIntegrationTest {
...
}
Note: Runner is the most generic Runner possible.
You could also attempt overriding a more specific runner if you already use one.
Edit:
As you are working with legacy, I intentionally tried not to use newer language features, like generics (Class<?>).
The solution is based on this baeldung article.
Junit5
Last but not least:
This is probably not relevant in your particular case but might be interesting for future readers.
If you manage to upgrade to Junit5, you could handle this within an extension.
You could implement a custom extension like this:
public class IgnoreEndTestEarlyException implements TestExecutionExceptionHandler {
#Override
public void handleTestExecutionException(ExtensionContext context,
Throwable throwable) throws Throwable {
if (throwable instanceof EndTestEarlyException ) {
return;
}
throw throwable;
}
}
And use it like this:
#ExtendWith(IgnoreEndTestEarlyException.class)
public class MyIntegrationTest
I tend to create another annotation (something like #IntegrationTest), put the #ExtendsWith on there, and use the new annotation.
It would be cleaner and easier to add multiple extensions.
You can run Junit4 and Junit5 within the same module, but you must replace all annotations within your integration test suit.
It might not be worth the effort for multiple thousand tests.
For Junit4 I found a better solution for my usecase. Just override the runChild Method from BlockJUnit4ClassRunner and add a try catch for the EndTestEarlyException.
#Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
Description description = describeChild(method);
if (isIgnored(method)) {
notifier.fireTestIgnored(description);
} else {
Statement statement = new Statement() {
#Override
public void evaluate() throws Throwable {
try {
methodBlock(method).evaluate();
} catch (EndTestEarlyException e) {
System.out.println("EndTestEarlyException - ignore");
}
}
};
runLeaf(statement, description, notifier);
}
}

How to new an InvocationException in Java?

How could I new an InvocationException in Java ?
InvocationException needs an ObjectReference in its constructor, I don't know how to create one.
Do you mean InvocationTargetException?
From the API: Is a checked exception that wraps an exception thrown by an invoked method or constructor.
Not sure what you try to achieve, maybe share some code and describe your intentions, however if you want to extend this exception then:
package .....;
import java.lang.reflect.InvocationTargetException;
public class SampleException extends InvocationTargetException {
protected SampleException() {
super();
}
public SampleException(Throwable target) {
super(target);
}
public SampleException(Throwable target, String s) {
super(target, s);
}
#Override
public Throwable getTargetException() {
return super.getTargetException();
}
#Override
public Throwable getCause() {
return super.getCause();
}
}
Maybe you want to override getTargetException with something specific to your requirement to catch InvocationTargetException and rethrow with your specific exception?
try{
.....
}catch(InvocationTargetException e){
//Do something with e?
throw new SampleException(); //Rethrow?
}
As I said not much information given.

Java -- thrown exceptions in implemented/overridden methods [duplicate]

The code below gives a checked error to throws Exception:
import java.io.IOException;
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws Exception {}
// ...
}
while the one below compiles fine:
import java.io.IOException;
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws NullPointerException {}
// ...
}
On what logic is Java doing this-- any ideas?
TIA.
The throws keyword indicates that a method or constructor can throw an exception, although it doesn't have to.
Let's start with your second snippet
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws NullPointerException {}
}
Consider
some ref = getSome();
try {
ref.ss99();
} catch (IOException e) {
// handle
}
All you have to work with is with your interface some. We (the compiler) don't know the actual implementation of the object it is referencing. As such, we have to make sure to handle any IOException that may be thrown.
In the case of
SQL2 ref = new SQL2();
ref.ss99();
you're working with the actual implementation. This implementation guarantees that it will never throw an IOException (by not declaring it). You therefore don't have to deal with it. You also don't have to deal with NullPointerException because it is an unchecked exception.
Regarding your first snippet, slightly changed
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws Exception { throw new SQLException(); }
}
Consider
some ref = new SQL2();
try {
ref.ss99();
} catch (IOException e) {
// handle
}
So although you are handling the exception declared in the interface, you would be letting a checked exception, SQLException, escape unhandled. The compiler cannot allow this.
An overriden method must be declared to throw the same exception (as the parent) or one of its subclasses.

exception handling in the implemented method

The code below gives a checked error to throws Exception:
import java.io.IOException;
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws Exception {}
// ...
}
while the one below compiles fine:
import java.io.IOException;
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws NullPointerException {}
// ...
}
On what logic is Java doing this-- any ideas?
TIA.
The throws keyword indicates that a method or constructor can throw an exception, although it doesn't have to.
Let's start with your second snippet
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws NullPointerException {}
}
Consider
some ref = getSome();
try {
ref.ss99();
} catch (IOException e) {
// handle
}
All you have to work with is with your interface some. We (the compiler) don't know the actual implementation of the object it is referencing. As such, we have to make sure to handle any IOException that may be thrown.
In the case of
SQL2 ref = new SQL2();
ref.ss99();
you're working with the actual implementation. This implementation guarantees that it will never throw an IOException (by not declaring it). You therefore don't have to deal with it. You also don't have to deal with NullPointerException because it is an unchecked exception.
Regarding your first snippet, slightly changed
interface some {
void ss99() throws IOException;
}
public class SQL2 implements some {
#Override
public void ss99 () throws Exception { throw new SQLException(); }
}
Consider
some ref = new SQL2();
try {
ref.ss99();
} catch (IOException e) {
// handle
}
So although you are handling the exception declared in the interface, you would be letting a checked exception, SQLException, escape unhandled. The compiler cannot allow this.
An overriden method must be declared to throw the same exception (as the parent) or one of its subclasses.

Exception declaration in inheritance?

package com.rnd.core.java;
import java.io.IOException;
public class TestExceptionInheritance {
public void checkExcpetions () throws ArrayIndexOutOfBoundsException{
System.out.println("Inside TestExceptionInheritance ParentClass");
throw new ArrayIndexOutOfBoundsException();
}
}
package com.rnd.core.java;
import javax.sound.midi.MidiUnavailableException;
public class TestExceptionInheritance2 extends TestExceptionInheritance {
public void checkException () throws MidiUnavailableException {
System.out.println("Hello");
throw new MidiUnavailableException();
}
#Override
public void checkExcpetions() throws StringIndexOutOfBoundsException {
// TODO Auto-generated method stub
//super.checkExcpetions();
System.out.println("HI");
}
public static void main(String[] args) throws Exception {
TestExceptionInheritance obj = new TestExceptionInheritance2();
obj.checkExcpetions();
}
}
I have overriden the checkException Method of the parent class in my subclass but I throw a different exception here.
I want to understand why the compiler allows me to throw an altogether different exception; though I know that the method version would be decided based on the reference type.
-------------------Edit 1---------------------------
I have added an #override notation over the overridden method. Overridden method allows me to throw StringIndexOutOfBoundException and RunTimeException along with ArrayIndexOutOfBoundException but not any other exception like for example Exception.
According to the Exception class hierarchy, both StringIndexOutOfBoundException and ArrayIndexOutOfBoundException are subclasses of IndexOutOfBoundException.
How and why does the compiler allows me to throw StringIndexOutOfBoundException because ArrayIndexOutOfBoundException will be never be caught in StringIndexOutOfBoundException.
Thanks for your help.
The real simple answer is you are not overriding what you think you are. The parent class declares a function public void checkExcpetions () and you have a function public void checkException (). These are two different functions which is why there is no compiler error
Using the #Override tag is one way to have the compiler check that you are overriding what you think you are. In this case if you used the tag there would be an error since you are not overriding a parent method

Categories

Resources