Is there an effective way to use generics in a throws clause? - java

According to
Cannot Create, Catch, or Throw Objects of Parameterized Types (Java Tutorials):
You can, however, use a type parameter in a throws clause:
class Parser<T extends Exception> {
public void parse(File file) throws T { // OK
// ...
}
}
But why would you want to? You can't construct T here. If you inject T after building it outside, isn't its stack trace going to be all wrong? Were they simply documenting a feature that happened to work regardless of it's usefulness?

Why not
class FooParser extends Parser<FooException> {
public void parse(File file) throws FooException {
throw new FooException("Not Supported");
}
}

You could have
public class ExceptionWithPayload<T> extends Exception {
private final T payload;
public ExceptionWithPayload(T payload) {
this.payload = payload;
}
public T getPayload(){
return payload;
}
}
and then in some other class, you could write
throw new ExceptionWithPayload<MyClass>(myObject);
so as to be able to pass any object you like back to the thing that catches the exception, but with type checking in the catch clause.

You can throw checked exceptions where it was not expected with the sneaky throw trick: http://rdafbn.blogspot.hu/2013/07/lomboks-sneaky-throws.html
Or without magic: http://www.mail-archive.com/javaposse#googlegroups.com/msg05984.html

Related

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 8 - throw multiple generic checked exceptions in lambda

In a project I am working at, I have found a class which wraps all methods of its super-class in some elaborate exception handling. It looks similar to that:
public void method1() throws ExceptionA {
String exceptionString = "";
try {
super.method1();
} catch (ExceptionA e) {
exceptionString = // <convert the exception to string in an elaborate way>
throw e;
} finally {
// <an elaborate logger call which uses value of exceptionString>
}
}
public void method2() throws ExceptionB, ExceptionC {
String exceptionString = "";
try {
super.method2();
} catch (ExceptionB | ExceptionC e) {
exceptionString = // <convert the exception to string in elaborate way>
throw e;
} finally {
// <an elaborate logger call which uses value of exceptionString>
}
}
// ... <a bunch of other methods like this>
I immediately though "Wow, how could would it be to have one generic wrapper and just call it in every of these methods. The class would be like 10x shorter!".
So I got to work.
This is where I got stuck:
private interface ThrowingMethod<E extends Exception> {
void run() throws E;
}
public <E extends Exception> void wrapMethod(ThrowingMethod<E> method) throws E {
String exceptionString = "";
try {
method.run();
} catch (Exception e) {
exceptionString = // <convert the exception to string in an elaborate way>
throw e;
} finally {
// <an elaborate logger call which uses value of exceptionString>
}
}
public void method1() throws ExceptionA {
wrapMethod(super::method1); // works
}
public void method2() throws ExceptionB, ExceptionC {
wrapMethod(super::method2); // Error in Eclipse: "Unhandled exception type Exception"
}
// ... <a bunch of other methods like this>
In conclusion, this approach works for methods that throws only one type of checked exception. When method throws multiple checked exceptions, Java assumes that the exception type is Exception.
I tried to add more generic parameters to ThrowingMethod and wrapMethod but it doesn't change anything.
How can I get a functional interface to work with multiple generic exceptions?
When you expand your interface to use two type variables, i.e.
private static interface ThrowingMethod<E1 extends Exception,E2 extends Exception> {
void run() throws E1, E2;
}
public <E1 extends Exception,E2 extends Exception>
void wrapMethod(ThrowingMethod<E1,E2> method) throws E1,E2 {
// same as before
}
the rules regarding the type inference do not change and they are the same for both type variables. E.g. you can still use
public void method1() throws ExceptionA {
wrapMethod(super::method1);
}
as before, as the compiler simply infers the same single exception type for both type variables.
For the method declaring two exceptions, it won’t pick up one for the first type variable and the other for the second; there is no rule which could tell the compiler which exception to use for which type variable.
But you can help the compiler out in this case, e.g.
public void method2() throws ExceptionB, ExceptionC {
wrapMethod((ThrowingMethod<ExceptionB, ExceptionC>)super::method2);
}
which is the best you can get with this approach.
So your goal is just to wrap a bunch of methods with logging? A typical way to handle this is with AOP. You'd just create a single pointcut that matches all those methods, and you wouldn't have a bunch of repeated boilerplate. No need for those interfaces or wrapping methods.

