How to handle exception handling in singleton pattern? - java

I am trying to understand how to handle exception handling here. I have my below Singleton class which connects to cassandra, initialize all the metadata on the first call and then starts a periodic background thread which updates all our metadata every 15 minutes.
public class CassUtils {
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private final CassSession cassSession;
private static class Holder {
private static final CassUtils INSTANCE = new CassUtils();
}
public static CassUtils getInstance() {
return Holder.INSTANCE;
}
private CassUtils() {
CassConfig config = Utils.getConfig();
try {
this.cassSession = new CassSession(config);
initializeMetadata(); // initializes metadata on the very first call
} catch (Exception ex) {
// log error
throw new IllegalStateException("cannot initialize metadata: " + ex.getMessage());
}
}
private void startScheduleTask() {
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
try {
List<ProcessMetadata> processMetadata = getProcessMeta();
List<ClientMetadata> clientMetadata = getClientMeta();
List<ProcMetadata> procMetadata = getProcMeta();
if (!processMetadata.isEmpty() && !clientMetadata.isEmpty())
MetadataManager.setMetadata(processMetadata, clientMetadata, procMetadata);
} catch (Exception ex) {
// log error
}
}
}, 30, 15, TimeUnit.MINUTES);
}
private void initializeMetadata() {
List<ProcessMetadata> processMetadata = getProcessMeta(true);
List<ClientMetadata> clientMetadata = getClientMeta();
List<ProcMetadata> procMetadata = getProcMeta();
if (processMetadata.isEmpty() || clientMetadata.isEmpty() || procMetadata.isEmpty()) {
throw new IllegalStateException(); // is it ok to throw exception without any message here?
}
MetadataManager.setMetadata(processMetadata, clientMetadata, procMetadata);
startScheduleTask();
}
I need to notify the caller who is calling this singleton if there are any issues.
Now for whatever reason if CassSession throws exception because that is the class connects to cassandra and for some reason it is not able to connect to cassandra (mostly it will never happen), then I catch the exception in catch block in CassUtils class and throw IllegalStateException to the users with a message in it.
Also let's say if we are able to connect to cassandra through CassSession (which we will always) but in the initializeMetadata method, all our metadata are empty, then I don't want to proceed further so I am throwing IllegalStateException without any message in it. Is that ok? Because ultimately it will be caught by catch block of CassUtils class which is throwing exception to the calling users.
How to handle exception handling in singleton cases so that we can notify calling person whoever is calling this singleton. And IllegalStateException is the right exception to be thrown here? These above cases will happen during the first call at the initialization time. Is there any better way to do?

You are using static / class initialization to create the ClassUtils instance. As a general rule:
All checked exceptions that are thrown in class initialization must be caught. The compiler insists.
Any unchecked exceptions that propagate out of a classes static initialization will ultimately cause an Error to be thrown. Even in contexts where you are able to catch this error, you will be stuck with a class whose initialization has failed. The JVM won't ever retry the initialization, and the class ... and any other class that depends on it will be unusable.
So, if you were to deal with this, you would need to catch and (appropriately) handle the exception during static initialization.
Next problem is that if you want to report the failure to users of the CassUtils singleton, then getInstance() has to return an instance of CassUtils (or maybe a subclass) that is capable of:
remembering the exception, or whatever that reported the failure, and
rethrowing it to the caller of instance methods on the CassUtils API.
That is possible, but complicated.
And IMO it is undesirable. I think you would be best off NOT attempting to recover. Treat failure to initialize the Casandra session as a fatal error. If you can't do that, then the getInstance() method should be the method that throws / rethrows the exception that says "we are broken". At least, that avoids the need for potentially any caller of any CassUtils method to have to deal with the "we are broken" exception.
Did anyone ever mention to you that singletons are a bad idea? Consider using dependency injection instead.

Related

Is it bad practice to pass exception as argument to a method in java

