How to handle errors from web service - java

Sorry I am new to Spring and Java and this may be covered lots of times but I wanted to get some advice.
I'm creating a Spring web application which needs to retrieve user data from an existing REST based XML web service. I am going to create a domain object, service and DAO which uses the Spring REST template to invoke the web service.
In the DAO I was going to create a method like this:
public User getUser(String userId)
If there is a problem (for example if the user account is locked or been deleted), the web service returns a 200 response and puts an error code in the XML response. These errors should be displayed in the application and I will need to be able to identify the error so I can show custom error message to the user. What is the recommended way to handle these error, should I:
Define different exceptions (runtime) for each of the error response codes and add these to the method signature
Use a single exception (e.g. UserException) and use different messages.
Do something else
Any help would be highly appreciated.

You want to use different exception for each error type by extending Extension. if you have many different ones, try to group them using class inheritance. An example would make it simpler. Suppose you have these 2 kinds of errors, account deleted and account locked, you would do :
class AccountException
extends Exception {
}
then you extend Account extension for all the errors involving account problems, eg:
class AccountLockedException
extends AccountException {
}
and
class AccountDeletedException
extends AccountException {
}
etc... This way you make it crystal clear and don't have to look through all your exceptions. Not sure I'm clear enough, It's my first answer here. GL!

I would create a single Exception class for a category. For instance, for all user related exceptions, you can create something like below:
This way, it will be clean to catch one exception and verify the error code to find what caused the exception.
public class MyException extends Exception{
public static final int ERR_USER_NOT_FOUND = 101;
public static final int ERR_DB_ACCESS_ERR = 500;
private int errorCode;
public MyException(int errCode){
this.errorCode = errCode;
}
public int getErrorCode() {
return errorCode;
}
}

Related

Should exceptions be used to describe user input errors?

I have a service that saves a tree-like structure to a database. Before persisting the tree, the tree gets validated, and during validation, a number of things can go wrong. The tree can have duplicate nodes, or a node can be missing an important field (such as its abbreviation, full name, or level).
In order to communicate to the service what went wrong, I'm using exceptions. When the validateTree() method encounters a problem, it throws the appropriate exception. The HttpService class then uses this exception to form the appropriate response (e.g. in response to an AJAX call).
public class HttpService {
private Service service;
private Logger logger;
// ...
public HttpServiceResponse saveTree(Node root) {
try {
service.saveTree(root);
} catch (DuplicateNodeException e) {
return HttpServiceResponse.failure(DUPLICATE_NODE);
} catch (MissingAbbreviationException e) {
return HttpServiceResponse.failure(MISSING_ABBREV);
} catch (MissingNameException e) {
return HttpServiceResponse.failure(MISSING_NAME);
} catch (MissingLevelException e) {
return HttpServiceResponse.failure(MISSING_LEVEL);
} catch (Exception e) {
logger.log(e.getMessage(), e. Logger.ERROR);
return HttpServiceResponse.failure(INTERNAL_SERVER_ERROR);
}
}
}
public class Service {
private TreeDao dao;
public void saveTree(Node root)
throws DuplicateNodeException, MissingAbbreviationException, MissingNameException, MissingLevelException {
validateTree(root);
dao.saveTree(root);
}
private void validateTree(Node root)
throws DuplicateNodeException, MissingAbbreviationException, MissingNameException, MissingLevelException {
// validate and throw checked exceptions if needed
}
}
I want to know, is this a good use of exceptions? Essentially, I'm using them to convey error messages. An alternative would be for my saveTree() method to return an integer, and that integer would convey the error. But in order to do this, I would have to document what each return value means. That seems to be more in the style of C/C++ than Java. Is my current use of exceptions a good practice in Java? If not, what's the best alternative?
No, exceptions aren't a good fit for the validation you need to do here. You will likely want to display multiple validation error messages, so that the user can see all the validation errors at once, and throwing a separate exception for each invalid input won't allow that.
Instead create a list and put errors in it. Then you can show the user the list of all the validation errors.
Waiting until your request has gotten all the way to the DAO seems like the wrong time to do this validation. A server-side front controller should be doing validation on these items before they get passed along any farther, as protection against attacks such as injection or cross-site scripting.
TL;DR The Java-side parts you showed us are nearly perfect. But you could add an independent validation check and use that from the client side before trying to save.
There are many software layers involved, so let's have a look at each of them - there's no "one size fits all" answer here.
For the Service object, it's the perfect solution to have it throw exceptions from the saveTree() method if it wasn't able to save the tree (for whatever reason, not limited to validation). That's what exceptions are meant for: to communicate that some method couldn't do its job. And the Service object shouldn't rely on some external validation, but make sure itself that only valid data are saved.
The HttpService.saveTree() should also communicate to its caller if it couldn't save the tree (typically indicated by an exception from the Service). But as it's an HTTP service, it can't throw exceptions, but has to return a result code plus a text message, just the way you do it. This can never contain the full information from the Java exception, so it's a good decision that you log any unclear errors here (but you should make sure that the stack trace gets logged too!), before you pass an error result to the HTTP client.
The web client UI software should of course present detailed error lists to the user and not just a translated single exception. So, I'd create an HttpService.validateTree(...) method that returns a list of validation errors and call that from the client before trying to save. This gives you the additional possibility to check for validity independent of saving.
Why do it this way?
You never have control what happens in the client, inside some browser, you don't even know whether the request is coming from your app or from something like curl. So you can't rely on any validation that your JavaScript (?) application might implement. All of your service methods should reject invalid data, by doing the validation themselves.
Implementing the validation checks in a JavaScript client application still needs the same validation inside the Java service (see above), so you'd have to maintain two pieces of code in different languages doing exactly the same business logic - don't repeat yourself! Only if the additional roundtrip isn't tolerable, then I'd regard this an acceptable solution.
Visible and highly noticeable, both in terms of the message itself and how it indicates which dialogue element users must repair.
From Guru Nielsen,
https://www.nngroup.com/articles/error-message-guidelines/