How I can get a list of all possible exceptions of function

How I can scan my code and get all possible throws MyException errorCode's of execute() function?
Errors const:
public enum ErrorId {
OK(1),
REPORT_LIMIT(2),
NOT_UNIQUE_FIELD(3),
INCORRECT_PROPERTY(4);
private int id;
ErrorId(int id) {
this.id = id;
}
}
For example I have 'MyException' :
public class MyException extends Exception {
#Getter
protected final ErrorId errorCode;
public MyException(ErrorId errorCode) {
this.errorCode = errorCode;
}
}
And class with method:
public class MyClass {
public void execute() throws MyException {
//do something 1
...
if(isSomethingWrong1) throw new MyException(ErrorId.REPORT_LIMIT);
executeMethod2();
//do something N
if(isSomethingWrongN) throw new MyException(ErrorId....);
}
public void executeMethod2() throws MyException {
// ...
throw new MyException(ErrorId....)
// ...
}
}
I don't think there's an answer here that you'll like.
Reflection won't work in this case, because it's concerned with types, not values. The compiler can't help you here, either, because if the error code comes in through a variable, then at runtime, all bets are off -- the value could be any possible value of the type you're using. If you're using an enum for the code value, then you have a known list of all possible values, but you won't know which ones are actually used in any particular function without reading that function. A static analysis tool may be of use here, but you'd need to continue running it over time to keep this information up to date.
However, all is not lost. As I said in my second comment, you have another choice -- extract subclasses. Let's consider this definition of your Exception class.
public abstract class MyException extends Exception {
#Getter
protected final ErrorId errorCode;
public MyException(ErrorId errorCode) {
this.errorCode = errorCode;
}
}
It's the same as yours is now, but it's abstract. This class is open for extension. So we could create a subclass ReportLimitException like this:
public class ReportLimitException extends MyException {
public ReportLimitException() {
super(ErrorId.REPORT_LIMIT);
}
}
and another like this, for example:
public class DuplicateFieldException extends MyException {
public DuplicateFieldException() {
super(ErrorId.NOT_UNIQUE_FIELD);
}
}
Now, any given method can advertise which particular exceptions it uses via its throws clause. This is, in fact, why that clause exists.
public void execute() throws ReportLimitException, DuplicateFieldException {
//do something 1
//...
if(isSomethingWrong1) throw new ReportLimitException();
executeMethod2();
//do something N
if(isSomethingWrongN) throw new DuplicateFieldException();
}
At this point, if you advertise the exceptions explicitly, you'll have achieved your goal, at the cost of some potentially long throws clauses (which should actually be a hint to you that the method may be doing too much work anyway). Alternatively if you don't want to advertise every exception like that, you could also use your IDE's "find references" feature to locate every place where those exceptions are created (look for references to the constructors).
And the calling code doesn't even have to be aware of the change. It can continue using code like this:
try {
// stuff that might throw any of your exceptions
} catch (MyException ex) {
switch (ex.getErrorCode()) {
// handle the cases...
}
}

What is type of exception to throw if property is not injected?

If module was not injected, in methodA which type of exception can i throw?
public class Customer{
private String module;
public void methodA(){
if (StringUtils.isBlank(module))
throw new ???
}
}
You can either create your own custom exception, or throw IllegalStateException along with an appropriate message. From the docs:
Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation. (emphasis mine)
Since you don't expect module to be blank, you're in an invalid state and hence this exception would be appropriate to throw in this case IMO.
No Specfic predefined Exception is already there which you can make use of. So you can make a new one like ModuleException:-
public class ModuleException extends Exception {
public ModuleException() { super(); }
public ModuleException(String message) { super(message); }
public ModuleException(String message, Throwable cause) { super(message, cause); }
public ModuleException(Throwable cause) { super(cause); }
}
After creating ModuleException you can throw it in your class like:-
public void methodA(){
if (StringUtils.isBlank(module))
throw new ModuleException("Module is blank but is MANDATORY");
}
I would've said to use NullPointerException but the isBlank method also returns true when it's an empty String. The best option would probably be to make your own Exception (info can be found here). That way you also get complete customization.