I have a method that should rollback if an exception occurs in a service. In the exception block, the rollback service throws an exception when it fails. I created a service for rollback but i pass exception as argument to second method. is that bad practice?
public static void method1() {
try{
//do something that can throw exception
} catch (Exception e) {
method2(data, e);
}
}
public static void method2(String data, CustomException ce) {
try{
// rollback service that could fail
} catch(Exception e) {
log.warn("rollback failed!!!");
ce.addSuppressed(e);
}
}
At the end of the day, Exceptions are normal Java objects with the added property that they can be thrown. If we were to deny Exceptions as parameters, it would take away the ability to, for example, have centralized handler-methods for Exceptions (a concept found, for example, in JavaEE's ExceptionMapper). If we were to deny the use of Exceptions as parameters, we would most probably violate the DRY principle and most probably the Separation of Concerns principle. Both of which could lead to harder to read and maintain code.
Furthermore, if one of our method accepts Object (or Object... or Collection<Object>, ...) as parameter, we are not able to prevent that maybe an Exception is passed as parameter.
In conclusion, I see no reason why it should be a bad practice to pass an Exception as method parameter.

How to throw an Exception inside a Try/Catch block?

I have the following Java method:
public Class createClass(Class class) {
try {
// retrieve the professor of the class and check if he exists
Professor professorFound = professorRepository.findById(class.getProfessorId());
if (professorFound != null) {
// if the professor exists, then check if he already has a class
// with the same id
List<Class> classes = professorFound.getClasses();
List<Class> classFound = classes.stream().... // loop to find the class...
// if he has, throw an exception
if(!classFound.isEmpty()) {
throw new ClassAlreadyRegisteredException();
} else {
// if he does not have, then create the class
Class class = new Class();
professorFound.getClasses().add(class);
return professorRepository.save(professorFound);
}
} else {
// if the professor does not exist, throw an exception
throw new ProfessorNotFoundException();
} catch (Exception e) {
// if there is any other error during the communication with the database,
// throw a generic IOException
throw new ClassIOException();
}
}
Basically, what I need is to throw specific Exceptions (if the professor informed in the request does not exist, or if the professor already has a class with the same id), or throw a generic IOException if there is any other error during the communication with the database.
However, in the way that I have developed, if any specific Exception is thrown, the try block will catch the exception and will throw a generic IOException.
How can I solve this problem?
I'm very interested in understanding what are the best practices in this case.
Should I catch each specific exception separately and throw them twice?
Is that a good practice?
EDIT:
This is how my ClassAlreadyRegisteredException looks like:
public class ClassAlreadyRegisteredException extends ApiException {
private static final long serialVersionUID = 1L;
public ClassAlreadyRegisteredException(String code, String message, String developerMessage, String origin, HttpStatus status) {
super(code,message,developerMessage,origin, status);
}
}
This is how my ApiException looks like:
#Data
#AllArgsConstructor
#RequiredArgsConstructor
#EqualsAndHashCode(callSuper = false)
public class ApiException extends RuntimeException{
private static final long serialVersionUID = 1L;
private String code;
private String userMessage;
private String developerMessage;
private String origin;
private HttpStatus status;
}
Thanks in advance.
Catch and re-throw.
try {
... same as before ...
} catch (ClassAlreadyRegisteredException | ProfessorNotFoundException e) {
throw e;
} catch (Exception e) {
// if there is any other error during the communication with the database,
// throw a generic IOException
throw new ClassIOException();
}
Alternatively, remember the exception to throw it later.
Exception fail = null;
try {
….
// save exception in place of existing throws
// for example:
fail = new ClassAlreadyRegisteredException();
…
} catch (Exception ex) {
...same as original...
}
if (fail != null) {
throw fail;
}
I use both techniques; the choice depends on what is simpler in any given situation. Neither is uncontestably better.
For the catch and re-throw method, you have to keep the list of caught-and-rethrown exceptions consistent with the exceptions you actually throw from within the try-clause. In larger cases, I'd avoid that problem by using an exception hierarchy, so I could catch the common base class.
For the save-and-throw method, you have to arrange control flow so that nothing significant is done after detecting the failure, since you don't have the immediate 'throw' command to exit the try-clause. Nevertheless there are cases where it is simple enough; the original example is one such.
Checked vs Unchecked Exceptions
It's totally acceptable to throw an exception in a catch block. A common use case is to take a checked Exception and throw a unchecked RuntimeException which would allow the exception bubble up to where it needs to be handled.
You'll want to use checked exceptions for use cases such as Connectivity/IO, SQL exceptions..
Handling Checked Exceptions
To answer your question, in most libraries that connect to the database, an checked IOException is thrown if there are any connectivity issues. For these cases, you can always specify this in the method signature public Class createClass() throws IOException
this specifies that any callers of createClass() has to fulfill the contract that the IOException is handled.
or
You can rethrow this as a RuntimeException
try {
...
} catch (IOException e) {
throw new RuntimeException(e); // <- send the original exception so you can preserve the exception and stacktrace.
}
This will essentially bubble up to STDOUT or whatever handler your framework specifies.
CAUTION:
However, catching an cover all Exception and throwing a more specific ClassIOException can have unintended consequences.
If you have a NullPointerException this will be captured by your catch (Exception e) block and rethrown as a ClassIOException
Doing this will corrupt the stacktrace and cause your error logs to be much more difficult to debug.
Understanding what constitutes an checked Exceptions.
Another tip is to consider what your Exception cases are.
If they are standard flow of the application, service, or business logic -- these may not be appropriate exceptions.
The ClassAlreadyRegisteredException and ProfessorNotFoundException may not be exceptional cases in your application... unless these are already specified by your professor.
Sometimes these can be thrown as RuntimeException if the situation calls for it.
Best Practices?
There are still many opinions on how exceptions are handled. So here are some rule of thumb questions I ask myself when working with exceptions
Is the stacktrace preserved? Will I be able to trace back to the root Exception
Is this common logic and represents an exceptional case that deviates from what my application provides?
If I throw this exception, is it an absolute necessity for anything calling this method to handle this exceptional logic?

When to use the user Java keyword Throw on a user-defined Exception?

Is it possible to create a user-defined exception and only catch it in a try-catch or does the user-defined exception have to be thrown with the throw statement.
Question: I am somewhat confused on whether when to use the throw keyword? I think that the throw is used with user-defined Exceptions.
Code: (Java)
public genericPanel() {
try {
if (i.length == size) {
throw new MyOwnDefinedError("Error - Size is 1 integer
to large");
}
for (int index=0;index<=i.length;index++) {
System.out.println(i[index]);
}
} catch (MyOwnDefinedError o) {
o.getMessage();
} catch (Exception e) {
e.getMessage();
}
}
class MyOwnDefinedError extends Exception {
MyOwnDefinedError(String myNewString) {
super( myNewString);
}
throw is used whenever you want to throw any Exception, whether user-defined or not. There is no difference between "pre-defined" exceptions (like IOException) or self-defined one, as in your MyOwnDefinedError.
You can read the answer in the java documentation on throwing excepions:
http://docs.oracle.com/javase/tutorial/essential/exceptions/throwing.html
Before you can catch an exception, some code somewhere must throw one.
Any code can throw an exception: your code, code from a package
written by someone else such as the packages that come with the Java
platform, or the Java runtime environment. Regardless of what throws
the exception, it's always thrown with the throw statement.
As you have probably noticed, the Java platform provides numerous
exception classes. All the classes are descendants of the Throwable
class, and all allow programs to differentiate among the various types
of exceptions that can occur during the execution of a program.
You can also create your own exception classes to represent problems
that can occur within the classes you write. In fact, if you are a
package developer, you might have to create your own set of exception
classes to allow users to differentiate an error that can occur in
your package from errors that occur in the Java platform or other
packages
Throw is used to throw an exception.
Throw is a part of method definition.
At a given point of time, a throw statement can only throw one exception.
A throw statement is post fixed by an instance of exception.
The throw keyword in java is used for user defined exceptions you are right. For example you are doing a banking application and you want to withdraw money from a customer's account. As is normal, the amount cannot go negative so you would throw a InvalidAmountException or something similar.
The keyword itself is used every time when an exceptional situation needs to be underlined, hence you will use throw for throwing any kind of exception, that exists in the API already or one that an user implemented.
As it goes for the handling of the exception - if one extends the Exception class from java, the Exception should be specifically placed on the method definition by using the throws keyword. If you want the exception to pop-up at runtime and maybe interrupt the execution of your program you can extend the RuntimeException. In this case, the exception handling it is optional - you don't have to specify it with throws or you don't have to wrap the execution of the method with try/catch block.
A complete tutorial on exception can be found here.
class Test
{
void testDivision(float a,float b)
{
if(b=0.0)
{
try
{
throw new MathematicalException("Please, do not divide by zero");
}
catch (MathematicalException ae)
{
System.out.println(ae);
}
}
else
{
float result=a/b;
System.out.println("Result:" + result);
}
}
public static void main(String args[])
{
float f1 = Float.parsefloat(args[0]);
float f2 = Float.parsefloat(args[1]);
Test t1 = new Test();
t1.testDivision(f1,f2);
}
class MathematicalException extends Exception
{
MathematicalException();
MathematicalException(String msg)
{
super(msg);
}
}
}

What is the advantage of chained exceptions

I do not understand the advantages of having a chained exception in the code.
Considering the ResourceLoader example from java world, if the programmer knows of a possibility of encountering ResourceLoadException , why not catch the same exception instead of SQLException? Else, the programmer can catch both the exceptions in the same code than having to throw a new Throwable instance?
Can anyone please provide information on the need for chained exceptions?
The article says it quite well:
Exception chaining allows you to map one exception type to another, so that a method can throw exceptions defined at the same abstraction level as the method itself, without discarding important debugging information.
That is, if you have a method that loads some object from a database, you may rather want some ResourceLoadException (closer related to the methods abstraction level) instead of a low-level SQLException even if that was the original source of the problem. However, if you simply catch the SQLException and throw a ResourceLoadException instead, you may loose important debugging information.
Thus, chaining the exceptions is a good alternative. You throw a "high-level" exception, well suited for the particular method, but chain it with the exception that caused it.
Else, the programmer can catch both the exceptions in the same code than having to throw a new Throwable instance?
I don't quite follow your reasoning here. The point is that he should not need to worry about the SQLException at this level of abstraction.
Why Chain exception?
We need to chain the exceptions to make logs readable.
Take following examples of 1. without chaining and 2. chaining, exceptions to feel the difference
Create following Exceptions
class NoLeaveGrantedException extends Exception {
public NoLeaveGrantedException(String message, Throwable cause) {
super(message, cause);
}
public NoLeaveGrantedException(String message) {
super(message);
}
}
class TeamLeadUpsetException extends Exception {
public TeamLeadUpsetException(String message, Throwable cause) {
super(message, cause);
}
public TeamLeadUpsetException(String message) {
super(message);
}
}
class ManagerUpsetException extends Exception {
public ManagerUpsetException(String message, Throwable cause) {
super(message, cause);
}
public ManagerUpsetException(String message) {
super(message);
}
}
class GirlFriendOfManagerUpsetException extends Exception {
public GirlFriendOfManagerUpsetException(String message, Throwable cause) {
super(message, cause);
}
public GirlFriendOfManagerUpsetException(String message) {
super(message);
}
}
Now use them
1. Without chaining
public class MainClass {
public static void main(String[] args) throws Exception {
getLeave();
}
static void getLeave() throws NoLeaveGrantedException {
try {
howIsTeamLead();
} catch (TeamLeadUpsetException e) {
e.printStackTrace();
throw new NoLeaveGrantedException("Leave not sanctioned.");
}
}
static void howIsTeamLead() throws TeamLeadUpsetException {
try {
howIsManager();
} catch (ManagerUpsetException e) {
e.printStackTrace();
throw new TeamLeadUpsetException(
"Team lead is not in good mood");
}
}
static void howIsManager() throws ManagerUpsetException {
try {
howIsGirlFriendOfManager();
} catch (GirlFriendOfManagerUpsetException e) {
e.printStackTrace();
throw new ManagerUpsetException("Manager is in bad mood");
}
}
static void howIsGirlFriendOfManager()
throws GirlFriendOfManagerUpsetException {
throw new GirlFriendOfManagerUpsetException(
"Girl friend of manager is in bad mood");
}
}
2. Chaining
public class MainClass {
public static void main(String[] args) throws Exception {
getLeave();
}
static void getLeave() throws NoLeaveGrantedException {
try {
howIsTeamLead();
} catch (TeamLeadUpsetException e) {
throw new NoLeaveGrantedException("Leave not sanctioned.", e);
}
}
static void howIsTeamLead() throws TeamLeadUpsetException {
try {
howIsManager();
} catch (ManagerUpsetException e) {
throw new TeamLeadUpsetException(
"Team lead is not in good mood", e);
}
}
static void howIsManager() throws ManagerUpsetException {
try {
howIsGirlFriendOfManager();
} catch (GirlFriendOfManagerUpsetException e) {
throw new ManagerUpsetException("Manager is in bad mood", e);
}
}
static void howIsGirlFriendOfManager()
throws GirlFriendOfManagerUpsetException {
throw new GirlFriendOfManagerUpsetException(
"Girl friend of manager is in bad mood");
}
}
Now compare logs
1. Without chaining
com.bskyb.svod.autoingest.GirlFriendOfManagerUpsetException: Girl friend of manager is in bad mood
at com.bskyb.svod.autoingest.MainClass.howIsGirlFriendOfManager(MainClass.java:61)
at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:52)
at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:43)
at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
com.bskyb.svod.autoingest.ManagerUpsetException: Manager is in bad mood
at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:55)
at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:43)
at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
com.bskyb.svod.autoingest.TeamLeadUpsetException: Team lead is not in good mood
at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:46)
at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
Exception in thread "main" com.bskyb.svod.autoingest.NoLeaveGrantedException: Leave not sanctioned.
at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:37)
at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
2. Chaining
Exception in thread "main" com.bskyb.svod.autoingest.NoLeaveGrantedException: Leave not sanctioned.
at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:36)
at com.bskyb.svod.autoingest.MainClass.main(MainClass.java:29)
Caused by: com.bskyb.svod.autoingest.TeamLeadUpsetException: Team lead is not in good mood
at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:44)
at com.bskyb.svod.autoingest.MainClass.getLeave(MainClass.java:34)
... 1 more
Caused by: com.bskyb.svod.autoingest.ManagerUpsetException: Manager is in bad mood
at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:52)
at com.bskyb.svod.autoingest.MainClass.howIsTeamLead(MainClass.java:42)
... 2 more
Caused by: com.bskyb.svod.autoingest.GirlFriendOfManagerUpsetException: Girl friend of manager is in bad mood
at com.bskyb.svod.autoingest.MainClass.howIsGirlFriendOfManager(MainClass.java:58)
at com.bskyb.svod.autoingest.MainClass.howIsManager(MainClass.java:50)
... 3 more
A caller of the loadResource should not need to know the exact details of how those resources are loaded, or at the very least not care about the details of why it failed. (keep in mind it might not be you that wrote loadResources, or it might be someone else that needs to use the loadResources method).
All you should care about when calling loadResource is it might throw a ResourceLoadException. Not that implementation details fails because of a SQLException - this might change with time too, later on someone might decide to load resources from somewhere else that could fail too.
You just need to load some resources, you need to handle if it fails, and not handle potential MainframeHasCrashedException, FileNotFoundException and the dozen other reasons loading those resources might fail.
Now, when something does fail, it's handy to have the original exception that caused the failure, such as an SQLException - so someone scouring through log files or similar can figure out the cause of the error by inspecting the stacktrace
You shouldn't be tempted to just catch Exception here either, if loadResources could also throw other exceptions , e.g. an UnautorizedException, you might not want to deal with that when you're calling loadResources - you might want to propagate that exception up to other callers that can deal with an UnautorizedException(and perhaps prompt the user for some credentials). a catch(Exception e) would swallow that UnautorizedException that you really can't deal with there.
The advantage is that the caller only has to handle a ResourceLoadException instead of SQLException. That way if you later change your data storage to be in a file that accessing it might cause an IOException. You don't have to go back and change the type of Exception that your caller handles. This is useful to your caller because the caller is going to handle either exception the same way.
I think the reason from that sample is that the author wishes to create a uniform interface which isn't dependent on some specific underlying system, like SQL. Hence, he converts the exception to the more general form, leaving the actual implementation transparent to the business logic.
However, in some cases it might be desirable to propagate an error like SQLException. This will be useful in places where one needs to take different actions based on the thrown Exception.
The first benefit is encapsulation. ResourceLoader might be an interface with several implementations (for instance one loading the resources from the database, while another loads them from the file system), where the implementation to use is selected at runtime. Then the caller should be agnostic to the root cause of why loading the resource failed, but might still wish to react to resource load failures. This is particularly useful if the interface declares two different exceptions to be thrown to which the caller might wish to respond differently (for instance, a TransientResourceLoadFailureException, where a retry might suceed, and a PermanentResourceLoadFailureException, where a retry is known not to succeed).
The second benefit of exception chaining is that each exception in the chain may have a different message, which allows to include additional information for debugging. In your case, note that the ResourceLoadException's message contains the name of the resource that could not be loaded, which is not guaranteed to be included in the SQLException, but might be necessary to reproduce the problem (certain databases are not exactly known for specific error messages).
These benefits come at the cost of having to write and maintain the catch blocks. You should decide on a case by case basis whether the benefits justify the cost.
Chaining exception is for debugging purposes.When you get a general exception, you can check if there is a chained lower exception and try to understand why that lower level exception occurred.