Intercept Exceptions to Translate it to another language

I am trying to intercept an Exception thrown by my algorithm in Java, and change the text to another language, and show it to the user. Is this possible in java?
Sorry by my English.
You can catch an exception, and then throw a new one of the same type (or a different type if you prefer). Then translate the message from the original exception and pass it into the new exception. Something like the following (not tested):
try {
// do something
}
catch (Exception e) {
throw new Exception(translate(e.getMessage()))
}
public String translate(String message) { /* translation code */ }
Update in response to comment:
If you can modify the application (and particularly if the application uses custom exceptions derived from a few base classes) then you might be able to modify these to retrieve translated messages (but if you could do that, you could build in the translated messages, or full internationalisation, from the start!).
Intercepting and replacing all Exceptions globally is probably not possible, although it looks like you can at least detect them globally using debug hooks - see this answer. It's conceivable that you could modify the Exception message on-the-fly using reflection, but this sounds pretty nasty.
One final possibility is to use Aspect-Oriented Programming (AOP) to compile-in extra behaviour around code that throws an exception (see this question, for example). You'd need to recompile the whole application using AOP tools though, and would probably still need to modify the application code a bit.
I think you want Thread.setDefaultUncaughtExceptionHandler()
This issue had more details if you need them...
swing uncaughtexceptionhandler
You would need to translate the message text of an exception only if your were reporting the message text of exceptions. But doing that is a mistake.
The message was created when the exception was thrown. It therefore at best can provide only very low level information, which can be inappropriate for reporting to a user.
Philosophically, using the message is against the whole point of exceptions, which is to separate the detection and initiation of error handling (the throw part) from completion of handling and reporting (the catch part). Using the message means the message must be good for reporting, which moves responsibility for reporting to the location that should be responsible for only detection and initiation. That is, I'd argue that the getMessage() part of the design of Throwable was a mistake.
Instead of doing that, follow the advice to choose what message to report to the user at the point where your catch the exception. You can internationalize that message use the usual Java text internationalization facilities.
I solved my question with this solution
public class ParamsException extends RuntimeException {
private static final long serialVersionUID = 7161500238672497882L;
public ParamsException() {
super();
}
public ParamsException(String message) {
super(new BaseResourcesBusiness().getException(message));
}
public ParamsException(Throwable cause) {
super(cause);
}
public ParamsException(String message, Throwable cause) {
super(new BaseResourcesBusiness().getException(message), cause);
}
}
the BaseResourceBusiness.getException(message) get the message from a XML or Database to a specific language. So all my exception is created in this mode
public static final class NotFoundInDatabaseException extends ParamsException {
private static final long serialVersionUID = -1595240938885629473L;
public NotFoundInDatabaseException () {
super("Not found in database");
}
}
in the code im using with this mode throw new NotFoundInDatabaseException ()

Validation errors handling from EJB in JSF

