I'm using Spring Boot and Spring Data JPA, and i have a generic method that returns a generic type object and a custom exception that needs to be thrown from the generic method.
Unfortunately, I get an error from the IDE suggesting that I should throw the generic Throwable instead of my custom exception. Whenever I try to throw my exception, I get a compilation error.
The generic method -> Gets one of three client types from the database, or throws an ClientNotFoundException stating that the client wasn't found in db:
public static <T> T isExists(JpaRepository repository, int id, ClientType clientType) throws Throwable {
T fromDB = (T) repository.findById(id).orElseThrow(() -> new ClientNotFoundException("Error getting info from dababase", Calendar.getInstance(), null, clientType));
return fromDB;
}
What seems to be the problem? How can I throw my custom exception from my generic method? Thanks :)
edited:
If I manually throw from method header ClientNotFoundException, the lines go red and the app is not compiling-
The compilation error that I get is:
java: unreported exception java.lang.Throwable; must be caught or declared to be thrown
IDE (using IntelliJ) suggests 3 options:
Convert exception to Throwable
Annotate with #SneakyThrows
try/catch
The suggestions are not the best for me, so I'd like to check other solutions..
Related
Does anyone know why throwing a Throwable or an Exception in a Stream doesn't compile in the code below?
Environment: Win 10 x64, Eclipse 2020-03, openJDK v14
public void myMethod(final boolean myBoolean) throws Throwable {
if (myBoolean) {throw new Exception("Compiler accepts this OK");}
if (myBoolean) {throw new Throwable("Compiler accepts this OK");}
Stream.of("").forEach(s -> {throw new Error("");});
Stream.of("").forEach(s -> {throw new RuntimeException("");});
Stream.of("").forEach(s -> {throw new Exception("Compiler -> Unhandled exception type Exception");});
Stream.of("").forEach(s -> {throw new Throwable("Compiler -> Unhandled exception type Throwable");});
}
I've declared that the Method throws Throwable & outside the Stream it compiles ok, but inside, it seems I can only throw subclasses of Error & RuntimeException.
Short answer is that Exception and Throwable are checked exceptions. The rules for checked exceptions say that they must either be caught within the method (or lambda) in which they are thrown, or they must be declared in the throws list of the method (or functional interface).
(See also: What does "error: unreported exception <XXX>; must be caught or declared to be thrown" mean and how do I fix it? for some background.)
Neither of those things is practical in your example. So you should avoid throwing checked exceptions in that context. Use unchecked exceptions instead; i.e. RuntimeException or subclasses.
Note that it is a bad idea to declare a method as throws Throwable or throws Exception. This effectively forces the caller to deal with1 exceptions that it (typically) has no knowledge of. If you want to use checked exceptions, use ones that are specific to the "exceptional condition" you are signalling. Declare a custom exception if necessary.
1 - ... either by handling them, or declaring them in its method signature!
I have inherited some code from another team which uses
#Test (expectedExceptions = {Exception.class})
everywhere when the code might be throwing a more specific exception.
My understanding is that this is wrong because we are not expecting the right type of exception. But the current owners are saying that they have seen no issue because of this.
Is my understanding correct?
This is poor design, since it could be masking errors other than the one being tested for. As an example, suppose your code should throw a SecurityException on some operation but instead is throwing a NullPointerException because of a naive dereference. Your test would pass when it should fail.
You should always make your matchers as specific as possible, and in this case, that means the most specific exception class that applies.
Exception is Parent class of all types of exception in java, so basically your test will pass if code throws any checked or unchecked exception. But its better to write unit test that will expect a particular type of exception which your code can throw. For e.g. let say your have a method to validateParam
public void validateParam(String param) throws SomeCustomValidationException {
//suppose param is null , now this code will throw NullPointerException
if (param.length() > 2) {throw new SomeCustomValidationException();}
}
and you call it like this
public void businessLogic(String param) {
try {validateParam(param);}
catch(SomeCustomValidationException e){//show error dialog to the user}
}
So although your unit test will pass but your business logic will not work as you expected
I am currently implementing a system in which I am using aspectJ to check whether a user is allowed to call a method or not. My methods look something like this:
#Constrained(
mayUsers = {Constrained.Types.ADMIN,
Constrained.Types.SELLER, Constrained.Types.ORGANIZER}
)
public boolean save() {
/* code */
}
I am able to use AspectJ to intercept the message call and do the check, but if the call is not allowed I want to throw an exception. If I just throw the Exception the user of the method is not informed about the Exception which might be thrown.
Now my question is:
Is it possible to enforce that the every method that has the #Constrained Annotation throws a specific Exception?
Is it possible to enforce that the every method that has the
#Constrained Annotation throws a specific Exception?
No it is not possible to do that right now. But what you can do is that at runtime you can check that all the methods that have this annotation must throw exception. If any of method does not declare throws clause, you can throw some Illegal*Exception to tell the developer that each method must declare throws clause.
You have two solutions:
Compile time annotation checking using APT (Annotation Processing Tool)
Runtime checks (pre-conditions)
I was wondering if anyone could help - I am writing a custom Json serializer, extending from JsonSerializer, and I want to wrap any exceptions that could be thrown in my own custom exception, extended from IOException. However, whenever I run any unit tests (using junit) to confirm that the exception is thrown it is failing, saying that -
Expected: (exception with message a string containing "Unable to serialize!" and an instance of com.cybersource.profile.serializer.MySerializerException)
got: <com.fasterxml.jackson.databind.JsonMappingException: Unexpected IOException (of type com.cybersource.profile.serializer.MySerializerException): Unable to serialize!>
Any idea how to get around this, or is it not possible to throw a custom exception?
Got it sorted - turns out for a custom exception you shouldn't extend from IOException, but JsonProcessingException!
I am newbie to unit testing. I am using TestNG with MyEclipse to develop unit test cases for my application. While doing it I am facing some problems with EasyMock. Here is my code (Name of the class, method names and return types are changed for security reasons but you will get a clear idea what I am trying to achieve here).
public MyClass
{
// This is a method in my class which calls a collaborator which I
// want to mock in my test case
public SomeObject findSomething(SomeOtherObject param) throws Exception
{
SomeOtherObject param a = myCollaborator.doSomething(param);
// Do something with the object and then return it
return a;
}
}
Now here is my test. Now what I actually want to achieve in my test
case is that I want to check that my function (findSomething) properly
throws exception in case some exception is thrown. In future some
other developer can change the signature (throws Exception isn't
really part of method signature) of the method and remove the throws
Exception from my method. So how can I make sure that nobody changes
it?
#Test(dataProvider="mydataProvider", expectedExceptions=Exception.class)
public void MyTest(SomeOtherObject param) throws Exception {
{
EasyMock.expect(myCollaboratorMock.doSomething(param)).andThrow(new Exception());
EasyMock.replay(myCollaboratorMock);
}
I am getting exception
"java.lang.IllegalArgumentException: last
method called on mock cannot throw java.lang.Exception"
What I am
doing wrong here? Can someone shed some light on how to write a test
case for my particular scenario?
The collaborator's doSomething() method doesn't declare that it may throw Exception, and you're telling its mock to throw one. It's not possible.
Exception is a checked exception. It can only be thrown if it's declared in the method signature. If the method has no throws clause, all it can do is throwing runtime exceptions (i.e. RuntimeException or any descendant class).