How to use Hamcrest in Java to test for a exception?

How do I use Hamcrest to test for an exception? According to a comment in https://code.google.com/p/hamcrest/wiki/Tutorial, "Exception handling is provided by Junit 4 using the expected attribute."
So I tried this and found that it worked:
public class MyObjectifyUtilTest {
#Test
public void shouldFindFieldByName() throws MyObjectifyNoSuchFieldException {
String fieldName = "status";
String field = MyObjectifyUtil.getField(DownloadTask.class, fieldName);
assertThat(field, equalTo(fieldName));
}
#Test(expected=MyObjectifyNoSuchFieldException.class)
public void shouldThrowExceptionBecauseFieldDoesNotExist() throws MyObjectifyNoSuchFieldException {
String fieldName = "someMissingField";
String field = MyObjectifyUtil.getField(DownloadTask.class, fieldName);
assertThat(field, equalTo(fieldName));
}
}
Does Hamcrest provide any additional functionality above and beyond the #Test(expected=...) annotation from JUnit?
While someone asked about this in Groovy (How to use Hamcrest to test for exception?), my question is for unit tests written in Java.
Do you really need to use the Hamcrest library?
If not, here's how you do it with Junit's support for exception testing. The ExpectedException class has a lot of methods that you can use to do what you want beyond checking the type of the thrown Exception.
You can use the Hamcrest matchers in combination with this to assert something specific, but it's better to let Junit expect the thrown exceptions.
public class MyObjectifyUtilTest {
// create a rule for an exception grabber that you can use across
// the methods in this test class
#Rule
public ExpectedException exceptionGrabber = ExpectedException.none();
#Test
public void shouldThrowExceptionBecauseFieldDoesNotExist() throws MyObjectifyNoSuchFieldException {
String fieldName = "someMissingField";
// a method capable of throwing MyObjectifyNoSuchFieldException too
doSomething();
// assuming the MyObjectifyUtil.getField would throw the exception,
// I'm expecting an exception to be thrown just before that method call
exceptionGrabber.expect(MyObjectifyNoSuchFieldException.class);
MyObjectifyUtil.getField(DownloadTask.class, fieldName);
...
}
}
This approach better than the
#Test (expected=...) approach because #Test (expected=...) only
tests if the method execution halts by throwing the given exception,
not if the call you wanted to throw the exception threw one. For example, the test will succeed even if doSomething method threw the MyObjectifyNoSuchFieldException exception which may not be desirable
You get to test more than just the type of the exception being thrown. For example, you could check for a particular exception instance or exception message and so on
The try/catch block approach, because of readability and conciseness.
I couldn't implement it in a nice way if counting assertion error descriptions (probably this is why Hamcrest does not provide such a feature), but if you're playing well with Java 8 then you might want something like this (however I don't think it would be ever used because of the issues described below):
IThrowingRunnable
This interface is used to wrap code that could potentially throw exceptions. Callable<E> might be used as well, but the latter requires a value to be returned, so I think that a runnable ("void-callable") is more convenient.
#FunctionalInterface
public interface IThrowingRunnable<E extends Throwable> {
void run()
throws E;
}
FailsWithMatcher
This class implements a matcher that requires the given callback to throw an exception. A disadvantage of this implementation is that having a callback throwing an unexpected exception (or even not throwing a single) does not describe what's wrong and you'd see totally obscure error messages.
public final class FailsWithMatcher<EX extends Throwable>
extends TypeSafeMatcher<IThrowingRunnable<EX>> {
private final Matcher<? super EX> matcher;
private FailsWithMatcher(final Matcher<? super EX> matcher) {
this.matcher = matcher;
}
public static <EX extends Throwable> Matcher<IThrowingRunnable<EX>> failsWith(final Class<EX> throwableType) {
return new FailsWithMatcher<>(instanceOf(throwableType));
}
public static <EX extends Throwable> Matcher<IThrowingRunnable<EX>> failsWith(final Class<EX> throwableType, final Matcher<? super EX> throwableMatcher) {
return new FailsWithMatcher<>(allOf(instanceOf(throwableType), throwableMatcher));
}
#Override
protected boolean matchesSafely(final IThrowingRunnable<EX> runnable) {
try {
runnable.run();
return false;
} catch ( final Throwable ex ) {
return matcher.matches(ex);
}
}
#Override
public void describeTo(final Description description) {
description.appendText("fails with ").appendDescriptionOf(matcher);
}
}
ExceptionMessageMatcher
This is a sample matcher to make a simple check for the thrown exception message.
public final class ExceptionMessageMatcher<EX extends Throwable>
extends TypeSafeMatcher<EX> {
private final Matcher<? super String> matcher;
private ExceptionMessageMatcher(final Matcher<String> matcher) {
this.matcher = matcher;
}
public static <EX extends Throwable> Matcher<EX> exceptionMessage(final String message) {
return new ExceptionMessageMatcher<>(is(message));
}
#Override
protected boolean matchesSafely(final EX ex) {
return matcher.matches(ex.getMessage());
}
#Override
public void describeTo(final Description description) {
description.appendDescriptionOf(matcher);
}
}
And the test sample itself
#Test
public void test() {
assertThat(() -> emptyList().get(0), failsWith(IndexOutOfBoundsException.class, exceptionMessage("Index: 0")));
assertThat(() -> emptyList().set(0, null), failsWith(UnsupportedOperationException.class));
}
Note that this approach:
... is test-runner-independent
... allows to specify multiple assertions in a single test
And the worst thing, a typical fail will look like
java.lang.AssertionError:
Expected: fails with (an instance of java.lang.IndexOutOfBoundsException and is "Index: 0001")
but: was <foo.bar.baz.FailsWithMatcherTest$$Lambda$1/127618319#6b143ee9>
Maybe using a custom implementation of the assertThat() method could fix it.
I suppose the cleanest way is to define a function like
public static Throwable exceptionOf(Callable<?> callable) {
try {
callable.call();
return null;
} catch (Throwable t) {
return t;
}
}
somewhere and then e.g. call
assertThat(exceptionOf(() -> callSomethingThatShouldThrow()),
instanceOf(TheExpectedException.class));
perhaps also using something like the ExceptionMessageMatcher of this answer.
Since junit 4.13 you can use its Assert.assertThrows, like this:
import static org.junit.Assert.assertThrows;
...
MyObjectifyNoSuchFieldException ex = assertThrows(MyObjectifyNoSuchFieldException.class, () -> MyObjectifyUtil.getField(DownloadTask.class, fieldName));
// now you can go further and assert things about the exception ex
// if MyObjectifyUtil.getField(...) does not throw exception, the test will fail right at assertThrows
In my opinion this sort of exceptions asserting is superior to #Test(expected=MyObjectifyNoSuchFieldException.class) because you can:
further assert things about the exception itself;
assert things about side effects (in your mocks, for example);
continue your test case.
You should use junit-utils, which does contain an ExceptionMatcher that can be used together with Hamcrest's assertThat() method.
Example 1:
assertThat(() -> MyObjectifyNoSuchFieldException.class,
throwsException(MyObjectifyNoSuchFieldException.class));
Example 2:
assertThat(() -> myObject.doStuff(null),
throwsException(MyObjectifyNoSuchFieldException.class)
.withMessageContaining("ERR-120008"));
Additional details here: obvj.net/junit-utils
In addition to the above.
if you change the interfaces to ... extends Exception, you can throw an Error like this:
#Override
protected boolean matchesSafely(final IThrowingRunnable<EX> runnable) {
try {
runnable.run();
throw new Error("Did not throw Exception");
} catch (final Exception ex) {
return matcher.matches(ex);
}
}
trace will look like this:
java.lang.Error: Did not throw Exception
at de.test.test.FailsWithMatcher.matchesSafely(FailsWithMatcher.java:31)
at de.test.test.FailsWithMatcher.matchesSafely(FailsWithMatcher.java:1)
at org.hamcrest.TypeSafeMatcher.matches(TypeSafeMatcher.java:65)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:12)
at org.junit.Assert.assertThat(Assert.java:956)
at org.junit.Assert.assertThat(Assert.java:923)
at
...

Categories

Resources