multiple singleton beans referencing the same class - java

I have a java class lets say 'class1' which basically holds a ConcurrentHashMap (to be used as a cache) and some functions to update and remove the entries in the map.This class is not designed to be a singleton class.
I was having a discussion with a colleague, but couldnt really decide due to a couple of posts i read on the internet.I am asking if it is okay to do this-
<bean id="reqrespCacheMgr1" class="gravity.applications.RFQService.reqrespgtwy.utility.ReqRespCacheManager" scope="singleton">
</bean>
<bean id="reqrespCacheMgr2" class="gravity.applications.RFQService.reqrespgtwy.utility.ReqRespCacheManager" scope="singleton">
</bean>
<bean id="reqrespCacheMgr3" class="gravity.applications.RFQService.reqrespgtwy.utility.ReqRespCacheManager" scope="singleton">
</bean>
I am basically trying to create 3 singleton instances of the same class..I think it doesnt really spoil the meaning of singleton-ness because we are talking about singleton scope in the spring bean factory context and not the class loader context.. I know there are alternate ways to do this.. Like having 3 concurrenthash maps in the same class and using only one singleton bean reference ,there by trying to create update and remove methods for 3 maps in the same class.
I hope i didnt make it confusing but all i wanna know is which is a good approach.I am afraid im making an improper use of design patterns..
Let me know if the question is unclear

It seems you need not a singleton but prototype
<bean id="reqrespCacheMgr" class="gravity.applications.RFQService.reqrespgtwy.utility.ReqRespCacheManager" scope="prototype" />
class B1 {
#Autowire
ReqRespCacheManager cacheManager;
}
class B2 {
#Autowire
ReqRespCacheManager cacheManager;
}
class B3 {
#Autowire
ReqRespCacheManager cacheManager;
}
All 3 beans will get a new instance of ReqRespCacheManager

Looks OK to me, as long as you only need to use those 3 instances for the entire lifecycle of your application. Are you aware that autowiring a single property wont work for this type?
You will need to use #Qualifier to assign a specific instance into your application beans:
public class FooBean {
#Inject
#Qualifier("reqrespCacheMgr3")
ReqRespCacheManager cacheManager;
}
Alternatively, you can collect all three into a single bean by injecting a List component of your type.
#Inject
List<ReqRespCacheManager> caches;
Hope that helps! Good luck, and dont forget to think 2 steps ahead.

Related

How (and when) to initialize a Spring bean which needs to access other beans only known in runtime?