I would like to know what is the best way to handle validation errors in medium/big Java EE application.
Suppose I have managed bean and facade as it is below.
class SomeManagedBean {
#EJB
SomeFacade someFacade;
public void performSomeAction() {
(...)
someFacade.businessAction(loggedUser, editedEntity);
(...)
}
}
class SomeFacadeImpl {
public Object businessAction(User user, Entity entity) {
if (!isInCorrectStateToDoAction(entity)) {
// error A
}
(...)
if (!hasRightToDoAction(user, entity)) {
// error X
}
doAction(user, entity);
}
}
I expect that businessAction from SomeFacade should validate their inputs and check if it can do this business action with given arguments. It's because I may use this business method in several places in application and I do not want copy validation code.
Suppose I would like to use FacesMessage to provide to client informations about validation errors.
Some solutions:
exceptions - when something is wrong with arguments I simply throw an Exception
so I have to throw IncorrectStateForActionException, NoRightToDoActionException
why not: I can throw only one exception so I can't notify user about several things: "You don't have rights", (...), "Entity is incorrect state"
beside exception shouldn't be used to provide logic of our application
some Result class
class Result<T> {
T returnedValueFromMethod;
List<ProcessingError> errors;
}
now definition of my business method looks like:
public Result<Object> businessAction(User user, Entity entity)
when something is wrong I add error information to Result
when everything is all right I put returned value to my Result object and return this object
why not: this seems like kind of "error code" in pretty complex structure. Because of that recommendation which tells "change error codes into exception" it's understandable why we would like to avoid it.
we can do validation in facade and controller
why not: duplicated code
validation only in controller and action in facade
why not: it could be dangerous when we use this businessAction method from other place in code
we can do two methods in facade: validation and action (Query Command Separation)
result from validation should contain every possible error which may occur so it's pretty strange structure
we can do several methods for validation (errors from A to X)
it's easy to provide error messages
but this solutions seems just stupid
any other ideas?
What would be the best solution?
Do authentication/validation in business layer and let it throw an exception in case of failure. You can just handle it in JSF action method.
E.g.
#EJB
private SomeService service;
public void someAction() {
try {
service.doSomething();
addGlobalInfoFacesMessage("Doing something succeed!");
} catch (SomeBusinessException e) {
addGlobalErrorFacesMessage("Doing something failed with {0}", e.getMessage());
}
}
Or, you can let it go and have the container handle it by an <error-page> on the specific <exception-type>.
As to performing authentication and validation all by itself, the Java EE stack offers annotations like JAAS #RolesAllowed for authentication and JSR303 #NotNull, #Size, etc for model. This should reduce the if check boilerplate inside the service methods itself.

Sustainable Method to Provide Additional Information in Exceptions?

I'm looking for a way to provide multiple pieces of information for exceptions back to end users. The obvious solution of extending Exception ends up with text distributed throughput the code, for example
throw new MyException("Bad data", "The data you entered is incorrect", "http://www.example.com/moreinfo/baddata");
and this quickly becomes unworkable.
I then looked at a catalogue approach but that's too centralized and requires jumping around from one file to another every time an exception is thrown. I'm now considering a hybrid approach with a static ErrorInfoMap class that contains mappings from a key to the more detailed information. Each class then has a static section that contains its own error mappings, so using the class which throws the above exception as an example I'd change it to:
throw new MyException("Bad data");
and at the bottom of the class there would be something like:
static {
ErrorInfoMap.put("Bad data", new ErrorInfo("The data you entered is incorrect", "http://www.example.com/moreinfo/baddata"));
// Information for other exceptions thrown by this class goes here
}
which allows an exception handler to fetch the additional information if required. Is this a good way of solving this issue, or is there a better way to handle this?
I'm not sure what exactly you mean by "the catalog approach" (could you provide a reference or more detailed description?) but from the information you provided, it's not clear to me how a static ErrorInfoMap avoids the problem of being "too centralized and [requiring] jumping around from one file to another every time an exception is thrown".
To me there are several options, depending on exactly what you need to accomplish:
Create a root class, ExceptionTemplate that extends Exception and does whatever repeatable behavior you'd like all your exceptions to do. Formatted toString() methods are a good example. Depending on your exact goals, you might like having your exceptions implement a builder pattern, like so:
throw new BadDataException("Supplied data is not valid")
.expected("a positive integer")
.referenceUrl("http://www.example.com/moreinfo/baddata");
Avoid stringly-typed solutions where an enum or subclass will do. If you don't need to define new exception types at runtime (and if you do, that should be a red flag that there's something deeper wrong with your design) and have an enum that contains all the necessary information to construct your exceptions:
public class EnumException extends Exception {
private EnumException() {} // prevent objects from being instantiated elsewhere
public enum Type {
BAD_DATA("Bad Data","Supplied data is not valid", "http://www.example.com/moreinfo/baddata"),
MISSING_DATA("Missing Data","Required data not found", "http://www.example.com/moreinfo/missingdata");
Type(String title, String genericMessage, String url) {
// Store input
}
public EnumException exception() {
// construct your exception
return new EnumException();
}
}
}
Which can be called with something like:
// note no `new` - the exception is returned by the enum
throw EnumException.Type.BAD_DATA.exception().expected("a positive integer");
This has the advantages of ensuring compile-time type safety, while still giving you the flexibility to define different types of Exceptions in one place.
Create lots of exceptions. I'm still not totally sure what objection you have to just creating a bunch of exceptions. You're looking for ways to "provide additional information" but claim that "the obvious solution of extending Exception ends up with text distributed throughput the code". This shouldn't be the case. Every subclass of Exception should hold all the necessary information except what can only be provided at construction time. Therefore there should be minimal "text distributed throughout the code" as any boiler-plate / reusable strings should be in the Exception class, and nowhere else.
public class DocumentedException extends Exception
{
private String title;
private String genericMessage;
private String detailedMessage;
private String url;
// Generally avoid this long constructor, and define subclasses that only need detailedMessage
public DocumentedException(String t, String g, String d, String u) {
super(g + " - " + d); // sets the getMessage() return value to something sane
title = t;
genericMessage = g;
detailedMessage = d;
url = u;
}
public String toString() {
return title.toUpperCase()+"\n"+
genericMessage+"\n"+
detailedMessage+"\n"+
"More info on this error: "+url+"\n";
}
public static class BadData extends DocumentedException {
public BadData(String details) {
super("Bad Data", "Supplied data is not valid", details, "http://www.example.com/moreinfo/baddata");
}
}
public static class MissingData extends DocumentedException {
public MissingData(String details) {
super("Missing Data", "Required data not found", details, "http://www.example.com/moreinfo/missingdata");
}
}
}
Which you can then call simply with:
throw new DocumentedException.BadData("Username cannot contain whitespace");
Of course, if you expected to need to warn against username errors regularly, you could create an additional class:
public static class BadUsername extends BadData {
public BadUsername() {
super("Usernames can only contain letters, numbers, and underscores");
}
}
The goal, again, is to explicitly define a hierarchy of exceptions that handle all cases you anticipate needing to deal with, such that you avoid repeatedly defining the same strings throughout your application. I personally like the group-exceptions-into-inner-classes pattern I used above, it lets you be very explicit with your errors without creating hundreds of silly stub java files you need to look through constantly. I would say that every major package should have an associated exception-holding class that defines all necessary exceptions for that package.
An alternative to your hybrid approach would be to put the error mapping in the exception itself. When MyException is initialised with Bad data add in the ErrorInfo that you've shown, but also provide a range of constructors for MyException that allows you to override or supplement the default definition of what Bad data means.
You could always have "MyException" as the superclass and have the specific types of errors as subtypes of that. In terms of error messages, you can use static constants on the subtypes to store the different types of errors.
E.g
Exception
-> MyException
-> BadDataException
-> InvalidUserException
etc.
Would be throw like so:
throw new BadDataException(BadDataException.DATA_TOO_LONG);

