How do you handle Java Singletons when a network connection fails? - java

I have created a Singleton for my class which contains an instance of MemcachedClient (this could be any object that requires making a connection to a server but I am providing a concrete example). I initialize the MemcachedClient in a static init block. If the MemcachedClient cannot create an instance due to a connection error, this now means my class is worthless because it has a null MemcachedClient instance.
My question: What is the best solution for this type of situation? How are other people handling this situation?

The question (as stated in the title) is too broad, it depends of what the singleton is for.
In your case, the obvious question: if the initialization fails, can you expect that the issue will be solved in the near future? What is the cost of keep trying (redesign so your app does not crashes downward in weird ways) instead of just rebooting your app?
If you do not expect the error to be solved easily, just crash your application (with the proper logs/alerts/notifications). If you want it to keep running until the issue resolves, then the steps would be:
1) Pass the initialization to the constructor of the singleton (why put it in a static block if you can control access to the constructor).
2a) While the constructor fails, calls to getInstance will return null. Modify your application to be able to handle it.
2b) If the issue is present, create a singleton without the proper initialization. Calls to the methods of this objects will do nothing until the initialization issue has been solved / the object has been initialized. Modify your application to be able to handle these dummy methods. This method is swifter but way more complicated.
3) When a new instance is requested (if 2a) or a method is called (if 2b), check again if the object can be initialized.
Compare the cost of all the previous with the cost of just restarting your app after the issue has been solved.

Related

Is this a good reason to use a Singleton?

I'm making an Android app that will have the timetables of a local bus.
There are more than one timetable, the one that will be use depends on the day.
If it's a holiday I must use a special timetable, so I want to know when is a holiday and when is not.
The thing is that I'm creating a class that will handle this, it will try to retrieve information from memory or from a web api. Then some other classes will be able to communicate with this class, but it doesn't seem necessary to me to have more than one instance of this class, I could create just one instance and share it with the rest of the classes.
Could this class be a Singleton or it would be better if I create a normal class ?
In your case (retrieving info from memory), definitely avoid using a singleton class because it will highly likely be tied to your Activity context.
Your class will have a static reference to a class, therefore
it will be kept in memory when not needed.
singleton may be reinstantiated, or may use obsolete instance, with new instations of activities. You will lose control of the current variables.
diffent instances of the same activity class are highly likely to conflict with this class.
Examples of the same activity class several instantiation:
Change device orientation.
Running app from the webbrowser's, Google Play, file browser intent.
Besides, at some point, when you add functionality based on user reviews, your app will grow, you are likely want to refactor your class, break it into subclasses, put some of its methods into separate threads. It will no longer be easy to do.
It might seem fun while the app is small, and untested, but later, in Android specifically, you will run into a nightmite with unpredictable and hard to detect errors.
Because of Android's special way to recreate activity class, through onCreate, onResume etc. you will run into a nightmare, when the app will start living its own life.
You will no longer be able to rely on the assumption that the current singleton instantiation actually belongs to your current activity.
You may swap between orientations or run your app from different entry points (launcher, recent apps, google play), and it may reuse the variables actually prepared for a different activity instantiation.
If you need only one instance of the class, just create one instance of the class in the onCreate method - and that will make the app much more manageable.
One of the main advantages a Singleton class brings you is the fact that you are sure to have one and only one instance of an object doing some thing, and that it is instantiated only once (preferably at a specific point of your application, for instance at startup or only after certain other operations have been performed)
An example could be for instance a cache implementation: you want to make sure that all classes that need a certain cache read and write from the same object, that maybe is created and filled with information at startup time.
Your does not seem to be the case, unless you fetch the information you need when your application starts and then you keep them memorized for some reason: in this case you want to make sure your information is fetched one and only one time, to avoid wasting memory and elaboration time. Also, a Singleton is fine if you need to do some kind of operation when your class is instantiated, like opening a connection that then stays open.
On the other hand, if you just need a class with some method to call some external apis or database and you don't need to memorize any information in it, there is no reason to initialize a singleton.
If this is your case, why don't you try some static class/methods? They can be called like normal methods directly on the class with no need to instantiate objects or keeping a state, saving memory and avoiding side effects.

Enforce method call to avoid throwing exception

