Cjxcz Odjcayrwl
Cjxcz Odjcayrwl

Reputation: 22847

How to declare excpected exception on EJB 3.0?

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

Answers (2)

Archimedes Trajano
Archimedes Trajano

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

Sean Mickey
Sean Mickey

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

Related Questions