Java exception factory for higher level exceptions - java

I am looking to create a exception factory
I have a service that connects to different data stores and these data stores throw a number of exceptions.
I do not want to return these exceptions to users of the service but instead return higher level exception
e.g. storeServiceTransientReadException
When connecting to the data store I will use a try, catch throw pattern; e.g for a Cassandra connection:
public ResultSet safeExecute(Statement statement) throws StoreServiceException {
try {
return session.execute(statement);
}
catch(QueryExecutionException ex){
log.error(ex);
StoreServiceException storeException = StoreServiceExceptionFactory.getTransientException(ex);
throw storeException;
}
In the cassandra example I want the factory to create a read or write storeServiceException exception depending on whether the exception is a ReadFailureException, ReadTimeoutException, WriteFailureException or WriteTimeoutException
For other data stores I want to follow the same pattern then users of the service will only have to worry about the service errors and not specific data store errors.
For the factory I was think something along the lines of (in pseudo):
public class ExceptionsFactory {
public StoreServiceTransientException getTransientException(Exception ex){
if ReadException
return StoreServiceTransientException("read exception ")
if WriteException
return StoreServiceTransientException("write exception ")
}
public StoreServiceNonTransientException getTransientNonException(Exception ex){
if ReadException
return StoreServiceNonTransientException("read exception ")
if WriteException
return StoreServiceNonTransientException("write exception ")
}
But I cannot find many online example of this which worries me.
It is a really bad idea?
I should just have lots more specific catch blocks that return the storeServiceException I want?

It is a really bad idea? In my opinion, yes. This is a bad idea. The expensive part of using Exception(s) is filling in the stack trace. If you pre-create and save the Exception you throw then the stack trace will be meaningless (or at least of greatly reduced value). You aren't currently logging stack traces, so I would also change
log.error(ex);
to
log.error("Caught exception: " + ex.getMessage(), ex);
And similarly instantiate exceptions with the underlying cause -
throw new storeServiceException("Exception in storage.", ex);
And the name should follow normal naming conventions. Java class names start with a capital letter - yours' looks like a variable.

Related

Why doesn't Java have setMessage in Exception/Throwable classes?

I am not able to understand why Java doesn't allow to change exception message of an exception of type Exception (or its superclass Throwable) once it has been created. It allows to change the stackTrace using setStackTrace but not the message.
The use case I have seems genuine to me and would appreciate some alternative.
Use case
I have a controller service X that calls let's say 10 other dependent services. To make debugging easy, if a dependent service throws some exception we want to surface some identifiers from service X to its upstream to identify the failed request easily. For this we have requestId which we create and set for each dependency.
Now to avoid duplication across all dependent services and simplify code, we can create a common interceptor that allows us to do some work before and after each call. Something like -
// do some work
requestId = getRequestId(); // create or somehow get requestId
dependentService.setRequestId(requestId);
try {
dependentService.call();
}
catch (Exception e) {
e.setMessage(e.getMessage() + ... + requestId);
throw e;
}
//do some work
But Java doesn't allow us to set message. At the same time, we want to preserve the exception and its type (which could be any of the custom types defined by dependent services), so I don't want to do something like throw new Exception(e.getMessage() + ...)
It's not really what it's meant for, but you could attach another exception with addSuppressed:
} catch (Exception e) {
e.addSuppressed(new ExtraInfoException(...));
throw e;
}
where ... contains the extra info you want to include.
The advantage of this over adding to the exception message is that you can define your ExtraInfoException so that it has the info you want in fields, rather than having to parse it back out of the exception message.
With that said, a more idiomatic way to attach more exception info it would be:
} catch (Exception e) {
throw new ExtraInfoException(e, ...);
}
which has exactly the same advantage of allowing you to return structured information, with the additional advantage that you can catch ExtraInfoException directly, rather than catching Exception and then hunting for the extra info reflectively.
Why doesn't Java have setMessage in Exception/Throwable classes?
The answer to your question is that they (the library designers) did not think that changing a message on an exception was a useful thing to do.
To a large degree1, the designers have taken the view that they shouldn't design the APIs to directly support all possible use-cases ... including the obscure ones that almost nobody will encounter. Like your one2.
And in your case, there are other ways to achieve what you are trying to do; see the other answers.
I did a quick search of the Java bugs database to see if someone else had put in an RFE to request a setMessage method for Throwable or Exception. I couldn't find anything. If your requirement was even slightly common, there would probably be an RFE with an explanation of why it was declined.
1 - Obviously, there are exceptions to this, but that is beside the point.
2 - Obviously you would disagree that your use-case is obscure, but that that is also beside the point. The question is why they haven't implemented this, not whether they were wrong. (Asking / debating whether they were wrong is off-topic, because it is a matter of opinion.)
Resetting a message it's some kind of rewriting the history. You have a catch block when you catch exception and handle them. If you need to throw an exception during the handling, it's a different problem and an exception should be different.
} catch (SomeException e) {
// here we have SomeException and we want to handle it.
// if we can't we throw a new one, because we have a problem with handling.
// if the handling problem cause is SomeException we put it at the cause.
throw new AnotherException("with some message", e);
}
And in the stacks trace we will see that we have AnotherException because of SomeException which gives us information about the root of problem.
Just simply throw new instance like this:
try {
...
} catch(Exception ex) {
throw new Exception ("new message", ex);
}