I have a library and to create an instance, I use the connectWith() method to send database model:
Wallet wallet = new WalletPoket();
wallet.connectWith(
DAOFactory.getDAOFactory(DAOFactory.MYSQL)
);
Followed by these methods:
int privateCardId = wallet.addCard(1, "Economy 1");
boolean wasDeleted = wallet.deleteCard(privateCardId);
...
Calling the previous methods will result in a NullPointerException if the connectWith() method is not called prior.
Is it possible to force the user to call the connectWith() method or present the user with a warning if they do not?
Would it be acceptable to call the method from the constructor?
Wallet wallet = new WalletPoket(
DAOFactory.getDAOFactory(DAOFactory.MYSQL)
);
What would be the best alternative?
You have a few options.
Force the user to pass the option as an argument to the constructor.
Throw an exception with a message stating that connectWidth must be called if it was not called.
If there is a good default thing to connect with, then connect with that in the constructor.
This is where things get a bit verbose, since it means:
You have to check state before you do anything, and
You have to guard against developers doing silly things.
One thing you can do is check the state of your connection (ensuring that it's not null), then throwing an IllegalStateException explaining why it blew up:
if(null == daoFactory) {
throw new IllegalStateException("You are attempting to invoke this without a DAO Factory defined.");
}
...but you'd have to add this check to every method that you had in your program.
A preferred approach in my mind would be to add this to the constructor of the object, since that clearly captures the need to have this dependency before the entity is constructed. So effectively, I agree with your second approach.
The last thing you could do is do some fancy annotation processing to force a specific compiler warning or error should this dependency go missing, but it's likely a lot more straightforward to add it in as a constructor dependency instead.
If the addCard and deleteCard method calls are crucial to the Object's functionality (i.e almost always called), then add it as a constructor.
Otherwise, you can simply throw a detailed IllegalStateException when they're called in the wrong order. You should also document the library methods accordingly explaining what's needed for them to function properly.
The (library) class Wallet should have provided a constructor that takes the database endpoint. Since it is not available, you could provide a utility wrapper that accounts for it. That way, your utility wrapper can mandate the endpoint and make sure that it is available beforehand.
Another thing you can explore is dependency injection, i.e. whenever a client needs a Wallet, it does #Inject Wallet wallet. This, admittedly, has added complexity, but it renders the code that is more easily testable. (See javax.inject, or dagger).
I think, you should implement proxy design pattern to solve the problem.
When the client creates a Wallet, they should get the proxy of the Wallet instance.When client invokes the service API say addCard then Real Wallet object instance comes into picture(lazy loading) and does the dao instantiation which is a singleton instance.

Is the class loading different between standard JVM and Android Dalvik

the question might be a bit vague because i'm not sure how to put the scenario into context.
I'm trying to implement a factory pattern for object creation on my current Java program, which is a standalone app. I tried to use the self-registering way of creating the object list in the factory, as detailed in here
I encountered an error along the way though, that the static block in the object was never executed, and the list remained empty. I did a bit of research and found that the static block will only be executed one time, during the time when the class is loaded by the JVM.
That wonders me though, because i'd used the same method on a Android application before, and it worked without an issue. The static block will just execute to register the object itself to the factory.
Is there a difference between these 2 VM that is causing this behavior?
Thank you

Reading the same ResultSet from multiple threads

In the database, I have a definition table that is read from the application once upon starting. This definition table rarely changes, so it makes sense to read it once and restart the application every time it changes.
However, after the table is read (put into a ResultSet), it will be read by multiple handlers running in their own threads.
How do you suggest to accomplish this?
My idea was to populate a CachedRowSet, and then create a copy of this set (through the createCopy() method) for each handler every time a new request comes.
Do you think this is wise? Does this offer a good performance?
Thanks.
It may be better for you to use the singleton pattern. This would allow you to create a single class that all of your threads could access to get the object that they needed. This could also allow you to not have to shut down your application whenever changes are made. One way to accomplish this is to have a class where you have get and set methods for the information you need. And another class that will give out references of that object.
The class that gives out references could have a private constructor, and a getInstance method that will return a reference to itself to ensure that only one exists. This would also give you some other options regarding what you can do when things change.
Ok, if you control access to the resultSet, and you don't care to update the result set until you restart the application, then i would suggest wrapping the CachedRowSet in a custom class. One possible way to do this is to have a wrapper class that is a singleTon and provide it with getter methods so that other threads or classes for that matter can access it. That way you remove the need to make a copy and remove the dependency on CachedRowSet implementation. Creating a copy would cause unnessary overhead. Imagine, in the way you described above, if you had 1000 threads accessing your result set, you would call createCopy() 1000 times thus creating a 1000 copies of the same resultSet.
I think it is a pattern to read the configuration table into a static data structure (ConcurrentHashMap) and then let the threads to look it up.
You can ensure that there is no write race at startup by populating the reference map from a Servlet.init() - it is guaranteed to execute once per servlet.

Stateless session bean with instance variables

I have a stateless session bean that contains one public method, several private methods, and some instance level variables. Below is a pseudo code example.
private int instanceLevelVar
public void methodA(int x) {
this.instanceLevelVar = x;
methodB();
}
private void methodB() {
System.out.println(instanceLevelVar);
}
What I'm seeing is that methodB is printing values that weren't passed into MethodA. As best I can tell it's printing values from other instances of the same bean. What would cause this?
I should point out the code works as expected 99.9% of the time. However, the .01% is causing some serious issues / concerns for me.
I understand that if I had different public methods then I might not get the same bean back between calls, which would result in this behavior. However, in this case the only call is to the single public method. Will the container (Glassfish in this case) still swap the beans out between private method calls?
(edit) I renamed "class level" to "instance level" as this was causing some confusion.
When I read What is a Session Bean? section of the J2EE 1.4 tutorial:
Stateless Session Beans
A stateless session bean does not maintain a conversational state for a particular client. When a client invokes the method of a stateless bean, the bean's instance variables may contain a state, but only for the duration of the invocation. When the method is finished, the state is no longer retained. Except during method invocation, all instances of a stateless bean are equivalent, allowing the EJB container to assign an instance to any client.
In your case, the call to methodB() from methodA() will be on the same instance and is equivalent to this.methodB(). I'm thus tend to say that methodB() can't output something else that the value that what was passed to methodA().
This is confirmed by the first sentence in section 7.11.8 in the EJB 2.0 spec: "The container must ensure that only one thread can be executing an instance at any time". This means you cannot come to a situation where data (in your instance variables) from different clients (threads) will be mixed. You are ensured unique access to the instance variables until methodA() has returned!
That said, I'm not saying that you don't have a problem somewhere. But I don't think that your pseudo code is equivalent.
(EDIT: Having read some comments to the OP's question, there is now clearly a doubt about the pseudo code and semantic used. I'm clarifying possible consequences below.)
As underlined by Rocket Surgeon, what do you mean exactly by class variable? Do you really mean class variable as opposed to instance variable? If yes, the pseudo code doesn't reflect it but this will clearly lead to unpredictable behavior. Actually, from section 24.1.2 (and first point) in the EJB 2.0 spec, it is clear that you are not allowed to write data to a class variable (although you can do it). There must be a good reason for this :)
I would just not bother using instance variable in stateless session bean at all. Regardless of what the cause of the issue you have encountered, it's probably not something you would want to do anyway. Just try using local variables throughout or define instance variables in helper classes you are calling from the stateless session bean business methods.
The likely cause of the issue is that the container is using the same object in two requests (therefore two threads) at the same time. So the first thread gets to line that calls methodB and then the next thread gets to the code which calls methodB and then the first thread executes the call to methodB, causing the issue. That would explain the behavior, at any rate. It doesn't seem to fit the spec, but that could just be a bug.
In general, even if permitted, keeping state in the bean is not a great idea. It leads to confusion code and can easily lead to bugs where you forget to start over with your all your state on every method call.
It would be much better to just pass those objects around between methods, and that would avoid all issues.
Probably your are not properly reinitializing the instance variable.
Instance variables
In general we should not keep state in our stateless session bean. Objects referenced by instance variables, if not nulled after their use, are kept alive until the end of the request and even longer if our EJB container pools the session beans to reused. In the latter case we need to make sure that instance variable get properly reinitialized during a subsequent request. Therefore the use of instance variables may lead to the following issues:
during the same request, instance variable shared between different methods can easily lead to bugs where we forget to start over with the correct state on every method call
in case EJB container pools session beans and we may our code fails to properly reinitialize the instance variables we may reuse stale state set in a previous request
instance variables have instance scope which could introduce memory leak problems where space in the Heap is used to keep objects that are not (or should be not) used anymore.
Class variables
As for instance variables, class variables should not be used to keep shared state in Stateless session bean. This does not mean we should not use the static keyword but that we should use it with caution (e.g. define immutable constants, some static factory class, etc.)
Because this is very strange I performed a quick test with Netbeans and my local Glassfish 2.1.
Create a new project using Samples->Java EE->Servlet Stateless. This creates an enterprise project with a simple stateless bean and a servlet that uses it.
I modified the stateless bean to look like this, as close to your example as possible I think.
#Stateless
public class StatelessSessionBean implements StatelessSession {
String clName;
private void testNa() {
System.out.println(clName);
}
public String sayHello(String name) {
this.clName = name;
testNa();
return "Testcase";
}
}
This works as it should. I don't know what editor you're using, but if it's Netbeans it may be interesting to run it yourself.
It all hinges on what you mean by "class level variable". A class variable must have the static modifier. If clName doesn't, then each instance of your stateless session bean has its own copy of clName. Your Java EE server probably created a pool of two or more instances of the stateless session bean, and each of your calls to testNa() and sayHello() gets sent to an arbitrary instance.
I stumbled upon this question when I experienced the same problem. In my case, the private method actually sets the instance variable. What I have noticed is that sometimes the instance variable was already set, obviously from a previous request.
#Stateless
public class MyBean {
String someString;
public void doSomething() {
internalDoSomething();
}
private void internalDoSomething() {
if (someString != null) {
System.out.println("oops, someString already contained old data");
}
this.someString = "foo";
}
}
I guess it makes sense. When the container re-uses a cached instance, how should it know how to clear the variables...
To me, this is inline with and confirms both Pascal's reference to the EJB spec ("instance variables are supported") and Rocket Surgeon's recommendation ("don't do it, use local variables instead").
The problem with using Instance variables in stateless Beans.
According to the JEE specification that same stateless EJB instance might be shared with another client as well. The thumb rule is not to create instance variables in Stateless EJBs.
It might be possible the two clients accessing the application simultaneously are provided same EJB instance which would create problems since there is data inconsistency.
So it is not a good idea to use instance variables in stateless EJB beans .
I had similar issue because I used global static class variable in my ejb class and when I had concurrent stateless EJB running, variable was overwritten by other instances.
Static class fields are shared among all instances of a particular class, but only within a single Java Virtual Machine (JVM). Updating a static class field implies an intent to share the field's value among all instances of the class.
Hope help someone else :)

Categories

Resources