Spring Webflux - Proper way to throw checked custom exception (not RuntimeException) - java

May I ask what is the proper way to throw checked custom exception in Spring webflux please?
I would like to insist, it is about checked custom exception, like MyException.java, not something like RuntimeException, and it is about throwing exception, not handling exception.
I tried the following :
#Controller
#SpringBootApplication
public class QuestionHowToThrowException {
public static void main(String[] args) {
SpringApplication.run(QuestionHowToThrowException.class);
}
#PostMapping(path = "/question", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<ResponseEntity<QuestionResponse>> question(#RequestBody QuestionRequest questionRequest) {
Mono<FirstStep> firstStepMono = WebClient.create().post().uri("http://firstWebService:8111/getFirstStep")
.body(questionRequest.getThing(), String.class).retrieve().bodyToMono(FirstStep.class);
Mono<SecondStep> secondStepMono = firstStepMono.map(oneFirstStep -> getSecondStepFromFirstStepAfterCheck(oneFirstStep));
return secondStepMono.map(oneSecondStep -> ResponseEntity.ok(new QuestionResponse(oneSecondStep.getSecondThing())));
}
private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException {
if (firstStep.getThingNeedsToCheckCanThrowException().equals("exception")) {
throw new MyException("exception");
} else {
return new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good");
}
}
public class QuestionRequest {
private String thing;
public String getThing() {
return thing;
}
}
public class QuestionResponse {
private String response;
public QuestionResponse(String response) {
this.response = response;
}
}
public class FirstStep {
private String thingNeedsToCheckCanThrowException;
public String getThingNeedsToCheckCanThrowException() {
return thingNeedsToCheckCanThrowException;
}
}
public class SecondStep {
private String secondThing;
public SecondStep(String secondThing) {
this.secondThing = secondThing;
}
public String getSecondThing() {
return secondThing;
}
}
}
This is not possible, since there in an unhandled exception in getSecondStepFromFirstStepAfterCheck method.
If I throw and propagate, private SecondStep getSecondStepFromFirstStepAfterCheck(FirstStep firstStep) throws MyException the lambda caller method is not happy.
What is the cleanest and proper way to throw custom exception in webflux please?
Thank you