What is exception wrapping in Java?

What is Exception wrapping in Java? How is it useful in exception handling? How it differs from exception propagation?
Exception wrapping is when you catch an exception, wrap it
in a different exception and throw that exception.
Here is an example:
try{
dao.readPerson();
} catch (SQLException sqlException) {
throw new MyException("error text", sqlException);
}
Source: http://tutorials.jenkov.com/java-exception-handling/exception-wrapping.html
On the Other Hand
Exception Propagation: An exception is first thrown from the top of
the stack and if it is not caught, it drops down the call stack to the
previous method, if not caught there, the exception again drops down to
the previous method, and so on until they are caught or until they
reach the very bottom of the call stack.
Source: http://www.javatpoint.com/exception-propagation
I think Neeraj's answer is spot on. To add on to it, I think one particularly good case is to manage the number of exceptions thrown by abstracting exceptions. To expand on Neeraj's example:
class Manager {
public void sendPerson() throws ManagerException {
try{
Person person = dao.readPerson();
Socket socket = getSocket();
OutputStream os = socket.getOutputStream();
String personJson = objectMapper.writeValueAs(person);
os.write(personJson);
} catch (SQLException | SocketException | OutputStreamException | SerializationException e) {
throw new ManagerException("error text", e);
}
}
}
This way, the client only needs to do the following:
try {
manager.sendPerson();
} catch (ManagerException e) {
// Handle fail by manager
}
instead of worrying about the fine-grained details of what may have gone wrong in the manager.
A usecase would be to turn a checked exception into a runtime exception or vice versa.
Or it could just be a naming thing. Let's say you catch an SQLException at some point in your code, but you can reason that it's because the user is not logged in. Then you could catch it and throw your own custom NotLoggedInException.
This answer is taken from here : http://www.javapractices.com/topic/TopicAction.do?Id=77
Data can be stored in various ways, for example:
a relational database
text files
on the web (for example, fetching the weather forecast from a web site)
If the storage method changes, then the low level Exception objects thrown by the data access layer can also change. For example, when the data store is moved from text files to a relational database, IOException is replaced with SQLException.
In order to prevent such a change from propagating to higher layers, one can wrap such low level Exceptions in a generic "data exception" wrapper, designed exclusively to protect the higher layers from such changes.
Now we will see a example...
public class ResourceLoader {
public loadResource(String resourceName) throws ResourceLoadException {
Resource r;
try {
r = loadResourceFromDB(resourceName);
}
catch (SQLException e) {
throw new ResourceLoadException("SQL Exception loading resource "
+ resourceName: " + e.toString());
}
}
}
loadResource's implementation uses exceptions reasonably well. By throwing ResourceLoadException instead of SQLException (or whatever other exceptions the implementation throws), loadResource hides the implementation from the caller, making it easier to change the implementation without modifying calling code. Additionally, the exception thrown by loadResource() -- ResourceLoadException -- relates directly to the task it performs: loading a resource. The low-level exceptions SQLException and IOException don't directly relate to the task this method performs, and therefore will likely prove less useful to the caller. Further, this wrapping preserves the original exception's error message so the user knows why the resource could not load (perhaps because of a connection error or an incorrect username or password) and can take corrective action.

Servlet catch unique constraint exception

I'm trying to insert some data into the table named rmas.
The table format is
|rcode|rname|vcode|vanme
Here, I set primary key for rcode.
When I'm inserting a record with existing rcode, it displays something like ORA-0000-1 unique constraint Violated..
If I'm using the following code, it displays the message even in the case of other errors.
catch(Exception e)
{
//out.println("rcode already exists");
}
So, I want to catch that primary key exception only and display as "rcode already exist". Is it possible? If yes, then how?
Thanks in advance
Exception is the parent of all the exception. If you have catch(Exception e) { } block written then all the exceptions will fall into this category. You need to find which exception the compiler is returning. Say if your compiler returns this exception SQLIntegrityConstraintViolationException then the following block would come
catch(SQLIntegrityConstraintViolationException e)
{
// Error message for integrity constraint violation
}
catch(NullPointerException e)
{
// Null Pointer exception occured.
}
catch(Exception e)
{
// Other error messages
}
In this way you can have any number of exception blocks. But make sure more specific exception types are first written and then the parent exceptions
You're catching an Exception, which is the superclass of all exceptions. By catching this you use the Pokémon Style ("Gonna catch 'em all!") which is, in general, a bad practice since you lose the ability to take different courses of action based on the particular exception that was thrown in that block of code.
Catch only the exception related to the constraint violation to avoid showing the message for every exception.
Why would you like to do this on a servlet escapes me, but I suggest you take a look at the architecture of your solution and provide a layered approach, catching this exceptions in the Persistence tier and returning your own result code, that defines which message should be displayed to the user.
Note: I used Result code and not Error code to allow returning a code for a successful operation.
I wouldn't have any such code in a servlet. I think it belongs in a class that lives in your persistence tier. Servlets are HTTP listeners; they shouldn't have database code in them.
Have your interface-based persistence class catch that exception and handle it appropriately. Write an inteface-based service that uses the persistence class to fulfill the use case. Let the servlet call the service and figure out what to display next based on what happens.
It's called a layered architecture. I'd recommend it highly.
In my case in a spring boot application, I used DataIntegrityViolationException to catch unique constraint like this:
try {
userRepository.save(user);
log.debug("Created Information for User: {}", user);
} catch (DataIntegrityViolationException e) {
}
I would catch in the following manner:
catch(Exception ex){
if(ex.getMessage().contains("UNIQUE KEY"))
return "Error - Unique Key Violation!!";
else if(ex.getMessage().contains("FOREIGN KEY"))
return "Error - Foreign Key Violation!!";
else
return "Other Error: " + ex.getMessage();
}
Hope that's simple and functional!!

Throwing checked exception in Java

Let's say I am designing an API for storing passwords. According to Effective Java it is a good idea to use throw clauses to show checked exceptions, however by having a throw clause that throws a SQLException, which is a checked exception, then I am revealing the underlying implementation details of my API and thus I will be unable to change the implementation details of my API at a later stage. One of the pros to throwing a checked exception is that the programmer who uses the API should be able to handle the exception in a manner of their choosing. Which of these two methods should I choose to do, add a throw clause which reveals the implementation or hide it or use a different approach?
Your motivation is correct for not "leaking" SQLException to the users of your class.
The fact that you're using SQL could be considered an implementation detail. You may even swap SQL persistence for say, an in-memory one at a later time, and this change shouldn't impact the users of your class.
If you are inclined to use checked exceptions, I would define your own exception type (say, PasswordStoreException -- just an example name). You can use it to wrap the original exception that was thrown, e.g.:
try {
// do whatever
} catch (SQLException ex) {
throw new PasswordStoreException(ex);
}
It is today considered bad design for an API to declare checked exceptions. If you have ever used such an API, you should already know why.
In any case your API should never throw (let alone declare) exceptions belonging to other APIs. If you do that, you hang a completely unrelated dependency on your client's back. The only "exception" to this rule are JDK's standard exceptions like NPE, ISE and the like.
Catch the SQLException, and wrap it into your own exception:
try {
// JDBC code
}
catch (SQLException e) {
throw new MyException("Error persisting the secret", e); // choose a better name, of course
}
Whether this exception should be a checked exception or a runtime exception depends on what the caller can do about it. If it's recoverable (which, I think, is not the case here), it should be a checked exception. If it's not recoverable (the caller can just display an error message), then it should be a runtime exception.
If it's a checked exception, you have no choice; the exception MUST be declared in the throws clause of the method.
As is, it is always a good idea to throw your own exception checked/unchecked. But before that, try to fix the underlying exception if possible. I always prefer the below way,
try {
// JDBC code
}
catch (SQLException e) {
// try to solve the exception at API level
bollean solvable = trySolveException(e);
if (!solvable) {
// Alert the admin, or log the error statement for further debugging.
mailClient.sendMailToDBAdmin("Some issue storing password", e);
// or
LOG.severe("some issue in storing password " + e.toString);
throw MyException("A request/logstatement is logged on your behalf regarding the exception", e);
}
LOG.info("The exception is solved");
}
finally {
// don't forget to free your resources - to avoid garbage and memory leaks, incase you have solved the issue in trySolveException(e).
}
So,
1) You don't expose the SRQException directly, but you throw your own version of the exception.
2) You tried to solve the exception once and if not you alerted somehow - through a mail or a log statement.
3) Finally, you ve released all the resources if you succeed in solving the exception.
The finally clause can be avoided if you use the new Java7's try with resource close option.
For whether to throw checked or unchecked exception, I will give you an example
1) Say an exceptions like NPE - they are programmatic errors and the developer should be more responsible to have not created a NullPointer. You don't expect your code to account for such careless errors and put a try(NPE), catch(NPE). So throw a unchecked exceptions.
2) On the other hand the exceptions like SQL exceptions are at the rare cases, account for some external dependency. So, better throw a user defined checked exceptions. And the user can determine if he can connect to the backup SQL server if any.
3) There are another clause of exceptions, where the program cannot continue furhter. Say a Memory Out of Bounds. They should be thrown as Errors.
Try this..
fillInStackTrace() method is called to re-initialize the stack trace data in the newly created throwable. Will be helpful in masking the info about the exception when tries to access the API.

