I am converting a singleton to a Spring bean, so that if the singleton fails to initialize, then entire web application's spring context doesn't load properly.
The advantage of making the Spring context not load properly, is that people will take notice and fix the configuration during deployment itself. As opposed to using 'non-spring bean' singleton: when that throws exception during initialization, nobody notices.. until a actual user complains of missing functionality.
My changes are working as expected.. but I am not sure if I am doing the right thing.
Any thoughts?
The code looks like this:
public class MySingleton {
private static MySingleton INSTANCE = null;
private MySingleton(){}
public static MySingleton getInstance(){
if(INSTANCE == null){
synchronized(MySingleton.class){
if(INSTANCE == null){
try{
doWork()
}catch(Exception e){
throw new IllegalStateException("xyz", e);
}
INSTANCE = new MySingleton();
}
}
}
return INSTANCE;
}
private static void doWork() {
// do some work
}
}
And in the spring config xml, the bean will be defined as:
<bean id="MySingletonBean"
class="com.MySingleton"
factory-method="getInstance" lazy-init="false" singleton="true">
</bean>
Note:
Most of this is similar to the strategy discussed in this article:
http://springtips.blogspot.com/2007/06/configuration-hell-remedy-with.html
Edit 1:
The classes that use this singleton, are not spring beans themselves.. they are just non-spring pojos, that I can't convert to spring. They must rely on getInstance() method get hold of the Singleton.
Edit 2: (copying a comment I made below into this description section)
I am trying to target two things:
I want Spring to initialize the singleton. So that if the
initialization fails, then the application loading fails.
I want the other classes be able to use classes without having to rely on contextAwareObj.getBean("MySingleton")
EDIT 3 (FINAL):
I decided to make this class a singleton.. and am not making it a spring bean. If it fails to initialize, it will log something in the Log file.. hopefully the person doing deployment takes notice.... I abandoned the approach I mentioned earlier because I feel it will create a maintenance nightmare in future, so I had to pick between - singleton - or - spring bean. I chose singleton.
You must declare the INSTANCE field as volatile for double-checked locking to work correctly.
See Effective Java, Item 71.
Why are you using singleton pattern on the first place? Just let Spring create bean for you (with default singleton scope) and... use it. Of course always somebody might create the bean by hand, but this was never a problem in my case.
Dependency injection and Spring-managed bean lifecycle will ease your life significantly (just see how many pitfalls you can avoid). Also note that exceptions thrown from c-tor or #PostContruct method will propagate and cause application context startup to fail as well.
UPDATE: I get your point. This is what came in to my mind:
#Service
public class Singleton {
private static AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
public Singleton() {
final Singleton previous = INSTANCE.getAndSet(this);
if(previous != null)
throw new IllegalStateException("Second singleton " + this + " created after " + previous);
}
public static Singleton getInstance() {
return INSTANCE.get();
}
}
And let Spring do its job. You can use DI when possible and Singleton.getInstance() where you have to.
Also there are more hard-core solutions like compile-time AspectJ weaving and injecting Spring beans basically to everything.
I'm not sure why you'd want to do this. When you tell Spring that a bean should be a singleton, the corresponding class does not need to be a singleton, and does not need a factory. Spring just simply only ever creates one instance.
The linked article makes no sense to me, since there is NO injection happening, that I can see: "AnyService" is calling the singleton factory method; that the singleton is referenced in the app context is irrelevant until it's referenced, and it seems no other bean references it.
True singleton are hard to get working.
Volatile double-checked locking also does not work property. Read about it on wiki http://en.wikipedia.org/wiki/Double-checked_locking
Your best bet is to simply do this
public class MySingleton {
private static MySingleton INSTANCE = new MySingleton();
That is if you do not have any constructor parameters in your real code.
According to me this is a belts-and-suspenders solution.
If you create a bean and declare it as a singleton in the configuration then there should be no need to protect the bean against being multiply created.
You are now basically protecting yourself from someone wrongly configuring the bean.
I personally would "solve" that by documentation in the spring configuration and Javadoc.
To run code at startup (and fail on error) use one of the many ways to register startup events, e.g. see http://www.baeldung.com/running-setup-logic-on-startup-in-spring
Example:
#Component
public class InitializingBeanExampleBean implements InitializingBean {
private static final Logger LOG = Logger.getLogger(InitializingBeanExampleBean.class);
#Autowired
private Environment environment;
#Override
public void afterPropertiesSet() throws Exception {
LOG.info(Arrays.asList(environment.getDefaultProfiles()));
}
}
#Component
public class SingletonDAOImpl {
}
#Component
public class SingletonDAO {
#Autowired private SingletonDAOImpl instance;
public SingletonDAOImpl getInstance(){
return this.instance
}
}
public class WhateverPlaceYouNeedIt{
#Awtowired private SingletonDAO singletonDao;
public void useSIngleton() {
SingletonDAOImpl INSTANCE = singletonDao.getInstance();
}
}
I tried in so many ways to do something like SingletonDao.instance.doSomething()
but just is not in the spring way and you will find so many hacks in order to do this but is incorrect in my opinion
here
You have your Singleton, which can be changed after in a Multiton
For sure is a single implementation
is respecting the INSTANCE pattern as "getInstance"
Is in-memory so each time is the same object as in singleton
is the same principle applied slightly different, very simple, all the time try to KIS implementation(Keep it simple)
Related
I am new to Spring and not sure if there is a simple approach to what I am trying to do. Before I migrated some existing code base to Spring, I was manually loading configuration properties in a singleton class called ConfigurationProvider - pretty straight forward.
Now that I have migrated to Spring Cloud Config, I am trying to determine a pragmatic approach to a global configuration object with little to no manual setup. My current implementation is a not-so-singleton class that almost accomplishes what I am looking to do but comes with a design flaw.
#Configuration
public class ConfigurationProvider {
private static ConfigurationProvider _instance;
#Autowired
private StorageConfiguration storage;
// this being the design flaw
public ConfigurationProvider() {
_instance = this;
}
public static ConfigurationProvider getInstance() {
return _instance;
}
...
}
I considered throwing an exception if ConfigurationProvider::_instance is already initialized but this is just tacking onto the existing code smell. With all the bells and whistles of Spring Boot, I'd imagine there is a cleaner approach using one of the hundreds of annotations that is strapped with this framework.
you don't need the constructor or the static methods & property. Spring boot takes care of managing the object for you.
Wherever you want to use the ConfigurationProvider declare:
#Autowired
ConfigurationProvider configuration;
and use this instance
Martin's answer is preferable to the solution I was looking for. However, there is a way to inject your beans programmatically but it treads along the lines of an anti-pattern. In my case, I cannot refactor the configuration singleton due to design limitations.
#Autowired
private AutowireCapableBeanFactory autowireFactory;
...
autowireFactory.autowireBean(SingletonClass.getInstance());
I may be wrong here , but i am unable to figure out why is Spring creating 2 different objects from a Singleton class. Following is the code:
public class DbSingleTOn {
private static DbSingleTOn dbSingleTOn = new DbSingleTOn();
private DbSingleTOn() {
}
public static DbSingleTOn getInstance() {
return dbSingleTOn;
}
}
public class MyApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"spring-singleton.xml");
DbSingleTOn dbSingleTOn = context.getBean(DbSingleTOn.class);
System.out.println(dbSingleTOn.hashCode());
DbSingleTOn dbSingleTOn1 = context.getBean(DbSingleTOn.class);
System.out.println(dbSingleTOn1.hashCode());
context.registerShutdownHook();
}
}
Output:
18885489
17045421
Spring Config XML:
<bean id="bean1" class="com.singleton.DbSingleTOn" scope="prototype" >
</bean>
It is expected to get different object for a normal class using "prototype" scope, however, Why would "prototype" create 2 objects from Singleton class ?
Just because you create a singleton in a static field this does not have an impact on spring. Spring is simply not aware of that.
Prototype scope just means: return a new instance when getBean is called.
Singleton scope means: create an instance once and always return this one.
Two things. One, Spring has no idea (and really doesn't care) how your class is setup. The fact that you've implemented a programming pattern means nothing to Spring. Two, Spring uses reflection to instantiate the bean types you declare and therefore can use your private constructors.
Every time you request a prototype scoped bean from Spring, it will create a new instance of the bean.
If you don't setup directly how to instantiate the bean, Spring use reflection to call a constructor for create beans. In addition use of default singleton scope, you can also setup factory-method in your xml config to getInstance to tell Spring how to create your beans.
I have a prototype storm app that reads a STOMP stream and stores the output on HBase. It works, but is not very flexible and I'm trying to get it set up in a more consistent way with the rest of our apps, but not having much luck figuring out how the current way of working with Storm. We use spring-jms classes, but instead of using them in the standard spring way, they are being created at run time, and setting dependencies manually.
This project: https://github.com/granthenke/storm-spring looked promising, but it hasn't been touched in a couple years and doesn't build properly since the storm jars have been taken into apache incubator and repackaged.
Is there something I'm missing, or is it not worth my while to get these things integrated?
#zenbeni has answered this question but I wanna tell you about my implementation, it's hard to make spouts/bolts as spring beans. But to use other spring spring beans inside your spouts/bolts you could declare a global variable & in your execute method check whtether variable is null or not. If it's null you have to get bean from application context. Create a class which contains a method to initialize beans if it's not initialized already. Look ApplicationContextAware interface for more information(Spring bean reuse).
Example Code:
Bolt Class:
public class Class1 implements IRichBolt{
Class2 class2Object;
public void prepare() {
if (class2Object== null) {
class2Object= (Class2) Util
.initializeContext("class2");
}
}
}
Util Class for initializing Beans if not initialized already:
public class Util{
public static Object initializeContext(String beanName) {
Object bean = null;
try {
synchronized (Util.class) {
if (ApplicationContextUtil.getAppContext() == null) {
ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");
bean = ApplicationContextUtil.getAppContext().getBean(
beanName);
} else {
bean = ApplicationContextUtil.getAppContext().getBean(
beanName);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
}
Listener for Application Context Change:
#Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext appContext;
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
appContext = applicationContext;
}
public static ApplicationContext getAppContext() {
return appContext;
}
}
Note: Each Worker will initialize spring context because it's running in different JVM.
UPDATE
If you want to use a spring bean class in which you have some values previously assigned try this,
Note: Passing the current class to Bolt's constructor
Class (Topology Creation Class) which is already contains values:
public class StormTopologyClass implements ITopologyBuilder, Serializable {
public Map<String, String> attributes = new HashMap<String, String>();
TopologyBuilder builder=new TopologyBuilder();
builder.setBolt("Class1",new Class1(this));
builder.createTopology();
}
Bolt by using single argument constructor:
public class Class1 implements IRichBolt{
StormTopologyClass topology;
public Class1 (StormTopologyClass topology) {
this.topology = topology;
}
}
Now you could use attributes variable & it's values in bolt class.
In fact, storm-spring seems to be what you are looking for but it is not updated and have limitations (cannot define tasks on bolts / spouts for instance, etc). Maybe you should roll your own integration?
Don't forget your target: a cluster with many workers. How does spring behave when you will deploy your topology with storm api (rebalance for instance) on one more worker? Does it mean it has to instanciate a new Spring context on the worker JVM at startup before Storm deploys the targeted bolts / spouts and defines the executors?
IMHO if you define only Storm components in a Spring configuration it should work (startup configuration for the topology then storm only manages the objects) but if you rely on Spring to manage other components (it seems so with spring-jms), then it could become messy on topology rebalances for instance (singleton per worker / jvm? Or the whole topology?).
It is up to you to decide if it is worth the trouble, my concern with a Spring configuration is that you easily forget the storm topology (it seems it is one JVM but can be many more). Personally I define my own singletons per class-loader (static final for instance or with double check locking if I need deferred instanciation), as it does not hide the (medium-high) complexity.
I realize that this is very after the fact, but did you think of using Apache camel for the JMS connection handling? Camel isn't IOC or DI, but it does model enterprise integration patterns. Maybe that's what you are (were?) looking for?
Nick.
Maybe this tutorial can help you.
http://spring.io/guides/gs/messaging-stomp-websocket/
I'm just getting started with Spring IOC concept. I often see most of the examples found in the internet use the code to get the object.
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Hello hello = (Hello) appContext.getBean("hello");
As a reference from these questions 1 and 2 in the stackoverflow. I've inferred that, it's not necessary to use appContext.getBean("hello") in the code which is considered to be the bad practice. Also, not recommended anymore. Correct me right here, If my inference is wrong.
Keeping that in view, I have made changes in my project accordingly.
Here's my applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
<bean id="utilClassRef" class="org.hd.derbyops.DUtils" lazy-init="false" />
<bean id="appContext" class="org.hd.derbyops.ContextProvider" lazy-init="false">
<property name="utils" ref="utilClassRef" />
</bean>
</beans>
My contextProvider Class Code
public class ContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx;
/**
* Objects as properties
*/
private static DUtils utils;
public void setApplicationContext(ApplicationContext appContext)
throws BeansException {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
public static DUtils getUtils() {
return utils;
}
public void setUtils(DUtils dUtilsRef) {
utils = dUtilsRef;
}
}
For instance, consider a class A that depends on org.hd.derbyops.DUtils.
I'm using the following code line
ContextProvider.getUtils();
inorder to get DUtils Object in class A, thus avoiding usage of ApplicationContext.getBean() anywhere in my code.
Assume, if I have 10 classes and my class A is dependent on all of them, whose objects to be created and accessed without using ApplicationContext.getBean(). In that case also, as done above, I have a thought of creating properties of ContextProvider class followed by setter's and getter's of that property, where in get<PropertyName> is static. So that, I can use it wherever I'm in need of an object, like this
ContextProvider.get<PropertyName>;
Here's my brief question.
Firstly, Is my approach right? If it's right, loading all the beans at the start-up, wouldn't it be a performance killer? How would you do that in your applications without calling getBean atleast more than once?
If you were to design a web-application & you were to implement Spring IOC, without using ApplicationContext.getBean() in any of the code. How would you do that?
Note: with reference to the other questions tagged above
Calling ApplicationContext.getBean() is not Inversion of Control!
The simple answers are yes and no, no, and no. And finally, do a search online for spring MVC, as this probably does what you want.
So, your approach. Yes, you've got most of it right. However, it's considered very bad practice to use static methods for everything. And, you don't need to. Spring is based on the idea that you can simply create normal pojos, and spring will use them as singletons, and inject them into one another (it can also create objects on the fly, but I'm going for the common case here). If you use static classes and methods then:
You can't mock them for unit testing (you're using JUnit right?)
You can't use them with inheritance
Static initialisers are a great way to loose exceptions
etc, etc
So, yes to injection, and no to static stuff.
Next, performance. You're right in that it's a lot slower to use spring, but, if you do all your injection on startup it only happens once. Spring is meant for server side applications where there is likely to be a number of singleton classes passing data around. So, there might be a class to get stuff from a DB, one to process it, and one to display it, and spring is used to wire them together.
If you're using spring in an application where you start up repeatedly, like a command line app, then you are using it for the wrong sort of application, and you probably want to use a builder or something. Spring is meant for big enterprise apps that aren't restarted often.
Finally, if you simply inject all the dependencies for a class into it at startup, and you do this with all your classes, then you don't need to do any getBean stuff at all. Also, using the init-method and destroy-method attributes on a bean means that you can start up processes once spring has finished injecting dependencies. You need only load the context, and your app will spring (pun intended) into existence.
As for web projects, Spring MVC basically takes the whole inversion of control pattern and applies it to web applications. The spring stuff gets loaded by the container, and you can define the URLs to respond to using nothing more than bean names. And most of your code can stay as pojos. If you have something insanely complex, you may want to look at spring web flow, but I'd advise you to make sure that your spring foo is very strong before attempting that.
Here's my example for getting the first instance without actually calling getBean() on ApplicationContext.
public class Test{
// Declare private static variable so that we can access it in main()
private static Triangle triangle;
// Use constructor injection to set the triangle
public Test(Triangle triangle) {
Test.triangle = triangle;
}
public static void main(String[] args) {
// Specify the context file containing the bean definitions
// Spring automatically creates instances of all the beans defined
// in this XML file. This process is performed before you actually make
// a getBean("beanName") call.
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
// Use instance methods of triangle
Test.triangle.draw();
}
}
You can use another way:
In spring.xml (Your bean configuration XML file)
<bean class="com.example.Test" init-method="myMethod">
<constructor-args ref="triangle"/>
</bean>
Now for your main class
public class Test {
private final Triangle triangle;
public Test (Triangle triangle) {
this.triangle = triangle;
}
public static void main (String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
}
// Called by Spring immediately after the Triangle Bean has been created and
// all the properties for the bean have been set. This method name must match
// the one specified with destroy-method attribute in spring.xml
public void myMethod () {
triangle.draw();
}
}
I have a class that looks like so:
public class Configurator {
private static Configurator INSTANCE = null;
private int maxRange = 1;
// many other properties; each property has a default value
private static synchronized Configurator getInstance() {
if(INSTANCE == null)
return new Configurator();
return INSTANCE;
}
public static int getMaxRange() {
getInstance().maxRange;
}
public static void setMaxRange(int range) {
getInstance().maxRange = range;
}
// Getters and setters for all properties follow this pattern
}
It serves as a global configuration object that can be set on app startup, and then is used by dozens of classes throughout the project:
// Called at app startup to configure everything
public class AppRunner {
Configurator.setMaxRange(30);
}
// Example of Configurator being used by another class
public class WidgetFactory {
public void doSomething() {
if(Configurator.getMaxRange() < 50)
// do A
else
// do B
}
}
I'm now importing this code into a Spring project, and am trying to configure my Sprinig XML (beans). My guess is that I could define a lone Configurator bean like so (or something similar):
<bean id="configurator" class="com.me.myapp.Configurator" scope="singleton">
<property name="maxRange" value="30"/>
<!-- etc., for all properties -->
</bean>
That way, when WidgetFactory#doSomething executes, Spring will have already loaded the Configurator class and configured it ahead of time.
Is it correct for me to set the scope="singleton", or does this not matter? Am I setting the static properties correctly? Is there anything else I need to do or consider here? Thanks in advance.
There are some difference between Singleton as a design pattern and Spring's singleton facility. Singleton as a design pattern will ensure you have one object of class defined per Class Loader. Spring's singleton facility (and approach), in contrast, will define one instance per Spring Context.
In this case you can utilize your getInstance() method to be used by Spring to grab your object instance:
<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>
With Spring the singleton bean scope is the default therefore you don't need to define it.
If you want to use configurator as a Spring bean you will have to inject it in other objects, not use getInstance() to grab it. So in other Spring beans use #Autowired or define reference to bean through xml file. If you don't reorganize usage of configurator in other classes, there will no be difference, Spring will instantiate your class, but you will use it as before.
Also I saw that you have an error in designing your singleton. Your getInstance() method should be public, and other methods should not be static. In the example you've used you should use Singleton like this:
Configurator.getInstance().someMethod()
In this case you actually just use the Singleton class, without instantiating any objects! See wikipedia on Singleton (with Java example) for more information on the Singleton design pattern and how to use it.
NOTE: It's worth knowing and attempting to use Configurator as a Singleton and make use Spring's singleton facility. If you do this the benefits will be that you can
Remove the getInstance() method
Make your constructor public
Let the Spring instantiate that single object.
Beans are singleton by default. You can find this/more information out via the spring website.
You shouldn't instantiate a new Configurator in getInstance because it won't refer to the spring loaded bean and that could cause some serious issues. You can wire this bean in and then leave it alone, it won't be null because you've wired it in (and if it is your program will have failed initialising).
Yes, if you want something global, singleton scope is the right option.
a few things worth mentioning here are :
The default scope in spring is singleton, so you don't need to
explicitly set your bean as singleton scope.
Using Spring you do not need to write Singleton pattern style code, such as private instances and a factory methods. That is because Spring will
guarantee that there is only one single instance per Spring
container. Not even to say, your factory method is private.
By the way: this is not Thread-safe:
if(INSTANCE == null)
return new Configurator();
return INSTANCE;
}
Whereas this would be:
private static Configurator INSTANCE = new Configurator();
(Eager Initialization)
private static volatile Singleton _instance = null;
(Lazy initialization with volatile keyword)
It has to do with the way Java allocates Memory and creates instances. This is not atomic, but done in two steps and can be interfered by the thread scheduler.
See also http://regrecall.blogspot.de/2012/05/java-singleton-pattern-thread-safe.html.