How to handle Exception from Singleton java? - java

I have a singleton class
public class SingletonText {
private static final CompositeText text = new CompositeText(new TextReader("text/text.txt").readFile());
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}}
And TextReader constructor that could throw FileNameEception
public TextReader(String filename) throws FileNameException{
if(!filename.matches("[A-Za-z0-9]*\\.txt"))
throw new FileNameException("Wrong file name!");
file = new File(filename);
}
How can I rethrow it to main and catch it there?
Main class
public class TextRunner {
public static void main(String[] args) {
// write your code here
SingletonText.getInstance().parse();
System.out.println("Parsed text:\n");
SingletonText.getInstance().print();
System.out.println("\n\n(Var8)Task1:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[AEIOUaeiou].*", new FirstLetterComparator());
System.out.println("\n\n(Var9)Task2:");
SortWords.sortWords(SingletonText.getInstance().getText().toString(), "^[A-Za-z].*", new LetterColComparator());
System.out.println("\n\n(Var16)Task3:");
String result = SubStringReplace.replace(SingletonText.getInstance()
.searchSentence(".*IfElseDemo.*"), 3, "EPAM");
System.out.println(result);
}}

Static block is executed only when class is loaded for the first time, so you can have something as below which will allow you to re-throw the exception. In you main method, you will surround getInstance() invocation in a try-catch block and then in catch you can do whatever you are looking for.
In case of exception, this exception will be thrown and re-thrown (from you static block) only once, at time of class loading. What #Alexander Pogrebnyak has said is also true.
Looking at the code you have provided, since you are always reading text/text.txt files so below approach will work. In case you are looking to read different files and then re-throwing exception then that becomes all together a different story, and you hadn't asked that part neither the code you have provided shows the same. In any case, if that's what you are looking for then:
you need to create a singleton object of your CompositeText class.
create a setter method will create an object TextReader class using the file name string passed.
that setter method will have the try-catch block, and in the catch block you will re-throw the exception so that you can catch again in main method.
P.S.: since static blocks are executed only once when class is loaded and class is loaded only once per JVM (until you have custom class loaders and overriding the behavior) so this ensures that this singleton is thread-safe.
Code:
public class SingletonText {
private static CompositeText text = null;
static{
try {
text = new CompositeText(new TextReader("text/text.txt").readFile());
} catch (FileNameException e) {
// TODO: re-throw whatever you want
}
}
public SingletonText() {}
public static CompositeText getInstance() {
return text;
}
}

try to lazy initialze the singleton.
something like this:
public class SingletonText {
private static CompositeText text;
public SingletonText() {
}
public static CompositeText getInstance() {
if (text ==null) {
text = new CompositeText(new TextReader("text/text.txt").readFile());
}
return text;
}
}
Also, you need to declare the constructor private, and if it multi-threaded application you need to synchronized the new statement with double check locking. see this in wiki:
https://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
Enjoy..

You will get java.lang.ExceptionInInitializerError when your singleton static initializer will fail.
As a cause it will have your FileNameException.
If you don't do anything, default exception handler will print the whole stack trace to standard error.

Related

How to break out initialization block?