I have a Spring webapp running on Java 5. This is was my applicationContext.xml file:
<bean id="child1" class="foo.ChildOne" />
<bean id="child2" class="foo.ChildTwo" />
<bean id="main" class="foo.Main">
<property name="childrenList">
<list value-type="foo.IChildren">
<ref bean="child1" />
<ref bean="child2" />
</list>
</property>
</bean>
Both ChildOne and ChildTwo classes implement the IChildren interface. And in my Main class, I have defined a childrenList which gets populated with child1 and child2 beans. Easy, right?
But in the future, there might be no child1, and instead, we will maybe have a child81 based on another unknown class. And it still has to work without touching the current code or XML files, only through configuration. This child81 would be defined on its own applicationContext file (in a JAR), and we will list the bean names in a database field (child2,child81,etc).
I guess that's not a good design pattern; most likely it's a terrible, horrible, painful, you-better-run-while-you-can design, which will haunt me in the years to come. But I didn't define it, and I can't change it, so please lets assume it's OK for the purpose of this question.
Instead of injecting the beans myself using the applicationContext.xml, I have to retrieve them somehow, in runtime. I can't use autowiring either, because I don't know what class the beans are, all I know is all of their classes implement IChildren.
So I have made my main bean class ApplicationContextAware and I have added this method:
public void loadChildren() {
if (childrenList == null) {
childrenList = new LinkedList<IChildren>();
for (String name : theListOfBeanNames) {
childrenList.add((IChildren) context.getBean(name));
}
}
}
It works alright; each bean is defined in its own applicationContext, and then I retrieve them by name. But... when do I call loadChildren()? So far, I'm doing it in the first line of each one of my methods. Since there is a null-check, it will initialize the list only once. But surely, there must be an easier/cleaner/better way of doing this?
I don't think I can just use the init-method="loadChildren" property in my applicationContext, because then it would fail if my main bean is being loaded before all the children have been... and I can't control the loading order. Or can I?
This is from my web.xml file:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/application-context/applicationContext-*.xml
,classpath*:WEB-INF/application-context/applicationContext-children.xml
</param-value>
</context-param>
(We use the "classpath* notation" to load every applicationContext-children.xml file from within the JARs). If I invert the order and place the children XML before the main ones, would it ensure they will be loaded in that specific order? No matter what version of what application server we use?
I've also seen a #PostConstruct annotation which would be useful if I could add it to my loadChildren method. But when would it be called then? I've read that it's after the injections have been done, but... only for the current bean, right? It doesn't ensure that all the other beans are already loaded?
Is there any other option?
Spring can do this for you:
#Component
public class MyComponent {
#Autowired
private final List<IChildren> children;
...
}
That will autowire in everything than implements IChildren.
Mr Spoon's answer does exactly what I asked, so I'm marking it as the correct answer. However, I forgot to mention that the children order in the list does matter, so I still can't use autowiring. Here is what I ended up doing instead, in case anybody else finds it useful.
As stated in the answers to this question, another option is to catch the ContextRefreshedEvent by implementing the ApplicationListener<ContextRefreshedEvent> interface. That ensures that the loadChildren method is executed only after all the initialization is done.
Since we are using a very old Spring version (2.0.7), our ApplicationListener interface is slightly different, for example it doesn't support generic types. So, instead of doing this, my class looks like this:
public class Main implements ApplicationListener {
public void loadChildren(ApplicationContext context) {
//...
}
public void onApplicationEvent(ApplicationEvent ev) {
if (ev instanceof ContextRefreshedEvent) {
loadChildren(((ContextRefreshedEvent) ev).getApplicationContext());
}
}
}

Singleton in Java and Spring [duplicate]