Java - Can final variables be initialized in static initialization block?

Based on my understanding of the Java language, static variables can be initialized in static initialization block.
However, when I try to implement this in practice (static variables that are final too), I get the error shown in the screenshot below:
Yes of course: static final variables can be initialized in a static block but.... you have implicit GOTOs in that example (try/catch is essentially a 'GOTO catch if something bad happens').
If an exception is thrown your final variables will not be initialized.
Note that the use of static constructs goes against Object-Oriented dogma. It may complicate your testing and make debugging more difficult.
You can do this but you need to exit the static block by throwing an exception - you can rethrow the exception that was caught or a new one. Generally this exception must be a RuntimeException. You really should not catch a generic Exception but more specific exception(s) that might be thrown from within your try block. Finally, if a static initializer throws an exception then it will render the class unusable during that specific run because the JVM will only attempt to initialize your class once. Subsequent attempts to use this class will result in another exception, such as NoClassDefFoundError.
So, to work, your initializer should read something like this:
static {
try {
...
} catch (Exception e) {
e.PrintStackTrace();
throw new InitializationFailedException("Could not init class.", e);
}
}
Assuming that InitializationFailedException is a custom RuntimeException, but you could use an existing one.
public class MyClass
{
private static final SomeClass myVar;
static
{
Object obj = null; // You could use SomeClass, but I like Object so you can reuse it
try
{
obj = new SomeClass(...);
}
catch(WhateverException err)
{
// Possibly nested try-catches here if the first exception is recoverable...
// Print an error, log the error, do something with the error
throw new ExceptionInInitializerError(err);
}
finally
{
myVar = (SomeClass) obj;
}
}
}
Assuming no where upstream is in a position to catch either an ExceptionInInitializationError or a general Exception then the program should not ever try to use myVar. If however those are caught and the program doesn't end, then you need to code to watch for and handle myVar being null (or be happy with NullPointerExceptions coming out all over).
I'm not sure there is a good way to handle this.
Can you put the declaration in the finally block?
try {
//load file
} catch(IOException e) {
// horay
} finally {
HOST=config.get......
}

Categories