I have a class looks like this
class Some {
private enum Inner {
}
}
And I'm trying to find the Inner class in a initialization block of my test class.
class SomeTest {
private static final Class<?> INNER_CLASS;
{
for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals("Inner")) {
INNER_CLASS = declaredClass;
// Variable `INNER_CLASS` might be assigned in loop
// break? return?
}
}
throw new ExceptionInitializerError("failed to find Inner.class");
}
}
The compiler doesn't like this and I couldn't find any better way.
How can I solve this? Is there any good pattern for this?
static and instance initialization block cannot throw checked exceptions as there is no way to declare that those blocks throws these execeptions. Change ExceptionInitializerError to RuntimeException (or any subclass) and wrap your code in try-catch
Besides here, you are not returning nor breaking thus you always throw exception.
As for "breaking out" well simply yo dont. You have to write that block as it would be body of void method but with the restriction that you cannot use return anywhere.
There are a few problems with your code:
You have the exception name incorrect. The exception you are trying to throw is called ExceptionInInitializerError not ExceptionInitializerError. That is one reason why it won't compile.
Never1 throw Error or subclasses of Error.
If you need to throw an unchecked exception, throw RuntimeException. Or better still, pick something more specific or define and use your own custom (unchecked) exception class.
This should (probably) be a static initializer block, not a plain (instance) initializer. You want this code to be executed once ... not every time a SomeTest instance is created.
Bailing out of a static initializer block is something you want to avoid. It basically leaves you with a dead application ... because the enclosing class and any classes that depend on it become uninitializable.
Having said that, the following might be a more appropriate structure:
static {
BlahType tmp = null;
label: {
for (...) {
if (...) {
tmp = ...;
break label;
}
}
throw new SomeException(...);
}
FINAL_VAR = tmp;
}
Note that we need to do the final assignment to FINAL_VAR in a way that ensures that it is definitely assigned. (My guess is that is a second reason you were getting compilation errors.)
And a more natural way to write the above would be:
static {
BlahType tmp = null;
for (...) {
if (...) {
tmp = ...;
break;
}
}
if (tmp == null) {
throw new SomeException(...);
}
FINAL_VAR = tmp;
}
1 - Maybe a bit too strong. I would say that throwing AssertionError is OK ... assuming that you intend for it never be caught / recovered from. In this case, recovery is moot anyway.
Use intermediate variable before final assignment.
class SomeTest {
private static final Class<?> INNER_CLASS;
static {
Class<?> innerClass = null;
for (final Class<?> declaredClass: Some.class.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals("Inner")) {
innerClass = declaredClass;
}
}
if (innerClass == null) {
throw new ExceptionInitializerError("failed to find Inner.class");
}
INNER_CLASS = innerClass;
}
}
There are couple of issues:
The exception is always thrown
You are assigning to a final variable in a loop
The initialization block is not static and assigning to a static final variable
Check this out:
class SomeTest {
private static final Class<?> INNER_CLASS;
static {
Class<?> foundClass = null;
for (final Class<?> declaredClass : Some.class.getDeclaredClasses()) {
if (declaredClass.getSimpleName().equals("Inner")) {
foundClass = declaredClass;
// Variable `INNER_CLASS` might be assigned in loop
// break? return?
}
}
INNER_CLASS = foundClass;
// throw new Exception("failed to find Inner.class");
}
}

Catching exceptions from static fields in the main class

I never really thought about this before but looking at the following code
public class SomeJavaProgram {
private static String runMe() {
throw new RuntimeException("hi tadsfasdf");
}
private static String name = runMe();
public static void main(String[] args) {
System.out.println("hi there.");
}
}
I never did statics like this in a main before but then I entered scala, and if you have subclasses that start adding defs, exceptions can be thrown before main is even called.
So, in java(not scala), is there a way to catch these exceptions(if I am the superclass and subclasses end up having a static field that throws an exception or static initializer block)....how can I catch all these?
I of course do rely on ONE single definition not throwing which is the
private Logger log = createLoggerFromSomeLoggingLib();
But after that, ideally I would want all exceptions to be logged to the logged file rather than stderr.
That said, I am glad I have always kept the stderr/stdout files along with my logging files now.
Use the static initializer:
private static String name;
static {
try {
name = runMe();
} catch (RuntimeException e) {
// handle
}
}

Catch exception while initializing static final variable

