I am trying to create a Singleton class, which will be accessed from two other classes.Can anyone please tell me whats wrong with the following code? I am just not able to figure out!
import java.util.LinkedList;
public class MessageQueue {
private static final LinkedList<ServerDataEvent> queue = new LinkedList<ServerDataEvent>();;
private static MessageQueue messageQueue = null;
/** A private Constructor prevents any other class from instantiating. */
private MessageQueue() {
}
/** Static 'instance' method */
public static MessageQueue getInstance() {
if (MessageQueue.messageQueue == null) {
System.out.println("Creating MessageQueue instance.");
MessageQueue.messageQueue = new MessageQueue();
}
return MessageQueue.messageQueue;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
I am accessing the singleton object from other classes like this:
MessageQueue messageQueue = MessageQueue.getInstance();
There are no errors, but
System.out.println("Creating MessageQueue instance.");
is getting executed whenever I do
MessageQueue messageQueue = MessageQueue.getInstance();
EDIT 1
import java.util.LinkedList;
public class MessageQueue {
private static final LinkedList<ServerDataEvent> queue = new LinkedList<ServerDataEvent>();;
private static final MessageQueue messageQueue = new MessageQueue();
/** A private Constructor prevents any other class from instantiating. */
private MessageQueue() {
System.out.println("problem...");
}
/** Static 'instance' method */
public static MessageQueue getInstance() {
return MessageQueue.messageQueue;
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
}
First of all, you did not specify any errors you get. If you want to get help, you should give us as much information as you can.
Secondly, the best fool-proof way to create a singleton in Java is this:
public enum MySingleton {
INSTANCE;
//whatever methods you want to implement
}
and you access it like so: MySingleton.INSTANCE.whatever().
It is much better to define and instantiate your singleton object like this:
private static final MessageQueue messageQueue = new MessageQueue();
And then getInstance will be just:
public static MessageQueue getInstance() {
return MessageQueue.messageQueue;
}
This way your singleton object is instantiated and will be thread safe because it is created by the class loader.
A shorter version which is thread safe.
public enum MessageQueue {
INSTANCE;
private final Queue<ServerDataEvent> queue =
new ConcurrentLinkedQueue<ServerDataEvent>();
public void addEvent(ServerDataEvent event) { queue.add(event); }
}
or
public enum MessageQueue {
;
private static final Queue<ServerDataEvent> queue =
new ConcurrentLinkedQueue<ServerDataEvent>();
public static void addEvent(ServerDataEvent event) { queue.add(event); }
}
would be easier if you did it this way...
public class MessageQueue {
private static final MessageQueue INSTANCE= new MessageQueue();
public static MessageQueue getINSTANCE() {
return INSTANCE;
}
private MessageQueue() {
}
}
What's the error that occurs? All I can see from this is you have two semicolons here:
private static final LinkedList<ServerDataEvent> queue = new LinkedList<ServerDataEvent>();;
Simplest method:
private static final MessageQueue messageQueue = new MessageQueue();
public static MessageQueue getInstance() {
return MessageQueue.messageQueue;
}
Related
I have a singleton class like this
public class EventProcessor{
//........
private EventProcessor() {
Client client = ClientBuilder.newClient();
String scheme = requiredHttps() ? "https" : "http";
m_webTarget = client.target(..........);
}
public static EventProcessor getAuditEventProcessor() {
return m_EventProcessor.instance();
}
protected boolean requiredHttps() {
// read value from config file
// Configuration class is also a singleton and getConfig() is a static method
Map map = Configuration.getConfig().getCurrent().getSecuritySettings().getSettings();
//...............
}
}
when I write the unit test, I have a setup method like this
private EventProcessor m_EventProcessor;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
m_EventProcessor = EventProcessor.getAuditEventProcessor();
}
I got ExceptionInInitializerError for "m_EventProcessor = EventProcessor.getAuditEventProcessor();" Can someone help me to figure out what's the peoblem for that? Is it because call a singleton class in another singleton class?
I have to add custom method method to my logging system. Let's say I have in several places line of code like:
private static Logger LOGGER = LoggerFactory.getLogger(MyJavaClass.class);
Logging is handling by slf4j. How can I extend my logger with adding new(!) method like public void error(SomeTypeObject obj) { /implementation/ }
The goal is to not change existing code. How can I force LoggerFactory to return my own Logger implementation extended with mentioned method?
I followed answers for this queston: stackoverflow.com/questions/2653855/implement-custom-logger-with-slf4j
So, I've made my LoggerFactory, StaticLoggerBinder and MyLoggerAdapter.
StaticLoggerBinder
public class StaticLoggerBinder implements LoggerFactoryBinder {
private static final StaticLoggerBinder SINGLETON = new StaticLoggerBinder();
public static final StaticLoggerBinder getSingleton() {
return SINGLETON;
}
public static String REQUESTED_API_VERSION = "1.6.99";
private static final String loggerFactoryClassStr = MyLoggerFactory.class.getName();
private final ILoggerFactory loggerFactory;
private StaticLoggerBinder() {
loggerFactory = new MyLoggerFactory();
}
public ILoggerFactory getLoggerFactory() {
return loggerFactory;
}
public String getLoggerFactoryClassStr() {
return loggerFactoryClassStr;
}
}
Logger Factory
public class MyLoggerFactory implements ILoggerFactory {
ConcurrentMap<String, Logger> loggerMap;
public MyLoggerFactory() {
loggerMap = new ConcurrentHashMap<String, Logger>();
}
public Logger getLogger(String name) {
Logger simpleLogger = loggerMap.get(name);
if (simpleLogger != null) {
return simpleLogger;
} else {
Logger newInstance = new MyLoggerAdapter(name);
Logger oldInstance = loggerMap.putIfAbsent(name, newInstance);
return oldInstance == null ? newInstance : oldInstance;
}
}
void reset() {
loggerMap.clear();
}
}
MyLogger
public class MyLoggerAdapter implements Logger {
//methods from Logger interface
//and my additional method
public void error(Exception ex) {
//do smthng;
}
}
Now, in MyJavaClass i have a field
private static Logger LOGGER = LoggerFactory.getLogger(MyJavaClass.class);
The problem is, when i try to LOGGER.error(myExceptionObject) the method is not visible. I am missing something. I would be very grateful for help.
In your MyJavaClass you should use your MyLoggerFactory:
private static MyLoggerAdapter LOGGER = MyLoggerFactory.getLogger();
instead of
private static Logger LOGGER = LoggerFactory.getLogger(MyJavaClass.class);
In this example logger can get so:
private static MyLoggerAdapter log = (MyLoggerAdapter) StaticLoggerBinder.getSingleton().getLoggerFactory.getLogger(MyController.class.getName());
I have Java app with Spring running on tomcat.
This class is causing a very strange problem for me:
#WebListener
public class ThreadPool extends ThreadPoolExecutor implements ServletContextListener {
private ThreadPool() {
super(MIN_ACTIVE_THREADS, MAX_ACTIVE_THREADS, DEACTIVATE_THREADS_AFTER_TIMEPERIOD, TimeUnit.SECONDS, taskQueue);
}
private static final ThreadPoolExecutor pool = new ThreadPool();
public synchronized static void submit(Task task) {
executingTasks.add(task);
pool.execute(task);
}
#Override
public synchronized void contextDestroyed(ServletContextEvent arg0) {
cancelWaitingTasks();
sendStopSignalsToExecutingTasks();
pool.shutdown();
}
...
}
If the constructor is private or default I get this exception during runtime (on first HTTP request to the app):
Error configuring application listener of class com.testApp.util.ThreadPool
java.lang.IllegalAccessException: Class org.apache.catalina.core.DefaultInstanceManager can not access a member of class com.testApp.util.ThreadPool with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
at java.lang.Class.newInstance(Class.java:436)
at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:140)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4888)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5467)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Skipped installing application listeners due to previous error(s)
Error listenerStart
Context [] startup failed due to previous errors
But if i set the constructor public then I get no exceptions and everything works fine. Can anyone tell me why is this default or private constructor causing runtime exceptions?
Tomcat uses Class.newInstance() to create an instance of your ThreadPool. This method obeys the access rules of Java.
Since your constructor is private it fails with a IllegalAccessException. This is the runtime equivalent of not being allowed to call a function to the compiler error which you see if you would try to write new ThreadPool() outside of ThreadPool,
Tomcat's org.apache.catalina.core.DefaultInstanceManager is trying to create an object of your ThreadPool which you have configured as context listener. Now, since this is outside of org.apache.catalina.core you have to use a public constructor else org.apache.catalina.core.DefaultInstanceManager will not be able to create its object.
From org.apache.catalina.core.DefaultInstanceManager
private Object newInstance(Object instance, Class<?> clazz) throws IllegalAccessException, InvocationTargetException, NamingException {
if (!ignoreAnnotations) {
Map<String, String> injections = injectionMap.get(clazz.getName());
processAnnotations(instance, injections);
postConstruct(instance, clazz);
}
return instance;
}
Through the error, it said clearly because it cannot access a member of class.
can not access a member of class com.testApp.util.ThreadPool with modifiers
I think I accidentally discovered the real reason I was getting exceptions. Currently I am using this class, no exceptions thrown, tested on GlassFish and Tomcat:
public class TrackingThreadPool extends ThreadPoolExecutor {
private static final int MAX_WAITING_TASKS = 4000;
private static final int MAX_ACTIVE_THREADS = 20;
private static final int MIN_ACTIVE_THREADS = 4;
private static final int DEACTIVATE_THREADS_AFTER_SECONDS = 60;
private TrackingThreadPool() {
super(MIN_ACTIVE_THREADS, MAX_ACTIVE_THREADS, DEACTIVATE_THREADS_AFTER_SECONDS,
TimeUnit.SECONDS, waitingTasks);
}
private static final BlockingQueue<Runnable> waitingTasks = new LinkedBlockingQueue<>(MAX_WAITING_TASKS);
private static final Map<Long, Task> executingTasks = new HashMap<>(MAX_ACTIVE_THREADS * 2);
private static final TrackingThreadPool instance = new TrackingThreadPool();
public synchronized static void submitAndTrack(Task task) {
executingTasks.put(task.getId(), task);
instance.execute(task);
}
public synchronized static void shutdownAndCancelAllTasks() {
cancelWaitingTasks();
sendStopSignalToExecutingTasks();
instance.shutdown();
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (r instanceof Task) {
executingTasks.remove(((Task) r).getId());
}
}
private static void cancelWaitingTasks() {
List<Runnable> waitingTaskListRunnables = new ArrayList<>(waitingTasks.size() + 10); //+10 to avoid resizing
waitingTasks.drainTo(waitingTaskListRunnables);
for (Runnable r : waitingTaskListRunnables) {
if (r instanceof Task) {
((Task) r).sendStopSignal(byShutdownMethod());
}
}
}
private static void sendStopSignalToExecutingTasks() {
for (long taskId : executingTasks.keySet()) {
Task executingTask = executingTasks.get(taskId);
executingTask.sendStopSignal(byShutdownMethod());
}
}
private static String byShutdownMethod() {
return TrackingThreadPool.class.getSimpleName() + "#shutdownAndCancelAllTasks()";
}
}
And if I swap the positions of BlockingQueue<Runnable> waitingTasks and TrackingThreadPool instance like this:
private static final TrackingThreadPool instance = new TrackingThreadPool();
private static final Map<Long, Task> executingTasks = new HashMap<>(MAX_ACTIVE_THREADS * 2);
private static final BlockingQueue<Runnable> waitingTasks = new LinkedBlockingQueue<>(MAX_WAITING_TASKS);
I get exceptions again because waitingTasks is not instantiated by the time I make a new TrackingThreadPool instance.
I guess you can have a subclass of ThreadPoolExecutor with a private constructor / singelton pattern.
I have written a Thread Pool and I am not able to write the Junits(PowerMock) for that class.
public enum ThreadPool {
INSTANCE;
private static final String THREAD_POOL_SIZE = "threadpool.objectlevel.size";
private static TPropertyReader PROP_READER = new PropertyReader();
private final ExecutorService executorService;
private static final ILogger LOGGER = LoggerFactory
.getLogger(ReportExecutorObjectLevelThreadPool.class.getName());
ThreadPool() {
loadProperties();
int no_of_threads = getThreadPoolSize();
executorService = Executors.newFixedThreadPool(no_of_threads);
}
public void submitTask(Runnable task) {
executorService.execute(task);
}
private static void loadProperties() {
try {
PROP_READER.loadProperties("Dummy");
} catch (final OODSystemException e) {
LOGGER.severe("Loading properties for app failed!");
}
}
private int getThreadPoolSize() {
return Integer.valueOf(PROP_READER
.getProperty(THREAD_POOL_SIZE));
}
}
While Mocking this class I am getting NullPointerException in the line PROP_READER.loadProperties("DUMMY");
My Test Case is:-
PowerMockito.whenNew(PropertyReader.class).withNoArguments().thenReturn(mockPropertyReader);
PowerMockito.doNothing().when( mockPropertyReader,"loadProperties",anyString());
mockStatic(ThreadPool.class);
First you need to set your internal state of your enum as enum is final class
and the instance of an enum will be load on class loading
ThreadPool mockInstance = mock(ThreadPool .class);
Whitebox.setInternalState(ThreadPool.class, "INSTANCE", mockInstance);
then
PowerMockito.mockStatic(ThreadPool .class);
and then mocking
doNothing().when(mockInstance).loadProperties(any(String.class));
do not forget adding the following annotation to the test
#RunWith(PowerMockRunner.class)
#PrepareForTest({ThreadPool.class})
if it still not working you need to see which more member of the class you need to set in the internal state
I'm developing computer vision application and I will need Classifier class. This class will be immutable per run of application and it loads the trained data from disk on initialization. I want to ensure that whole program will have access to same trained data and I want to block reloading the from disk once they are loaded.
What I was considering was to use either static class or singleton. I'm not sure how to load data to static class, because the path to data file is not know at compile time - it will be program argument. So I was thinking of Singleton pattern, but there I don't know how to initialize it dynamically.
My idea was to use following:
class Singleton {
private static Singleton instance;
private Singleton() { ... }
private static SomeDataObject data;
public static Singleton getInstance() {
if(instance == null)
instance = new Singleton();
return instance;
}
public static init(string dataPath){
if(data == null)
loadDataFromFile(dataPath)
}
}
This would not work, because I have no control which method will be called first.
I know the proper way would be to create the instance with data at the begining and pass it to all classes and methods which need it, but that's not really general solution. I can keep track of all calls to Classifier in my own code, but if I would make the code as API, this would be a problem.
In short how to initialize singleton at runtime?
I don't think (exactly) what you want to do would work.
The below would work:
public static void main(String[] args)
{
Singleton.init("somepath");
...
Singleton.getInstance().doingStuff();
...
}
A better implementation may be: (which would cause a NullPointerException if you try to use it without calling init first) (not really Singleton any more though)
private static Singleton instance;
private SomeDataObject data;
private Singleton(String path) { loadDataFromFile(path); ... }
public static Singleton getInstance() {
return instance;
}
public static void init(String dataPath){
instance = new Singleton(dataPath);
}
Then there's: (possible bad coding practice aside)
class Main
{
public static void main(String[] args)
{
Singleton.currentPath = "somepath";
...
}
}
class Singleton
{
public static String currentPath = null;
private static Singleton instance;
private SomeDataObject data;
private Singleton(String path) { loadDataFromFile(path); ... }
public static Singleton getInstance() {
if(instance == null && currentPath != null)
instance = new Singleton(currentPath);
return instance;
}
}
which I suppose doesn't really solve much.
I use something that is "more" threadsafe than the current winning solution with almost no synchronized used.
import java.util.function.Supplier;
public class InitOnce {
/**
* Marked as final to prevent JIT reordering
*/
private final Supplier<String> theArgs;
private InitOnce(Supplier<String> supplier) {
super();
this.theArgs = supplier;
}
/**
* Uses the arguments to do something
*
* #return
*/
public String doSomething() {
return "Something : " + theArgs.get();
}
/**
* Initializes all the things
*
* #param someArgs
*/
public static synchronized void init(final Supplier<String> someArgs) {
class InitOnceFactory implements Supplier<InitOnce> {
private final InitOnce initOnceInstance = new InitOnce(someArgs);
#Override
public InitOnce get() {
return initOnceInstance;
}
}
if (!InitOnceFactory.class.isInstance(instance)) {
instance = new InitOnceFactory();
} else {
throw new IllegalStateException("Already Initialized");
}
}
private static Supplier<InitOnce> instance = new InitOnceHolder();
/**
* Temp Placeholder supplier
*
*/
private static final class InitOnceHolder implements Supplier<InitOnce> {
#Override
public synchronized InitOnce get() {
if (InitOnceHolder.class.isInstance(instance))
throw new IllegalStateException("Not Initialized");
return instance.get();
}
}
/**
* Returns the instance
*
* #return
*/
public static final InitOnce getInstance() {
return instance.get();
}
}