Reputation: 22847
I've created my own exception class:
public class ValidationException extends RuntimeException { ... }
I've declared it in EJB interface method:
public interface MyApi {
void save(MyDTO dto) throws ValidationException;
}
Now I've used it in the implementation:
@Stateless
@Local(MyApi.class)
public class MyService implements MyApi {
public void save(MyDTO dto) throws ValidationException {
...
throw ValidationException(errorMessages);
}
}
However, when I call that method:
@Path("/my")
@Stateless
public class MyChannel {
@Inject private MyApi myApi;
public void save(MyDTO dto) {
try{
myApi.save(dto);
} catch (ValidationException ex) {
// do sth with the exception
}
}
}
Instead of expected ValidationException, the EJBException is thrown with the following message:
0000167f BusinessExcep E CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "save" on bean
It surprised me, because the exception is declared in the interface and in the implementation. How else can I declare the exception, in order to be able to use it to communicate errors to the caller?
The whole mayhem happens on the WebSphere 8.5. I'm using EJB 3.0 and WebSphere libraries. The channel is JSON REST channel in the WAR module, which is wrapped in EAR module.
Upvotes: 0
Views: 2644
Reputation: 41220
Use the @ApplicationException
annotation. For example
@ApplicationException
public class ValidationException extends RuntimeException {
private static final long serialVersionUID = 7797343376699439504L;
}
You can use it with RuntimeException
so you don't have to use throws
declarations.
Upvotes: 1
Reputation: 7716
I believe the root of your problem lies in choosing to have your custom ValidationException
extend RuntimeException
. Within Java, RuntimeException
or any subclass of RuntimeException
does not have to be declared using a throws
clause on a method signature. The intent of RuntimeException
is that it is generally used in unrecoverable bug scenarios that are the result of something done incorrectly by the method caller, such as attempting to traverse beyond the end of an array (ArrayIndexOutOfBoundsException
) or passing an invalid parameter (IllegalArgumentException
).
Given that you would like to make your ValidationException
part of the method signature and thereby require the calling client to handle the exception, I suggest the following change:
//Modify your exception so that it
//subclasses Exception (not RuntimeException):
public class ValidationException extends Exception { ... }
You will not have to modify the MyService
interface, because the save
method already declares that it throws
the exception. But this small change will shift the way Java handles ValidationException
so that when the exception is thrown, it will behave in the way you expect (and without the extraneous noise about an "undeclared" exception).
Upvotes: 1