Java - ignore exception and continue

For my Java application, I am creating an instance of a user information object and populating it with a service that I don't control the source for.
The code looks like this:
// username given as parameter
UserInfo ui = new UserInfo();
try {
DirectoryUser du = LDAPService.findUser(username);
if (du!=null) {
ui.setUserInfo(du.getUserInfo());
}
} catch (Exception e) {
// Whatever
}
If LDAPService.findUser() can't locate a user, it will throw a NullPointerException and grind the rest of my application to a stop. It's okay if the user information isn't populated, so I want to be able to continue without causing everything else to start throwing exceptions.
Is there a way to do this?
I've upvoted Amir Afghani's answer, which seems to be the only one as of yet that actually answers the question.
But I would have written it like this instead:
UserInfo ui = new UserInfo();
DirectoryUser du = null;
try {
du = LDAPService.findUser(username);
} catch (NullPointerException npe) {
// It's fine if findUser throws a NPE
}
if (du != null) {
ui.setUserInfo(du.getUserInfo());
}
Of course, it depends on whether or not you want to catch NPEs from the ui.setUserInfo() and du.getUserInfo() calls.
You could catch the NullPointerException explicitly and ignore it - though its generally not recommended. You should not, however, ignore all exceptions as you're currently doing.
UserInfo ui = new UserInfo();
try {
DirectoryUser du = LDAPService.findUser(username);
if (du!=null) {
ui.setUserInfo(du.getUserInfo());
}
} catch (NullPointerException npe) {
// Lulz # your NPE
Logger.log("No user info for " +username+ ", will find some way to cope");
}
You are already doing it in your code. Run this example below. The catch will "handle" the exception, and you can move forward, assuming whatever you caught and handled did not break code down the road which you did not anticipate.
try{
throw new Exception();
}catch (Exception ex){
ex.printStackTrace();
}
System.out.println("Made it!");
However, you should always handle an exception properly. You can get yourself into some pretty messy situations and write difficult to maintain code by "ignoring" exceptions. You should only do this if you are actually handling whatever went wrong with the exception to the point that it really does not affect the rest of the program.
It's generally considered a bad idea to ignore exceptions. Usually, if it's appropriate, you want to either notify the user of the issue (if they would care) or at the very least, log the exception, or print the stack trace to the console.
However, if that's truly not necessary (you're the one making the decision) then no, there's no other way to ignore an exception that forces you to catch it. The only revision, in that case, that I would suggest is explicitly listing the the class of the Exceptions you're ignoring, and some comment as to why you're ignoring them, rather than simply ignoring any exception, as you've done in your example.
You are actually ignoring exception in your code. But I suggest you to reconsider.
Here is a quote from Coding Crimes: Ignoring Exceptions
For a start, the exception should be logged at the very least, not
just written out to the console. Also, in most cases, the exception
should be thrown back to the caller for them to deal with. If it
doesn't need to be thrown back to the caller, then the exception
should be handled. And some comments would be nice too.
The usual excuse for this type of code is "I didn't have time", but
there is a ripple effect when code is left in this state. Chances are
that most of this type of code will never get out in the final
production. Code reviews or static analysis tools should catch this
error pattern. But that's no excuse, all this does is add time to the
maintainance and debugging of the software.
Even if you are ignoring it I suggest you to use specific exception names instead of superclass name. ie., Use NullPointerException instead of Exception in your catch clause.
You can write a try - catch block around the line you want to have ignored.
Like in the example code of yours. If you just continue your code below the closing bracket of the catch block everythings fine.
LDAPService should contain method like LDAPService.isExists(String userName) use it to prevent NPE to be thrown. If is not - this could be a workaround, but use Logging to post some warning..
Printing the STACK trace, logging it or send message to the user, are very bad ways to process the exceptions. Does any one can describe solutions to fix the exception in proper steps then can trying the broken instruction again?

Categories

Resources