RuntimeException handling in java web application

I've faced an interesting aim, this aim targets the exception handling in existing web application written with wicket and hibernate frameworks,
suppose we have web app which is deployed in server and sometimes it produces runtime exceptions, the problem is how to get and save their stacktrace to db without modifying all classes(about 80 models and 150 views).
Hope i gave all clear.
Thanks in advance.
You can use an IRequestCycleListener to log/handle your exceptions:
public class MyExceptionReporter extends AbstractRequestCycleListener {
#Override
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
// log exception here
return null;
// if you want to also show an error page:
// return new RenderPageRequestHandler(new PageProvider(new ExceptionPage(ex)));
}
}
Then register it in WebApplication#init:
getRequestCycleListeners().add(new MyExceptionReporter());
Wicket 1.4 and earlier
Override Application.newRequestCycle() and return a custom subclass of WebRequestCycle that overrides RequestCycle.logRuntimeException() in order to provide additional logging behavior for all RuntimeExceptions in your application. Notice that any uncaught Exception will be wrapped by Wicket in a WicketRuntimeException (as stated in the Exception handling section of Request cycle and request cycle processor) :
There, use a Service/DAO component that will insert the exception message along with the stacktrace into the database. Remember that depending on the dbms, you might want to use a CLOB instead of a varchar type (for instance, in Oracle, a varchar column cannot hold more than 4000 bytes).
Here's an (untested) example:
public class myApplication extends WebApplication {
...
#Override
public RequestCycle newRequestCycle(Request request, Response response) {
return new myRequestCycle(this, (WebRequest) request, (WebResponse) response);
}
}
public class myRequestCycle extends WebRequestCycle {
...
#Override
protected void logRuntimeException(RuntimeException rex) {
super.logRuntimeException(rex);
Writer w = new StringWriter();
t.printStackTrace(new PrintWriter(w));
String stackTrace = w.toString();
someService.logExceptionToDB(rex.getMessage(),stackTrace);
}
}
Wicket 1.5 and later
See #Cristoph's answer
Write a utility which uses StackTraceElement[] to give you the complete stacktrace. Use an implementation of OutputStream to push it to a CLOB object. (I don't think BLOB is needed)

Categories

Resources