In one of the interview I got asked about to how to make sure single object is present of a Singleton class when used with multiple classloaders.I followed this SO Question but I couldn't understand how we should invoke the getClass(). As there is no information about it in the answer and as well as in the link provided in the answer. I am new to classloaders and things aren't that clear for me. I have tried the code and tried multiple combination but every time I am getting two instance instead of one.
package com.design_pattern;
import java.io.*;
import java.lang.reflect.Constructor;
public class SIngletonPattern {
public static void main(String[] args) throws Exception {
DatabaseConnection databaseConnection = DatabaseConnection.getDatabaseConnection();
ClassLoader classLoader = SIngletonPattern.class.getClassLoader();
System.out.println(classLoader);
//Class classs = classLoader.getClass().forName(DatabaseConnection.class.getName());
Class classs = DatabaseConnection.getClass(DatabaseConnection.class.getName());
System.out.println(classs.getName());
Constructor[] declaredConstructors = classs.getDeclaredConstructors();
DatabaseConnection db2 = null;
for (Constructor d:declaredConstructors) {
d.setAccessible(true);
db2 = (DatabaseConnection) d.newInstance();
}
if(db2 == null){
System.out.println("null");
}else{
System.out.println(databaseConnection == db2);
}
}
}
class DatabaseConnection implements Serializable {
private static volatile DatabaseConnection databaseConnection;
private DatabaseConnection() {
System.out.println("Instance created");
}
public static DatabaseConnection getDatabaseConnection() {
System.out.println("getInstance()");
if (databaseConnection == null) {
synchronized (DatabaseConnection.class) {
if (databaseConnection == null) {
databaseConnection = new DatabaseConnection();
}
}
}
return databaseConnection;
}
protected Object readResolve() {
return databaseConnection;
}
public static Class getClass(String classname)
throws ClassNotFoundException {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader == null)
classLoader = DatabaseConnection.class.getClassLoader();
return (classLoader.loadClass(classname));
}
}
Related
I'm trying to write a junit test for one of my classes. The design was not done by me; this is a fairly old application, java7, struts1, and clydeDB framework.
The classes are set up like this:
ProcessObj,
IProcessObj (interface),
ProcessHome,
public class ProcessHome {
private static ProcessHome instance = new ProcessHome();
//default Constructor
private ProcessHome() {
}
public static ProcessHome getInstance() {
return instance;
}
public IProcessObj getProcessObj() throws POException {
return ProcessObj.getInstance(); //this is below
}
}
public class ProcessObj implements IProcessObj {
// instance
private static IProcessObj instance;
...
//constuctor
private ProcessObj() throws POException {
init();
}
static IProcessObj getInstance() throws POException {
if (instance == null) {
instance = new ProcessObj();
}
return instance;
}
//jUnit test setUp
#Before
public void setUp() throws Exception {
public static IProcessObj iPO;
iPAO = ProcessHome.getInstance()
.ProcessObj();
Constructor<ProcessObj> pa = ProcessObj.class
.getDeclaredConstructor();
pa.setAccessible(true);
iPO = pa.newInstance();`
...
It works fine up to here, but then in the ProcessObj, the initialization method goes through another set of classes that are set up exactly like the process objects that are above, for the data access layer.
Is there a way that I can create a usable instance of the process object? Can someone explain to me what exactly is going on here? I keep getting a InvocationTargetException.
Why you don't do something like this:
public class ProcessHome {
private static ProcessHome instance = new ProcessHome();
//default Constructor
private ProcessHome() {
}
public static ProcessHome getInstance() {
return instance;
}
public IProcessObj getProcessObj() throws POException {
return ProcessObj.getInstance(); //this is below
}
}
public class ProcessObj implements IProcessObj {
// instance
private static IProcessObj instance;
...
//constuctor
private ProcessObj() throws POException {
init();
}
static IProcessObj getInstance() throws POException {
if (instance == null) {
instance = new ProcessObj();
}
return instance;
}
//jUnit test class
public class ProcessHomeTest {
private IProcessObj iPO = ProcessHome.getInstance()
.ProcessObj();
#Test
public void testIProcessObj() throws Exception {
//use iPO heretest iPO
assertEquals("some","some");
}
I created a test suite, with a #ClassRule to open the connection etc. Now I can run all my tests, and connection is opened only once.
But now, when I try to run a single test, I get an error, because connection was not opened. How can I solve this?
Code that illustrates what I'm trying to do:
#RunWith(Suite.class)
#SuiteClasses({MyTestCase.class})
public class MyTestSuite {
public static String connection = null;
#ClassRule
public static ExternalResource resource = new ExternalResource() {
#Override
protected void before() throws Throwable {
connection = "connection initialized";
};
#Override
protected void after() {
connection = null;
};
};
}
.
public class MyTestCase {
#Test
public void test() {
Assert.notNull(MyTestSuite.connection);
}
}
EDIT: current solution after #Jens Schauder suggestions. Works, but looks ugly. Is there a better way?
public class ConnectionRule extends ExternalResource {
private static ConnectionRule singleton = null;
private static int counter = 0;
private String connection = null;
public static ConnectionRule newInstance(){
if(singleton == null) {
singleton = new ConnectionRule();
}
return singleton;
}
#Override
protected void before() throws Throwable {
if(counter == 0){
System.out.println("init start");
connection = "connection initialized";
}
counter++;
};
#Override
protected void after() {
counter--;
if(counter == 0){
System.out.println("init end");
connection = null;
}
};
public String getConnection() {
return connection;
}
}
.
#RunWith(Suite.class)
#SuiteClasses({MyTestCase.class, MyTestCase2.class})
public class MyTestSuite {
#ClassRule
public static ConnectionRule rule = ConnectionRule.newInstance();
}
.
public class MyTestCase {
#ClassRule
public static ConnectionRule rule = MyTestSuite.rule;
#Test
public void test() {
Assert.notNull(rule.getConnection());
}
}
MyTestCase2 is identical.
Put the rule on the test, instead of the TestSuite.
You might extend the rule so that:
it does not recreate a connection if it is already there
keeps a reference to the connection, so the connection can get reused by later tests.
the reference to the connection you keep between tests might be a soft or weak one.
Singleton is a service that require injection of authentication and configuration data. I end with class:
class SingleService {
private String conn;
private String user;
private String pass;
private SingleService() {
// Can throw exception!!
conn = Config.getProperty("conn");
user = Config.getProperty("user");
pass = Config.getProperty("pass");
// Can throw exception!!
internalService = tryConnect(conn, user, pass);
}
private static SingleService instance;
public static void init() {
instance = new SingleService();
}
public static synchronized SingleService getInstance() {
if (instance == null) init();
return instance;
}
}
Dedicated init() method used for exception handling during application startup to early detect initialization errors early because later we just call getInstance() and doesn't expect to get errors:
class App {
public static void main(String args[]) {
try {
Config.init("classpath:auth.properties");
SingleService.init();
} catch (Exception ex) {
logger.error("Can't init SingleService...");
System.exit()
}
doJob();
}
private static void doJob() {
SingleService.getInstance().doJob();
}
}
I worry about init() method and singleton class signature. Fill that class was designed badly but don't understand what's wrong.
Is it possible to move away initialization from getSingleton() and synchronized and preserving control on exception during initialization?
This is how I would code it so you can throw exceptions if needed but still have a thread safe singleton.
enum SingleService {
INSTANCE;
private String conn;
private String user;
private String pass;
private SingleService instance;
public synchronized void init(Config config) throws SomeException {
// don't leave in a half state if we fail.
internalService = null;
conn = config.getProperty("conn");
user = config.getProperty("user");
pass = config.getProperty("pass");
internalService = tryConnect(conn, user, pass);
}
public synchronized void methodForService() {
if (internalService == null) throw new IllegalSateException();
// do work.
}
}
SingleService ss1 = SingleService.getInstance();
SingleService.init();
SingleService ss2 = SingleService.getInstance();
So ss1 is a different object than ss2 which is not what Singleton is designed for. If ss1 is modified at anytime ss2 will remain unaffected.
Fist of all you souhld not expose object creation method. If you want to check something, than go with asserts or any operation that will not corrupt instance object.
public static void checkIfValid() {
assert Config.getProperty("conn");// do not corrupt instance object
assert Config.getProperty("user");
assert Config.getProperty("pass");
}
public static synchronized SingleService getInstance() {
if (instance == null){ // only here you can initiate instance object
instance = new SingleService();
}
return instance;
}
My production code for problem I have sought:
public abstract class AbstractCaller<Port> {
abstract protected Port createPort();
protected init() {
Port port = createPort();
// heavy use of introspection/reflection on **port** object.
// Results are used later by **call** method.
}
public call() {
// Reflection based on data collected by **init** method.
}
}
public class ConcreteCaller extends AbstractCaller<ConcretePort> {
private ConcreteService service = new ConcreteService();
#Override
protected ConcretePort createPort() {
return service.getPort();
}
private static class Holder {
public static ConcreteCaller INSTANCE;
static {
INSTANCE = new ConcreteCaller();
INSTANCE.init();
}
}
public static Caller getInstance() {
return Holder.INSTANCE;
}
}
Abstract class has common init method that can only operate on fully initialized concrete class. Inner static class is used for lazy instantiation and perform init invocation.
There is no way to apply init method from superclass constructor to avoid need to call init in each implementation.
Can anyone tell me what does this thing do? Also if anyone can give an example if would be helpful.
public class ConnectionManager{
private static ConnectionManager instance = null;
.....}
Here is the complete code:
package com.gollahalli.main;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class ConnectionManager
{
private static ConnectionManager instance = null;
private final String USERNAME = "root";
private final String PASSWORD = "root";
private final String H_CONN_STRING = "jdbc:hsqldb:data/explorecalifornia";
private final String M_CONN_STRING = "jdbc:mysql://localhost/explorecalifornia";
private DBType dbType = DBType.MYSQL;
private Connection conn = null;
private ConnectionManager() { }
public static ConnectionManager getInstance() {
if (instance == null) {
instance = new ConnectionManager();
}
return instance;
}
public void setDBType(DBType dbType) {
this.dbType = dbType;
}
private boolean openConnection() {
try {
switch (dbType) {
case MYSQL:
conn = DriverManager.getConnection(M_CONN_STRING, USERNAME, PASSWORD);
return true;
case HSQLDB:
conn = DriverManager.getConnection(H_CONN_STRING, USERNAME, PASSWORD);
return true;
default:
return false;
}
}
catch (SQLException e) {
System.err.println(e);
return false;
}
}
public Connection getConnection() {
if (conn == null) {
if (openConnection()) {
System.out.println("Connection opened");
return conn;
} else {
return null;
}
}
return conn;
}
public void close() {
System.out.println("Closing connection");
try {
conn.close();
conn = null;
} catch (Exception e) { }
}
}
There is the singleton design pattern.
It used to make sure that only one instance of a class can be created.
public class MySingletonClass {
private static MySingletonClass instance;
public synchronized static MySingletonClass getInstance() {
if (instance == null) {
instance = new MySingletonClass(); // "lazy" initialization
}
return instance;
}
/**
* private constructor can be called only inside of MySingleton class, but not from outside.
*/
private MySingletonClass() {
// your code here
}
}
So, to get an instance of this class in the code, a developer does not use the constructor.
Developer uses the static method getInstance().
MySingletonClass mySingleton = MySingletonClass.getInstance();
Please be careful with singletons. Many novice developers abuse use of singletons and use them as global variables. Don't do it :)
UPDATE:
I added synchronized to the getInstance() method to make it thread safe.
It simply declares a field called instance whose type is ConnectionManager and initializes it to null (which is redundant because that would be its default value anyway).
Most likely the class is a singleton class (only one instance is allowed from them) judging by the instance field declaration and by the name of the class.
It's called the Singleton pattern.
This is used when you need only one object of a class, the singleton. It will be construct only one time and then you can access it through getInstance().
Naive implementation
public class SingletonDemo {
//Holds the singleton
private static SingletonDemo instance = null;
//Overrides default constructor, not to instantiate another one.
//Only getInstance will construct
private SingletonDemo() { }
//Only this method can construct a singleton, always call this one
public static SingletonDemo getInstance() {
if (instance == null) { //No singleton yet, create one
instance = new SingletonDemo();
}
//return the singleton (created this time or not)
return instance;
}
}
I would like to use db4o and I`m learning this using in youtube.com tutorial. Unfortunately I'm not able to find mistake in my code. I would like to know why I have got there error? I added all important library.
Code important class:
package data;
import com.db4o.*;
import com.db4o.config.EmbeddedConfiguration;
public class DataConnection {
private static DataConnection INSTANCE =null;
private final String PATH = "test.db4o";
private static ObjectContainer db;
private DataConnection(){}
private synchronized static void createInstance(){
if (INSTANCE ==null){
INSTANCE = new DataConnection();
INSTANCE.performConnection();
}}
public void performConnection() {
EmbeddedConfiguration config = Db4oEmbedded.newConfiguration();
db = Db4oEmbedded.openFile(config, PATH);
}
public static ObjectContainer getInstance() {
if(INSTANCE == null) createInstance();
return db;
}
public static void closeConnection() {
try{
db.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
Here is this tutorial (important thing 5:44):
http://www.youtube.com/watch?v=dcNfkED53to
Try replacing
new DataConnection.getInstance()
with
DataConnection.getInstance()
The keyword new is only used when creating a new object. Here you are calling a static method.