I'm hoping to make some calls to solr using Alfresco's org.alfresco.repo.search.impl.solr.SolrAdminHTTPClient class. However that bean search.solrAdminHTTPCLient does not seem to be accessible to me from the standard application context. Attempting to add a dependency and property reference for my own bean (via xml) has failed as well. Any reason this is not accessible?
public class MyClass extends DeclarativeWebScript implements ApplicationContextAware{
...
SolrAdminHTTPClient adminClient = (SolrAdminHTTPClient) appContext.getBean("search.solrAdminHTTPCLient");
Would like to avoid creating my own clients for standard solr admin queries.
Judging by the folder tree leading to this file, I would say that bean is available in the search SubSystem which means it lives completely in a different context, a child context in fact.
So you need to lookup that context first, before trying to retrieve your bean !
UPDATE: I have done some digging, and I guess that your window to that child context is in this particular bean.
So I think you can do the following :
SwitchableApplicationContextFactory search = (SwitchableApplicationContextFactory)applicationContext.getBean("Search");
ApplicationContext searchCtx = search.getApplicationContext();
SolrAdminHTTPClient adminClient = (SolrAdminHTTPClient) searchCtx.getBean("search.solrAdminHTTPCLient");
A friend from the IRC channel has however suggested an alternative solution:
Set up a seperate ChildApplicationContextFactory for Each and every bean you which to access in your child context, and he suggested you get some inspiration from this.
Related
I have a few classes that interact with databases (more than one). Some classes are reused so for example "obs.table1" is used to interact with table1 in database "obs" while "ref.table1" is used to interact with table1 in database "ref". These databases are at different URLs and each gets its own connection pool, etc... obs.table1 and ref.table1 are both instances of MyTable1Class, defined in beans file.
I have a pointcut that intercepts calls to methods annotated with #Transactional or with a custom annotation #MyTablesAnnotation and have it set so those calls will all get routed into a #Around advice.
This all works and the flow through the advice is correct.
What I am trying to add is reporting on what is going on in there. Currently I can tell where in there I am, but I can't tell if it was obs.table1 or ref.table1 object that got me there.
Is there a way to extract the bean id of the object on whose method the advice was invoked on?
ProceedingJoinPoint that is passed to the method the only thing I do with it is call a .proceed on it and the rest is just various checks and catches. I see that I can get either the target class or proxy class out of it, but... not sure how to go from there to knowing what the bean id was.
Is it possible?
Firstly it is not recommended to depend on bean id as it creates tight coupling with framework.
To quote from docs Note that it is not usually recommended that an object depend on its bean name, as this represents a potentially brittle dependence on external configuration, as well as a possibly unnecessary dependence on a Spring API.
Now to answer your question yes it is possible to fetch the name of bean via org.springframework.beans.factory.BeanNameAware.
The class for which you require the bean name should implement it and spring will auto-magically inject the name of the bean. However there is a gotcha which you should be aware and is mentioned in docs here
I have had chance of working on only one project using spring , and the way it worked was
Make a singleton class (lets say MySpringHelper), that has method like getBean(String beanName)
What getBean(String) does is, it first checks existence of applicationContext, if it exists uses same to get the bean , else creates new applicationContext and returns the bean
Wherever in you project you need a bean simply call MySpringHelper.getBean("abc")
Keeping this in mind , when i was studying spring , i noticed interface "ApplicationContextAware" ... I am not sure when will this be needed, uses above pattern such interface seems not of any use. Or the above Singleton MySpringHelper pattern/approach is incorrect ??
Looking forward to learn from your experience
To give more details on application , its like a pdf file generator, 1 pdf file having 12-15 different charts, so the main method runs 1 thread for each chart , and inside these chart logic we are using singleton MySpringHelper
Why are you checking the existance of applicationContext? It should be there if your helper bean is configured in xml and has setter method in it. There is no need to create application context in that case.
For your case, I would suggest you get applicationContext injected by Spring rather than by using ApplicationContextAware.
Can anyone explain what happens when we call
ApplicationContext.getApplicationContext().getBean(abcclassName.class)
being the abcclassName being an abstract class.
I understand that an abstract class cannot be instantiated. Then how does this work?
I have never done this with Abstract Classes, but with Interfaces.
What it will do is to get the instance of the subclass defined in your context. In other words if you have a bean of the class Cat (subclass of Animal) defined in your context and you use the class Animal to pass to your ApplicationContext.getBean(). You will get the Cat back.
If you have more than one subclass in your context, it will throw an exception though.
See this for reference: http://docs.spring.io/spring/docs/3.0.x/api/org/springframework/beans/factory/BeanFactory.html#getBean%28java.lang.Class%29
Looking through the source code for DefaultListableBeanFactory -- source -- should answer your question. (Both links are for version 3.0.x, as that is what I found with GrepCode. I imagine that not much has changed in terms of finding the matching beans by a type)
Basically, it takes the class, and looks for Beans in the ApplicationContext that are assignable to the provided type.
The method AbstractBeanFactory#isTypeMatch(String, Class<?>) contains the code that will be of most interest to you, and there is a path that reaches it via the DefulatListableBeanFactory#getBean(Class<?>) method.
After going through Source code Spring 3.0.5 , when you do ApplicationContext.getApplicationContext().getBean(abcclassName.class) on abstract class and if the abstract class is not configured as #component then the AbstractBeanFactory calls the isTypematch method to get the Correct Entity .
Basically it takes all beans ( which ever initiated in context) and iterate one by one and will check that bean is factory for requested or the bean can be assignable for the requested.
if only one bean resolved using that type then it returns that bean if its found multiple beans then it returned error .
return !BeanFactoryUtils.isFactoryDereference(name) &&
typeToMatch.isAssignableFrom(beanInstance.getClass());
The typeToMatch.isAssignableFrom(beanInstance.getClass()); call use Native method in Object class public native boolean isAssignableFrom(Class<?> cls); to check
I have a servlet based application which currently uses an injected HashMap of command processors to process a user entered command. This works very well but I need to modify this so that each instance of the command processor is unique.
The new requirements comes from the need to "pipe" the output on one command into another so if the command processors remain a single instance "piping" a list into a list would be problematic.
I still need to be able to map the class that handles the command to the command text.
My first thought was the change the HashMap from mapping the command to an instance of the command processor to mapping it to the class name and using that to instantiate an instance of the class. But that does not work due to the need to configure some of the commands with for example a list of options.
I have looked at making the beans prototypes which would seam to do what I want regarding getting a new instance of the configured bean but I am confused as to how I can map this, was thinking I could use the bean ID.
I am now at the stage of complete confusion and cant think how to do this.
I am aware that the explanation is a little light but this is a reflection of my confusion and I suspect that the greatest help will come from request for clarification which will help to get the head in order.
You could use request-scoped beans:
#Component
#Scope(value=WebApplicationContext.SCOPE_REQUEST,proxyMode=ScopedProxyMode.TARGET_CLASS)
public class CommandProcessor {
}
You can just inject CommandProcessor in your code and Spring will make sure you get different instance for every user request. You also will need CGLIB on your classpath.
If I got your requirements right you either need a factory method in your command class, or a FactoryBean that creates the instances.
If I am using spring frame work in my application does creating an object like this Test test = new Test() a bad way for creating an instance? Should I always use the bean config to get the objects/bean that I need? If yes, does that means I should have all the object/bean definition in spring applicationContext xml file?
If you want your object to be managed by Spring (this means that dependencies are injected, among other things) you have to use the ApplicationContext.
Calling Test test = new Test() isn't illegal, or even bad practice. It just means that Spring will have no awareness of this object, and it won't bother autowiring it's dependencies, or doing anything else that you'd expect Spring to do.
You don't necessarily need to use the applicationContext.xml file for ALL of your bean declarations. Many people favor annotations, which allow you to declare beans outside of the applicationContext.xml file.
It's worth nothing that Spring-managed beans are by default singletons (think of Servlets). If you want stateful beans that are Spring aware, you could use an ObjectFactoryCreatingFactoryBean to do something like this:
#Autowired
private ObjectFactory myWidgetFactory;
public void doStuff() {
Widget w = myWidgetFactory.getObject();
}
You can read more about this behaviour here:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBean.html
For me there's a big difference between objects that represent components of my application -- services, controllers, DAOs, utilities, etc. -- and objects that represent entities within my application -- Person, Order, Invoice, Account, etc. The former type of objects should absolutely be managed by Spring and injected. The latter type are typically created on the fly by the application, and that frequently will involve calling new. This is not a problem.
Test test = new Test() a bad way for
creating an instance?
Yes it is bad practice.
Should I always use the bean config
to get the objects/bean that I need?
Yes, if you are using Spring for dependency injection.
If yes, does that means I should have
all the object/bean definition in
spring applicationContext xml file?
Always! You could use Annotations too.