Reading through your sample code, it looks like you are trying to introduce some error handling with on your Mono.
You can create an unchecked exception by extending the RuntimeException class. If you want a checked exception that enforces handling, you can simply extend Exception.
public class MyException extends RuntimeException {
public MyException(String msg) {
super(s);
}
}
The cleanest way to throw an exception with the Reactor project is really just to throw it. There are error handling functions that allow you to provide different flows to certain error cases.
The good news is you have several options that provides some flow control for error handling.
Project Reactor provides several of these methods on the Mono object.
doOnError(),onErrorContinue(),onErrorReturn(),onErrorStop(),onErrorMap()
I am not entirely sure what you are trying to achieve with the following sample code.
return Mono.error(new MyException("exception"));
} else {
return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good"));
But this looks like a good case for a onErrorMap() since it looks like you are trying to translate some exception here
return Mono.just(new SecondStep(firstStep.getThingNeedsToCheckCanThrowException() + "good")
.onErrorMap(e -> "translated result");

For our applications, we have our custom base exception extend from RuntimeException. We then have standard exception handling that looks for our custom exception for special handling before returning results back to the end user. This allows us to use normal throws mechanics since we want all exceptions thrown to ripple up the top level of the call.
For performance concerns webflux and reactive are slightly lower performance on a per call basis especially for calls that don't need to do any parallelization. However once load is put onto the system it tends to become more performant primarily related to garbage collection. Overhead from the difference between map and flatMap should be negligible at best.

Related

How to wrap exceptions handling in helper class with lambda expressions

I am having troubles while trying to refactor exception handling logic in an helper class.
My code uses a repository which accesses a database and might throw the custom exception RepositoryException. If such exception is thrown by the repository, I want my code to catch it and set an error label in the graphical user interface (view):
... // more code
try {
existingCourse = repository.findByTitle(course.getTitle()); // <- throws RepositoryException
} catch (RepositoryException e) {
view.showError(e.getMessage(), course);
return;
}
... // some more code
The point is that this code is repeated several times and I would prefer to have it refactored in an helper class.
This is what I came up to after some experiments:
A custom FunctionalInterface called ThrowingSupplier, which represent the code that throws the exception.
A TransactionManager helper class, with a catcher methods that accepts a ThrowingSupplier
This is the related code (BaseEntity is just a base class for entities in my domain, as you might guess):
// ThrowingSupplier.java
#FunctionalInterface
public interface ThrowingSupplier<T extends BaseEntity> {
T get() throws RepositoryException;
}
/* ------------------------------------------------------ */
// ExceptionManager.java
public final class ExceptionManager<T extends BaseEntity> {
private T result;
private String exceptionMessage;
ExceptionManager() {
}
public boolean catcher(ThrowingSupplier<T> supplier) {
try {
clearResult();
clearExceptionMessage();
result = supplier.get();
return true;
} catch (RepositoryException e) {
exceptionMessage = e.getMessage();
}
return false;
}
// public getters and 'clearers' for attributes
...
}
And this is how I am using this now:
...
em = new ExceptionManager();
... // more code
if (!em.catcher(() -> repository.findByTitle(course.getTitle()))) {
view.showError(em.getExceptionMessage(), course);
return;
}
existingCourse = em.getResult();
... // some more code
Now it seems to me that this does not give any advantages with respect to using directly the try catch in every repository invocation. This is mainly because I need both the return value of the repository method and a way to tell the caller if the repository call has been successful. As a variation I tried to add the showError call inside catcher, but then I must pass view and entity in every invocation of catcher, which I do not like very much as it makes the code less readable.
Is there another way to accomplish this in an elegant manner or it is better to leave the try catch in every call to the repository? Also, what is the standard way to deal with this problem?

RestTemplate & ResponseErrorHandler: Elegant means of handling errors given an indeterminate return object

Using a RestTemplate, I am querying a remote API to return an object either of expected type (if HTTP 2xx) or an APIError (if HTTP 4xx / 5xx).
Because the response object is indeterminate, I have implemented a custom ResponseErrorHandler and overridden handleError(ClientHttpResponse clientHttpResponse) in order to extract the APIError when it occurs. So far so good:
#Component
public class RemoteAPI {
public UserOrders getUserOrders(User user) {
addAuthorizationHeader(httpHeaders, user.getAccessToken());
HttpEntity<TokenRequest> request = new HttpEntity<>(HEADERS);
return restTemplate.postForObject(CUSTOMER_ORDERS_URI, request, UserOrders.class);
}
private class APIResponseErrorHandler implements ResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) {
try {
APIError apiError = new ObjectMapper().readValue(response.getBody(), APIError.class);
} catch ...
}
}
private void refreshAccessToken(User user) {
addAuthorizationHeader(httpHeaders, user.getAccessSecret());
HttpEntity<TokenRequest> request = new HttpEntity<>(HEADERS);
user.setAccessToken(restTemplate.postForObject(TOKEN_REFRESH_URI, request, AccessToken.class));
}
}
The challenge is that getUserOrders(), or a similar API call, will occasionally fail with a 'recoverable' error; for instance, the API access token may have expired. We should then make an API call to refreshAccessToken() before re-attempting getUserOrders(). Recoverable errors such as these should be hidden from the user until the same ones have occurred multiple times, at which point they are are deemed non-recoverable / critical.
Any errors which are 'critical' (e.g.: second failures, complete authentication failure, or transport layer failures) should be reported to the user as there is no automatic recovery available.
What is the most elegant and robust way managing the error handling logic, bearing in mind that the type of object being returned is not known until runtime?
Option 1: Error object as a class variable with try / catch in each API call method:
#Component
public class RemoteAPI {
private APIError apiError;
private class APIResponseErrorHandler implements ResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) {
try {
this.apiError = new ObjectMapper().readValue(response.getBody(), APIError.class);
} catch ...
}
}
public UserOrders getUserOrders(User user) {
try {
userOrders = restTemplate.postForObject(CUSTOMER_ORDERS_URI, request, UserOrders.class);
} catch (RestClientException ex) {
// Check this.apiError for type of error
// Check how many times this API call has been attempted; compare against maximum
// Try again, or report back as a failure
}
return userOrders;
}
}
Pros: Clarity on which method originally made the call
Cons: Use of a class variable for a transient value. Lots of boilerplate code for each method that calls the API. Error handling logic spread around multiple methods.
Option 2: User object as a class variable / Error management logic in the ResponseErrorHandler
#Component
public class RemoteAPI {
private User user;
private class APIResponseErrorHandler implements ResponseErrorHandler {
#Override
public void handleError(ClientHttpResponse response) {
try {
APIError apiError = new ObjectMapper().readValue(response.getBody(), APIError.class);
// Check this.apiError for type of error
// Check how many times this API call has been attempted; compare against maximum
// Try again...
getUserOrders();
...or report back as a failure
} catch ...
}
}
Pros: Error management logic is in one place.
Cons: User object must now be a class variable and handled gracefully, because the User object cannot otherwise be accessible within the ResponseErrorHandler and so cannot pass it to getUserOrders(User) as before. Need to keep track of how many times each method has been called.
Option 3: Error management logic outside of the RemoteAPI class
Pros: Separates error handling from business logic
Cons: API logic is now in another class
Thank you for any advice.
Answering my own question: it turns out that there were fallacies in the question itself.
I was implementing a ResponseErrorHandler because I thought I needed it to parse the response even when that response was returned with a HTTP error code. In fact, that isn't the case.
This answer demonstrates that the response can be parsed into an object by catching a HttpStatusCodeException and otherwise using a standard RestTemplate. That negates the need for a custom ResponseErrorHandler and therefore the need to return an object of ambiguous type. The method that is handed the error can catch the HttpStatusCodeException, try to refresh the access token, and then call itself again via recursion. A counter is required to prevent endless recursion but that can be passed through rather than being a class variable.
The downside is that it still requires error management logic spread around the class, along with plenty of boilerplate code, but it's a lot tidier than the other options.
public UserOrders getUserOrders(User user, Integer methodCallCount) {
methodCallCount++;
UserOrders userOrders;
try {
userOrders = restTemplate.postForObject(USER_ORDERS_URI, request, UserOrders.class);
} catch (RestClientException ex) {
APIError apiError = new ObjectMapper().readValue(response.getBody(), APIError.class);
if (methodCallCount < MAX_METHOD_CALLS) {
if (apiError.isType(ACCESS_TOKEN_EXPIRED)) {
refreshVendorAccessTokenInfo(user);
userOrders = getUserOrders(user, methodCallCount);
}
}
}
return userOrders;
}

Receive custom exceptions from Restlet Framework in GWT client

I want to use Exception handling with the Restlet Framework and GWT clients.
The Restlet Framework supports the concept of annotated exceptions as described in this post;
http://restlet.com/company/blog/2015/12/21/exception-handling-with-restlet-framework/
In my project i created a LocationNameException
#Status(value = 409)
public class LocationNameException extends Exception
{
...
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
public LocationNameException(String pMessage, Throwable pCause)
{
super(pMessage, pCause);
}
}
And use this in my ServerResource;
#Override
#Transactional(rollbackOn = LocationNameException.class)
public LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException
{
...
Location lLocation = new Location(pLocationDto);
try
{
LocationDao lLocationDao = getLocationDao();
lLocationDao.persist(lLocation);
}
catch (PersistenceException pPersistenceException)
{
throw new LocationNameException("Location requires unique Name", pPersistenceException);
}
...
return lLocationDto;
}
With the interface
public interface LocationListServerResourceInt
{
...
#Post
LocationDto postLocation(LocationDto pLocationDto) throws LocationNameException;
...
}
This works, in the case of an exception the call returns code 409;
And at the GWT client side onFailure() is called;
private class PostLocationCallback implements AsyncCallback<LocationDto>
{
...
#Override
public void onFailure(Throwable pCaught)
{
mCallback.onFailure(pCaught, mLocationDto);
}
}
But parameter pCaught only contains a ResourceException with the status code 409.
My LocationNameException isn't included in the underlying cause stack.
I need this LocationNameException for appropriate error message handling.
The reason is the generated ServerResourceProxy LocationListServerResourceProxyImpl by the Restlet GWT ClientProxyGenerator;
public void postLocation(LocationDto param1, final LocationDto> callback)
{
...
public void handle(Request request, Response response)
{
if (getClientResource().getStatus().isError())
{
callback.onFailure(new ResourceException(getClientResource().getStatus()));
}
else
{
...
}
I think i have to rewrite the Post method in the ClientProxyGenerator;
The LocationNameException is present in the Response data so the Basic approach using the getResponseEntity() method of the ClientResource class should be possible.
Is this the way to go? Or can i catch the LocationNameException exception somewhere else as suggested by Catching annotated exceptions?
It is really hard to try a different approach because of the generated code. Is there an easy way to circumvent the code generator with custom classes?
As already mentioned the LocationNameException is present in the Response data.
Therefore we can get it, just like a normal entity;
...
public void handle(Request request, Response response)
{
if (getClientResource().getStatus().isError())
{
LocationNameException lLocationNameException = null;
boolean serializationError = false;
try
{
if (response.isEntityAvailable())
{
if (MediaType.APPLICATION_JAVA_OBJECT_GWT.equals(response.getEntity().getMediaType()))
{
lLocationNameException = new ObjectRepresentation<LocationNameException>(
response.getEntity().getText(),
(SerializationStreamFactory) MyLocationListServerResourceProxyImpl.this, false)
.getObject();
}
else
{
throw new IOException("Can't parse the enclosed LocationNameException.");
}
}
}
catch (Throwable e)
{
serializationError = true;
callback.onFailure(new ResourceException(e));
}
if (!serializationError)
{
callback.onFailure(lLocationNameException);
}
}
else
{
...
The ClientProxyGenerator needs to know the exception type (in this case LocationNameException). Therefore we specify the exception in the ClientProxy interface;
#Post
void postLocation(LocationDto pLocationDto, AsyncCallback<LocationDto> pResult) throws LocationNameException;
And use getExceptionTypes() or getGenericExceptionTypes() in the ClientProxyGenerator;
Class<?>[] exceptionTypes = method.getExceptionTypes();
java.lang.reflect.Type[] genericExceptionTypes = method.getGenericExceptionTypes();
Of course not all REST methods use a custom exception. When getExceptionTypes() returns an empty list we just return the good old status code;
callback.onFailure(new ResourceException(getClientResource().getStatus()));
With help of Jerome Louvel and Thierry Boileau i created a new ClientProxyGenerator() that supports custom exceptions towards a GWT client;
Just specify the exception from the interface in the ServerResourceProxy (ClientProxy)
and voilĂ 
It is possible to use this custom ClientProxyGenerator() in your project right away.
Download custom ClientProxyGenerator
And place it in a package on the server (for example package com.ludus.server.util)
In GWT module XML change the ClientProxyGenerator to the new version on the server;
And you're ready to go with your custom exceptions, but it would be nice if this extension would be integrated in the Restlet framework.

Global Exception Handling in Jersey & Spring?

I am developing the RESTful webservices using Jersey & Spring 3.2 along with Open CMIS.
I am not using MVC pattern of Spring and it's just Spring IOC & Jersey SpringServlet, the controller class is something like below code
#GET
#Path("/{objId:.+}")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public statusMsg addObject(#PathParam("objId") String objId{
return repoService.addObject(objId);
}
In the repoService I am performing the business logic to add the object using CMIS, my question is that I am catching around 5 exceptions related to CMIS then the base exception i.e Exception but for every service method I have to repeat it which I don't want to do.
I was searching on Google and found that #ControllerAdvice is the best solution for such problem wheer you can define all the checked & unchecked exceptions and wherever remove all the try catch blocks from the application. But it only work with MVC pattern.
Question 1: Is there a way I can use this in above Jersey-Spring framework?
After more reserach I found that Jersey provides ExceptionMapper to handle customized exception but I want to catch more CMIS exception or default Exception or IO Exception etc.
Question 2: How can I do it with ExceptionMapper?
Question 3: Am I on the correct approach or do you suggest any better approach to handle such issues.
Thanks in advance.
I use jersey2.11 with Tomcat and almost exception handle with ExceptionMapper.
(In domain logic, only DB rollback process use try-catch code.)
I think ExceptionMapper with #Provider automatically choose correct ExceptionMapper. So I suppose this function is satisfied with "I want to catch more CMIS exception or default Exception or IO Exception etc."
This code is my handling ExceptionMapper design code.
1.Some Jersey Root Resource Class
#GET
#Produces("application/json")
public String getUser(#NotNull #QueryParam("id") String id,
#NotNull #QueryParam("token") String token) throws Exception { // This level throws exceptions handled by ExceptionMapper
someComplexMethod(id, token); // possible throw Exception, IOException or other exceptions.
return CLICHED_MESSAGE;
}
2.ExceptionMapper package. com.yourdomain.exceptionmapper
AbstractExceptionMapper.java (All ExceptionMapper class extends this Abstract class)
public abstract class AbstractExceptionMapper {
private static Logger logger = LogManager.getLogger(); // Example log4j2.
protected Response errorResponse(int status, ResponseEntity responseEntity) {
return customizeResponse(status, responseEntity);
}
protected Response errorResponse(int status, ResponseEntity responseEntity, Throwable t) {
logger.catching(t); // logging stack trace.
return customizeResponse(status, responseEntity);
}
private Response customizeResponse(int status, ResponseEntity responseEntity) {
return Response.status(status).entity(responseEntity).build();
}
}
ExceptionMapper.java (At least this mapper can catch any exception which is not define specify exception mapper.)
#Provider
public class ExceptionMapper extends AbstractExceptionMapper implements
javax.ws.rs.ext.ExceptionMapper<Exception> {
#Override
public Response toResponse(Exception e) {
// ResponseEntity class's Member Integer code, String message, Object data. For response format.
ResponseEntity re = new ResponseEntity(Code.ERROR_MISC);
return this.errorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, re, e);
}
}
WebApplicationExceptionMapper.java (Specify WebApplicationException)
#Provider
public class WebApplicationExceptionMapper extends AbstractExceptionMapper implements
ExceptionMapper<WebApplicationException> {
#Override
public Response toResponse(WebApplicationException e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_WEB_APPLICATION);
return this.errorResponse(e.getResponse().getStatus(), re, e);
}
}
ConstraintViolationExceptionMapper.java (Specify Hibernate Validator ConstraintViolationException)
#Provider
public class ConstraintViolationExceptionMapper extends AbstractExceptionMapper implements
ExceptionMapper<ConstraintViolationException> {
#Override
public Response toResponse(ConstraintViolationException e) {
ResponseEntity re = new ResponseEntity(Code.ERROR_CONSTRAINT_VIOLATION);
List<Map<String, ?>> data = new ArrayList<>();
Map<String, String> errorMap;
for (final ConstraintViolation<?> error : e.getConstraintViolations()) {
errorMap = new HashMap<>();
errorMap.put("attribute", error.getPropertyPath().toString());
errorMap.put("message", error.getMessage());
data.add(errorMap);
}
re.setData(data);
return this.errorResponse(HttpStatus.INTERNAL_SERVER_ERROR_500, re, e);
}
}
.. and other specify exception can create ExceptionMapper classes.
In my experience, Exception Mapper is high level idea for focus to domain logic. It could drive out boring scattered try-catch block code from domain logic.
So I hope that you feel the "Yes i am" at Question 3 to resolve the problem at your environment.
you have not used try catch and throw anywhere across the application.
My code design use throws at method like this and this make to manage by ExceptionMapper classes.
public String getUser(#NotNull #QueryParam("id") String id,
#NotNull #QueryParam("token") String token) throws Exception
So in above approach I have created just 1 class for all the exceptions which I could expect and for any unknown exception the base Exception will be there to catch.
Now wherever in my application if any exception occurs it comes to the CentralControllerException and appropriate response with http status code is sent back.
Q.2. Do you foresee any issue in above approach.
I think if simple project or never update/modify project (project lifecycle short time), your one class exception mapper approach ok.
But ... i never take this approach. Simply, if need to manage more exception, this method become big and complex, and hard to read and maintain becoming.
In my policy, OOP should use pleomorphism strategy any level code(class plan, DI plan) and this approach some part aim to drive out if/switch block in code. And this idea make each method short code and simple, clear to "domain logic" and code become to resistant to modify.
So i create implements ExceptionMapper and delegate to DI which ExceptionMapper class manage to exception.
(So DI manage replace your single class If block manage which exception handling, this is typically refactoring approach similar Extract xxx http://refactoring.com/catalog/extractClass.html.
In our discussion case, single class and one method too busy, so extract each ExceptionMapper class approaching and DI call suitable class & method strategy.)
Btw, system processing result is same at present point. But if need to reduce future development cost ,should not took approach one class exception handling plan. Because if give up simply code and refactor status, project code is dead faster.
This is my idea and why this.
regards.
thanks for your reply. I can see you have created multiple classes based on the exception type and behaviour.
Q1. In your services method are you throwing any exception like
public void addObject(String objId) throws WebApplicationException{
}
or you have not used try catch and throw anywhere across the application.
Actually, I have tried something where in my web application I am not using try, catch and throws anywhere and in my CentralControllerException I have mentioned like below:
public class CentralControllerHandler implements ExceptionMapper<Exception> {
#Override
#Produces(MediaType.APPLICATION_JSON)
public Response toResponse(Exception ex) {
if(ex instanceof CmisContentAlreadyExistsException){
log.error(ex);
// send Response status as 400
}
if(ex instanceof IOException){
log.error(ex);
// send Response status as 400
}
return Response;
}
}
So in above approach I have created just 1 class for all the exceptions which I could expect and for any unknown exception the base Exception will be there to catch.
Now wherever in my application if any exception occurs it comes to the CentralControllerException and appropriate response with http status code is sent back.
Q.2. Do you foresee any issue in above approach.

Implementation for user defined Exception

I have been searching online and researching in some books, but the examples given are limited and I still have some doubts in user-defined exception.
Using the following codes as an example:
//Conventional way of writing user-defined exception
class IdException extends Exception
{
public IdException(String s)
{
super(s);
}
}
class Product
{
String id = new String();
public Product(String _id) throws IdException
{
id = _id;
//Check format of id
if (id.length() < 5)
throw(new IdException(_id));
}
}
It seems that the conventional way of writing a user-defined exception is almost always the same. In the constructor of the user-defined exception, we always call super(msg). This triggers a question in me: If most exceptions are implemented this way, what difference are there between all these exceptions?
For example, I can have multiple user-defined exceptions, but all seems to do the same thing without any differences. (There is no implementation in these exceptions, what makes them work?)
Example:
class IdException extends Exception
{
public IdException(String s)
{
super(s);
}
}
class NameException extends Exception
{
public NameException(String s)
{
super(s);
}
}
class ItemException extends Exception
{
public ItemException(String s)
{
super(s);
}
}
QUE: So shouldn't we (for example) implement the checking of id inside the exception class? If not all exception classes just seem to do the same thing (or not doing anything).
Example of implementing the check in an Exception:
class IdException extends Exception {
public IdException(String s)
{
super(s);
//Can we either place the if-statements here to check format of id ?
}
//Or here ?
}
Ideally you should not implement your business logic inside Exception. Exception tells information about exceptional behaviour, And in Custom Exception you can customise that information.
Find the best practice to write Custom Exception.
We have so many Exceptions already defined in java. All do the same thing : to notify user about the problem in code.
Now suppose we have only one Exception, then How we can what error occurs when the exception is thrown. After all, name matters a lot.
To take your example Exceptions, I would create a more elaborate message by formatting the data provided:
public IdException(String id, String detail) {
super(String.format("The id \"%s\" is invalid: %s", id, detail));
}
throw new IdException(_id, "Id too short.");
This way there is no real logic in the IdException class other than providing the given value (id) and a detail message together in the e.getMessage() String so debugging and logging is easy to read and the code itself is also straightforward:
There is something wrong with the Id _id, namely it is too short. Thus we throw it back at the caller.
Also, when you throw different types of Exceptions in a code, it allows caller code to handle each Exception type differently:
try {
getItem(id, name);
} catch (IdException ex) {
fail(ex.getMessage()); // "The Id is bogus, I don't know what you want from me."
} catch (NameException ex) {
warn(ex.getMessage()); // "The name doesn't match the Id, but here's the Item for that Id anyways"
} catch (ItemException ex) {
fail("Duh! I reported to the dev, something happened");
emailToAdmin(ex.getMessage()); // "The Item has some inconsistent data in the DB"
}
class MyException extends Exception{
int x;
MyException(int y) {
x=y;
}
public String toString(){
return ("Exception Number = "+x) ;
}
}
public class JavaException{
public static void main(String args[]){
try{
throw new MyException(45);
}
catch(MyException e){
System.out.println(e) ;
}
}
}
output: Exception Number = 45

Categories