Could you please explain why Spring is creating two objects for the configuration of beans shown below, since by default spring default scope is singleton?
The Spring configuration is here:
<bean id="customer" class="jp.ne.goo.beans.Customer">
<property name="custno" value="100"></property>
<property name="custName" value="rajasekhar"> </property>
</bean>
<bean id="customer2" class="jp.ne.goo.beans.Customer">
<property name="custno" value="200"></property>
<property name="custName" value="siva"></property>
</bean>
Spring's default scope is singleton. It's just that your idea of what it means to be a singleton doesn't match how Spring defines singletons.
If you tell Spring to make two separate beans with different ids and the same class, then you get two separate beans, each with singleton scope. All singleton scope means is that when you reference something with the same id, you get the same bean instance back.
Here is how the Spring documentation defines singleton scope:
Only one shared instance of a singleton bean is managed, and all requests for beans with an id or ids matching that bean definition result in that one specific bean instance being returned by the Spring container.
Singleton scope means using the same id retrieves the same bean, that is all. Testing that no two ids referenced the same class would get in the way of using maps as beans, and would be complicated by proxying things with BeanFactories.
For Spring to police this would involve a lot of work for little benefit. Instead it trusts the users to know what they're doing.
If you want a bean’s singleton-ness preserved across multiple names, that is do-able. You can have more than one name refer to the same bean, that is done by using an alias:
In a bean definition itself, you can supply more than one name for the bean, by using a combination of up to one name specified by the id attribute, and any number of other names in the name attribute. These names can be equivalent aliases to the same bean, and are useful for some situations, such as allowing each component in an application to refer to a common dependency by using a bean name that is specific to that component itself.
Specifying all aliases where the bean is actually defined is not always adequate, however. It is sometimes desirable to introduce an alias for a bean that is defined elsewhere. This is commonly the case in large systems where configuration is split amongst each subsystem, each subsystem having its own set of object definitions. In XML-based configuration metadata, you can use the element to accomplish this.
So if you add a name in the bean configuration:
<bean id="customer" name="customer2"
class="jp.ne.goo.beans.Customer">
</bean>
or create an alias for a bean defined elsewhere:
<alias name="customer" alias="customer2"/>
then "customer" and "customer2" will refer to the same bean instance.
Spring default scope is singleton and it will create one object for all instances unless you explicitly specify the scope to be prototype. You have not posted spring configuration. Please post it, it will give a better idea.
In Spring Singleton refers to One bean per Spring container where as in Java Singleton refers to one object per class loader.
So Spring singleton is not same as java singleton. Don't get confused between these two.
You're confusing two different concepts.
The word singleton in spring is used for a bean scope, meaning that the bean will be created only once for the whole application.
Singleton usual meaning refers to the GOF pattern. It is an object oriented pattern guarantying that only one instance of a class will exists (at least in the scope of the classLoader).
You are declaring two beans of the same class. That isn't the same.
#Component("springTestClass")
public class SpringTestClass{
private int randomNumber = 0;
public SpringTestClass(){
randomNumber = new Random().nextInt(2000);
}
public int getRandomNumber(){
return this.randomNumber;
}
}
And try to access this bean in two places the number will be the same. But what you have done was creating two separate beans.
If you want to check if this works try:
public class Main{
public static void main(String[] args){
ApplicationContext ctx = ....;
SpringTestClass testObject1 = (SpringTestClass)ctx.getBean("springTestClass");
SpringTestClass testObject2 = (SpringTestClass)ctx.getBean("springTestClass");
System.out.println(testObject1.getRandomNumber() == testObject2.getRandomNumber());
}
}
This code should return true if it is same instance;
But in SpringTestClass you can add #Scope("prototype") annotation.
The output will be false
Like others have mentioned, two beans should be created from the code you posted. Singletons are defined as follows (from the Spring documentation: Singleton Scope)
Only one shared instance of a singleton bean is managed, and all requests for beans with an id or ids matching that bean definition result in that one specific bean instance being returned by the Spring container.
To add clarity to this, the meaning behind "shared instance" is explained in the paragraph that follows the one above:
all subsequent requests and references for that named bean return the cached object
When a singleton bean is created, only one bean object is instantiated and cached. This refers only to the bean, not to whatever class the bean may be an instance of. For example,
<bean id="myBean" class="myPackage.myClass" />
<bean id="myOtherBean1 class="myPackage.myOtherClass1">
<property name="beanReference1" ref="myBean" />
</bean>
<bean id="myOtherBean2 class="myPackage.myOtherClass2">
<property name="beanReference2" ref="myBean" />
</bean>
In this made up configuration, "myOtherBean1" and "myOtherBean2" have references to the same "myBean" bean therefore the same "myPackage.myClass" instance. If you changed the code to add a second "myPackage.myClass" bean, it would be distinct from "myBean".
To fully understand this, also refer to the other Spring scope: the prototype. From the Spring documentation for Prototype Scope:
The non-singleton, prototype scope of bean deployment results in the creation of a new bean instance every time a request for that specific bean is made.
This means that if we were to use the same Spring XML as above, "myOtherBean1" and "myOtherBean2" would each receive their own distinct copies of "myBean" which is still just an instance of "myPackage.myClass".
Spring Singleton Bean Does not work like Java Singleton.
If we write
ApplicationContext ctx = new ClassPathXmlApplicationContext("MyConfig.xml");
Customer obj1= (Customer) ctx.getBean("customer");
Customer obj2 = (Customer) ctx.getBean("customer2");
System.out.println(obj1 == obj2);
System.out.println(obj1+ "::" + obj2);
If we see the output it will return 2 different Instance.
According to Spring Docs
Bean is singleton only one shared Instance will be managed, and all request beans with an ID or ID matching that bean definition. Here 2 different ID is available.
Spring container as managing Key value pair, Key as ID/Name and value is bean.
The following example shows a #Bean annotated method being called
twice:
#Configuration
public class AppConfig {
#Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
#Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
#Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
clientDao() has been called once in clientService1() and once in
clientService2(). Since this method creates a new instance of
ClientDaoImpl and returns it, you would normally expect having 2
instances (one for each service). That definitely would be
problematic: in Spring, instantiated beans have a singleton scope by
default. This is where the magic comes in: All #Configuration classes
are subclassed at startup-time with CGLIB. In the subclass, the child
method checks the container first for any cached (scoped) beans before
it calls the parent method and creates a new instance. Note that as of
Spring 3.2, it is no longer necessary to add CGLIB to your classpath
because CGLIB classes have been repackaged under
org.springframework.cglib and included directly within the spring-core
JAR.
spring default scope is singleton. Once the bean will be created and same bean used throughout its lifecycle.

chicken and egg Spring bean binding

Ok, so here is my use case:
I have the following classes each encapsulating an instance of the next one in line. So:
A -> B -> C -> D
eg: In class A, I have an instance of class B and in class B I have an instance of C and so on.
Well, I am trying to convert the loading\initialization\injection logic to a hybrid Spring system. The general idea being that B, C and D will need to more or less be ApplicationContextAware. By that I mean, that they will not actually implement that interface, but instead require the ApplicationContext as a constructor parameter. This way, in the hybrid approach (where the developer does not use Spring to initialize the instance) they must at least pass in the ApplicationContext so that additional beans may be wired. The problem is, that in order for the Spring container to load the beans, I now have to pass in the ApplicationContext in the XML. But as far as I can tell, there is no nice way to do this.
I tried something like this:
public class ApplicationContextPlaceholder implements ApplicationContextAware {
private ApplicationContext _applicationContext;
public void setApplicationContext( final ApplicationContext applicationContext ) throws BeansException {
_applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return _applicationContext;
}
}
<bean id="a" class="com.company.A">
<constructor-arg>
<bean id="applicationContext" class="com.company.ApplicationContextPlaceholder" />
</constructor-arg>
</bean>
But obviously this doesn't make any sense, since ApplicationContextPlaceholder isn't really an ApplicationContext. I've also looked for ways to reference the context inside the XML, but I'm not finding anything.
Does anyone know of an elegant solution to this type of problem?
EDIT #1:
I was thinking about it, and I could have ApplicationContextPlaceholder also implement ApplicationContext and just delegate to the injected context and then it occurred to me that maybe, just maybe this was already in Spring...but as far as I can tell, no.
EDIT #2:
The reason each class needs an ApplicationContext is that if a dev wishes to override one of the classes in the chain (say, C for sake of argument). In this instance the child class of C will still need to load D via Spring.
Unless a class is providing additional plumbing functionality, you should avoid exposing the ApplicationContext. Quoting the Spring reference: in general you should avoid it, because it couples the code to Spring and does not follow the Inversion of Control style.
If you are providing additional functionality (maybe, for example, a factory class that uses the ApplicationContext to assemble objects), then it's prudent to implement ApplicationContextAware since your functionality is already tied to Spring.
If you've considered your dependency injection alternatives and have decided on injecting the ApplicationContext in your beans, your ApplicationContextPlaceholder class (I would stay away from a Placeholder prefix to avoid any confusion with Spring property placeholders) is certainly a solution. (Since it is your own class, why not extend ApplicationObjectSupport for additional functionality.)
This class will need to be defined and initialized in your configuration, for example:
<bean id="appCtxHolder" class="ApplicationContextHolder" />
Because ApplicationContextHolder implements ApplicationContextAware, Spring will inject the ApplicationContext into appCtxHolder when it is initialized. You can use it for constructor injection like:
<bean id="a" class="com.company.A">
<constructor-arg>
<bean factory-bean="appCtxHolder" factory-method="getApplicationContext" />
</constructor-arg>
</bean>
ApplicationContextPlaceholder could have everything static. In that case, you don't need to pass ApplicationContext around, when a API requests for a certain bean, you could check if its null and if it is, load it using the ApplicationContext from ApplicationContextPlaceholder. That's assuming a setter based injection, if you are doing constructor based, you could init beans in the contructor too.

Java EE 6 injection to create different strategies

Say that I have class Controller with property strategy of type IStrategy. In Spring, I can create different instances of Controller and inject different strategy implementations by defining beans in xml configuration file as shown below:
<bean id="strategyAController" class="com.test.Controller">
<property name="strategy" ref="strategyAImpl">
</bean>
<bean id="strategyBController" class="com.test.Controller">
<property name="strategy" ref="strategyBImpl">
</bean>
<bean id="strategycController" class="com.test.Controller">
<property name="strategy" ref="strategycImpl">
</bean>
I can then reference these beans using #Autowired and #Qualifier("strategyAController"), etc. What is the equivalent way of doing this in Java EE 6
Funny you should ask! Gavin King, who designed Java EE 6 CDI, got into a nasty fight with someone on exactly the same problem.
http://www.tsolak.com/?p=59
The Spring code, of course, looks awfully like Java. We can do that in java - create some variables, set some properties, no biggie. I am curious, in your perticular application, what's the drawback of doing it in plain Java? What's the specific benefit you get from Spring for these beans?
In CDI you can use Qualifer to identify the different instances and producer methods to provide that instances.
public class ControllerFactory {
#Produces
#StrategyA
public Controller createControllerA {
return new Controller(configA);
}
#Produces
#StrategyB
public Controller createControllerB {
return new Controller(configB);
}
}
#StrategyB
#Inject
Controller howToAccessIt;
If you do not like to create a new StrategyA/B/C Annotation for each strategy, you could use one Annotation with an Field (for example an Enum) that identify the strategy. So that you can write: #Strategy(StratType.A).
Then you can use the InjectionPoint in your producer method, so that you can create the instance depending on the annotation in a generic way, instead of writing a new producer method for each Strategy:
#Produces
//must add a Annotation to clarify that this producer produces for all Strategies!
public Controller createController(InjetionPoint ip) {
Annotated annotated = ip.getAnnotated();
if (annotated.isAnnotationPresent(Strategy.class)) {
Strategy stragtegyAnnotation = (Strategy) annotated.getAnnotation(Strategy.class);
switch(stragtegyAnnotation.value) {
case A: return new Controller(configA);
...
}
}
}
So, I'm not really familiar with EE6 annotations, but I solved a similar issue using pure Spring annotations in a question that I asked and then answered myself. It's not quite the same thing because it only creates once instance, but with all of the different dependencies injected into a Map. Basically, it will allow to switch implementations based on a config flag, but not instantiate all of them at once.

How to autowire a bean inside a class that is not a configured bean?

Forgive me if I don't get the terminology correct.
My situation is thus:
I have a class, let's call it TheClass. Inside this class is a TheData object.
I have XML to set up the TheData bean, like so:
<bean id="theData" class="com.abc.TheData">
<property name="field" value="value1" />
</bean>
and a setter inside TheClass like so:
public void setTheData(TheData theData)
{
this.theData = theData;
}
My problem is that if I don't also create the TheClass bean in the XML (and thus can't let it get autowired), it won't know to autowire the theData field (right?). And due to certain restrictions, I can't configure TheClass in the XML (and thus later have it autowired). So, my question is, how can I make this work? I'm a bit of a novice so if I'm missing something, feel free to point it out.
If you can get hold of the Spring context, cast it to AutowireCapableBeanFactory, and pass your instance of TheClass to the autowireBean(Object) method. Spring will then try to apply its autowiring rules to that object.
You'd need to add #Autowired to the setTheData method, though.
You could use #Resource or #Component.
I just now saw this question and thought I might add one more method of doing what you want (although the AutowireCapableBeanFactory would be my choice).
You can leverage the #Configurable annotation in the manner that is described in this blog post
You should be able to just use the #Autowired annotation on your instance variable that your setter is setting, without having to declare a TheClass bean in your XML. That is:
public class TheClass {
#Autowired
private TheData theData;
}

Categories