I have following code:
public class LoadProperty
{
public static final String property_file_location = System.getProperty("app.vmargs.propertyfile");
public static final String application-startup_mode = System.getProperty("app.vmargs.startupmode");
}
It reads from 'VM arguments' and assigns to variables.
Since static final variable is only initialized at class load,
how can I catch exception in case some one forgets to pass parameter.
As of now, when I am using 'property_file_location' variable, exception is encountered in following cases:
If value is present, and location is wrong, FileNotFound exception comes.
If it is not initialized properly(value is null), it throws NullPointerException.
I need to handle second case at time of initialization only.
Similiar is case of second variable.
Whole idea is
To initialize application configuration parameters.
If successfully initialized, continue.
If not, alert user and terminate application.
You can catch it this way:
public class LoadProperty
{
public static final String property_file_location;
static {
String myTempValue = MY_DEFAULT_VALUE;
try {
myTempValue = System.getProperty("app.vmargs.propertyfile");
} catch(Exception e) {
myTempValue = MY_DEFAULT_VALUE;
}
property_file_location = myTempValue;
}
}
You can use a static initializer block as suggested by the rest of the answers. Even better move this functionality to a static utility class so you can still use them as an one-liner. You could then even provide default values e.g.
// PropertyUtils is a new class that you implement
// DEFAULT_FILE_LOCATION could e.g. out.log in current folder
public static final String property_file_location = PropertyUtils.getProperty("app.vmargs.propertyfile", DEFAULT_FILE_LOCATION);
However if those properties are not expected to exist all the time, I would suggest to not initialize them as static variables but read them during normal execution.
// in the place where you will first need the file location
String fileLocation = PropertyUtils.getProperty("app.vmargs.propertyfile");
if (fileLocation == null) {
// handle the error here
}
You may want to use a static bloc :
public static final property_file_location;
static {
try {
property_file_location = System.getProperty("app.vmargs.propertyfile");
} catch (xxx){//...}
}

StackOverflowError caused by non-static member of same type

The code in the following snippet throws java.lang.StackOverflowError.
public class Main
{
private Main m=new Main(""); //This statement causes the exception.
private Main(String s)
{
System.out.println(s);
}
public static void main(String[] args)
{
try
{
Main m1=new Main("The constructor called.");
System.out.println("Successful!");
}
catch (Exception ex)
{
System.out.println(ex);
}
}
}
There is no meaning to deliberately write this statement private Main m=new Main(""); inside the class itself but that statement is not ever supposed to be used by any code in the class then how can that statement cause the exception to be thrown?
Each time you call the constructor, you create an instance and thus execute the initializing code
private Main m=new Main("");
which calls the constructor, etc.
You probably want
private static Main m=new Main("");
in order to keep a singleton.
It's absolutely normal that your program cause a stack overflow ...
The compiler does not check that your member m is used or not in your code, though you are right it could have done it, probably with side effects : object not been built ...
In order to construct a Main object another Main object (the private Main m member) has to be constructed ... which gives an infinite recursion, hence the stack oveflow

Double checked locking in modern JVMs

I have a class that might throw any run-time exceptions during initialization. I want the class to be a singleton since the cost of keeping several objects in memory is high. I am using that class in another class.
My use case is as follows:
I have to use a single instance of Controller.
Each instance of Parent must use the same Controller instance.
Controller
constructor might throw exceptions.
If instantiation fails, I should
retry to instantiate after sometime.
So I check if my Controller instance is null when I try to do a "get" on the Controller, if yes, I try to instantiate it again.
Following is my code:
class Parent
{
private static volatile Controller controller;
private static final Object lock = new Object();
static
{
try
{
controller = new Controller();
}
catch(Exception ex)
{
controller = null;
}
}
private Controller getController() throws ControllerInstantiationException
{
if(controller == null)
{
synchronized(lock)
{
if(controller == null)
{
try
{
controller = new Controller();
}
catch(Exception ex)
{
controller = null;
throw new ControllerInstatntationException(ex);
}
}
}
}
return controller;
}
//other methods that uses getController()
}
My question is, is this code broken? I read somewhere that the above code would be a problem in JVM 1.4 or earlier. Can you provide references/solutions? Please note that I am asking this question because there is a lot of confusion regarding this topic in the internet.
Thanks.
I believe it's not broken, cause of volatile declaration. But imho better to avoid code like this. There is no guarantee, that this code will work with Java 8 for example. There are another way to create lazy singleton. I always (almost) use this method. First time faced with it in Java Concurrency in Practice book.
public class Singleton {
private Singleton() { }
private static class SingletonHolder {
public static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
I don't know what you are doing in your code, it's hard to say, how to tweak it. The most straightforward way, simply use synchronize method. Do you seriously want to receive some performance benefit using double-check-locking ? Is there bottle-neck in synch method ?
The only thing which is broken is to make the example far more complicated than it needs to be.
All you need is an enum
// a simple lazy loaded, thread safe singleton.
enum Controller {
INSTANCE
}
Using an AtomicBoolean (much like I suggested here) would be safer and allows for repeat attempts at instantiation on failure.
public static class ControllerFactory {
// AtomicBolean defaults to the value false.
private static final AtomicBoolean creatingController = new AtomicBoolean();
private static volatile Controller controller = null;
// NB: This can return null if the Controller fails to instantiate or is in the process of instantiation by another thread.
public static Controller getController() throws ControllerInstantiationException {
if (controller == null) {
// Stop another thread creating it while I do.
if (creatingController.compareAndSet(false, true)) {
try {
// Can fail.
controller = new Controller();
} catch (Exception ex) {
// Failed init. Leave it at null so we try again next time.
controller = null;
throw new ControllerInstantiationException(ex);
} finally {
// Not initialising any more.
creatingController.set(false);
}
} else {
// Already in progress.
throw new ControllerInstantiationException("Controller creation in progress by another thread.");
}
}
return controller;
}
public static class ControllerInstantiationException extends Exception {
final Exception cause;
public ControllerInstantiationException(Exception cause) {
this.cause = cause;
}
public ControllerInstantiationException(String cause) {
this.cause = new Exception(cause);
}
}
public static class Controller {
private Controller() {
}
}
}
Yes, it is guaranteed to work by the Java Memory Model on modern JVMs. See the section Under the new Java Memory Model in The "Double-Checked Locking is Broken" Declaration.
As other answers have pointed out, there are simpler singleton patterns, using Holder classes or enums. However, in cases like yours, where you want to allow for trying to reinitialize several times if the first try fails, I believe that double-checked locking with a volatile instance variable is fine.
It is not an answer to your question but this famous article on Double-Checked Locking is Broken explains well as to why it is broken for java 1.4 or earlier version.

Categories

Resources