CDI. How to check whether bean instantiated or not? - java

I've got a name of CDI #Named bean. For example, 'firedEmployeeBean'.
Is there any way in other CDI bean check whether 'firedEmployeeBean' already instantiated or not?

As already stated if you use #Inject once you check it will be. What you instead want is to have a property to tell you what you want:
boolean initiated;
if this simple solution does not cut it I would recommend to use Deltaspike:
MyBean myBean = BeanProvider.getContextualReference(MyBean.class, true);
Note the second argument, true - from docs: Pass true as second argument, if you look for an implementation of the given interface and an implementation isn't required or it isn't required that there is an instance with the given qualifier (see the qualifier example for further details). http://incubator.apache.org/deltaspike/core.html
Lastly you can use events. Events are really simple to use in CDI. What you need to do is fire the event when the bean is created and have the other bean observe that event.
http://docs.jboss.org/weld/reference/latest/en-US/html/events.html

As an alternative, you can use the CDI BeanManager to manually pull up a bean within a given context (or no context at all). Take a JSF context for example, you can use the following snippet to pull all active instances of MyBean within the context.
public void findBean(String beanName, FacesContext facesContext){
BeanManager cdiBeanManager = (BeanManager)((ServletContext) facesContext.getExternalContext().getContext()).getAttribute("javax.enterprise.inject.spi.BeanManager"); //get the BeanManager in your operational context
Bean bean = cdiBeanManager.getBeans(beanName).iterator().next(); //this actually returns a Set, but you're only interested in one
CreationalContext ctx = cdiBeanManager.createCreationalContext(bean);
MyBean theActualBean = cdiBeanManager.getReference(bean, bean.getClass(),ctx); //retrieve the bean from the manager by name. You're guaranteed to retrieve only one of the same name within the given context;
}
This is a pure Java EE implementation, no third party libs

Related

How can spring using #Resource to register a bean

I am studying someone's code in my company, and found a strange code, but don't know how it work.
The code looks like this
interface A {...}
interface B {...}
class MyClass implements A, B {...}
#Bean
B myB() {new MyClass();}
#Autowired
A a;
//***************** a will inject failed(bean not found) if I delete this part
#Resource
MyClass myB;
//******************
I don't know why spring can find the "a".
I try to delete the #Resource part and it tell me bean not found, so spring use #Resource to do bean register?
I was thought only #Bean can do that(ya, I know xml can do that too), isn't it?
Interesting issue. I assume it happens because Spring uses some kind of optimization/lazy-creation during dependency injection.
This is only my assumption, but it's a quite good explanation for this issue:
When Spring find a #bean annotation, it doesn't immediately creates the bean, instead it only register it. (It's quite logical, beans could depend on each-other, so first it only tries to collect all of the registered beans, before it tries to actually create them). It also collects all the places where a bean is needed to be injected.
Then it tries to fullfill the injections in rounds. As long as it can fullfill at least one injection in a round, it continues the process.
When the beans are registered, they are registered by name and type which come from the annotation properties or from the method name and return type.
So there will be a bean registered with name myB with type B
At the first round it cannot find any beans for
#Autowired
A a;
so it skips it.
Then it tries to inject a bean into
#Resource
MyClass myB;
It can find a registered bean by name. Although the registered bean's type is not the same nor an extension of the required type, this bean was requested by name, and its actual instance type is not known yet, so - I assume - at this point Spring's injection logic trusts the programmers will, and it instantiates the bean by calling myB(), checks the actual type against the required type and because it matches, it happily injects the returned bean and updates the bean type in the registry with the actual type, which is MyClass.
There are no more injections, so it starts the next round:
Now, when it tries to inject
#Autowired
A a;
it still cannot find a bean by name, but it can find a bean where the registered type is an instance of A, so it can inject that bean too.
So, in short:
If you request a bean by name, then Spring will go and check if that bean fullfills the otherwise un-matching type requirements, but if you request a bean by type, it won't check the actual type of all of the available beans, instead raises and exception an let you refine the injection.

How can I tell the CDI container to "activate" a bean?

Suppose I have some class with injections:
class MyBean {
#Inject
Helper helper;
// all sorts of data
}
and this class was created in a way the CDI container is not aware of it like reflection, serialization or new. In this case the helper is null because the CDI did not initialize it for us.
Is there a way to tell CDI to "activate" the bean or at least its injection? e.g., as if it was created with Instance<MyBean>#get?
Right now I have a hack where I do the following:
class SomeClass {
#Inject
Instance<MyBean> beanCreator;
void activateBean() {
MyBean mybean = ... // reflection/serialization/new
MyBean realBean = beanCreator.get();
Helper proxy = realBean.getHelper();
mybean.setHelper(proxy);
beanCreator.destroy(realBean);
}
}
This looks pretty bad but it works for everything I tested. It just shows what the end result is that I want.
Using Wildfly 10.1 if it matters.
First of all, the way you use MyBean is not a CDI way; in fact you operate on so called non-contextual object. What you are doing is taking a non-CDI managed object and asking CDI to resolve injection points. This is quite unusual, as you handle part of the lifecycle (creation/destruction), while asking CDI to do the rest.
In your case, the MyBean class needs to become InjectionTarget, and that is the way you should start looking. In order to trigger injection you will want to do something like this (during creation of MyBean):
// Create an injection target from your given class
InjectionTarget<MyBean> it = beanManager.getInjectionTargetFactory(beanManager.createAnnotatedType(MyBean.class))
.createInjectionTarget(null);
CreationalContext<MyBean> ctx = beanManager.createCreationalContext(null);
MyBean instance = new MyBean();
it.postConstruct(instance); // invoke #PostContruct
it.inject(instance, ctx); // trigger actual injection on the instance
Please note that this approach is usually clumsy (as in hard to make it work and maintain) and it might be better to instead turn your MyBean into a true CDI bean and leaving whole lifecycle management to CDI. For that, however, your question doesn't provide enough information.

How to instantiate a bean during the CDI AfterDeploymentValidation lifecycle event and pass a parameter to the bean?

I'm working on a CDI extension which needs populate a HashMap with all the discovered beans that have a specific annotation and then during the AfterDeploymentValidation lifecyle event instantiate an #ApplicationScoped bean and pass the HashMap to the newly instantiated bean.
Using the following code I can find any beans that have been annotated with #CQRSCommandHandler and populate a HashMap with the name of the bean and parameter set on the annotation.
public class CQRSExtension implements Extension {
private Map<String, String> discoveredCommandHandlers = new HashMap<String, String>();
public <T> void processAnnotatedType(#Observes #WithAnnotations({ CQRSCommandHandler.class }) ProcessAnnotatedType<T> processAnnotatedType) {
AnnotatedType<T> annotatedType = processAnnotatedType.getAnnotatedType();
String commandName = annotatedType.getAnnotation(CQRSCommandHandler.class).command().getName();
String handlerName = annotatedType.getJavaClass().getName();
discoveredCommandHandlers.put(commandName, handlerName);
}
}
What I'm struggling with is how I should eagerly instantiate the bean and pass the HashMap to this bean.
I can find plenty of examples such as this one (http://ovaraksin.blogspot.co.uk/2013/02/eager-cdi-beans.html) that show how to eagerly instantiate any beans that have a specific annotation, however I cannot work out how to instantiate one specific bean and pass a HashMap to this bean.
Ideally I would prefer not to use reflections to scan for the annotation.
How can I instantiate one specific bean and pass a HashMap to this bean? Alternatively this there a better way to achieve the same result without using reflections?
Why do you need to eagerly instantiate the bean?
You have two options:
Inject the extension into the bean instead, and use the HashMap in there.
E.g.
#Inject
public MyAppScopedBean(MyExtension extension) {
this.someHashMap = extension.getHashMap();
}
Pass the HashMap into a producer method to provide injection support for the HashMap.
You're essentially trying to break the concept of DI if you really want to instantiate the bean yourself.
If runtime scanning is an alternative, you might want to take a look at https://code.google.com/p/reflections/
It provides an easy and powerful API.
Otherwise take a look at this link. The example in 16.10 is very similar, since in the example values in beans are set by the extension. You could adapt the example to set the hashMap into your application scoped bean. You would the simply use an observer method like this
ApplicationScopedBean void processInjectionTarget(
#Observes ProcessInjectionTarget<ApplicationScopedBean> pit) { ...
and set the map into the bean in your wrapped InjectionTaget implementation.
https://docs.jboss.org/weld/reference/latest/en-US/html/extend.html#_wrapping_an_literal_injectiontarget_literal

Spring context dynamic change

I've read that dynamic bean definition change. I try it in a simple code example (see code below), and I find it very attractive in situations where I don't want to stop server but add/change bean definition.
Questions:
Is it safe do to so (see code below)?
I've read that it is possible to achieve bean definition change in runtime with help of StaticApplicationContex or BeanPostProcessor or BeanFactoryPostProcessor? So what is the difference?
public class Main {
final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<beans xmlns=\"http://www.springframework.org/schema/beans\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xmlns:context=\"http://www.springframework.org/schema/context\"\n" +
" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n" +
" <context:annotation-config />\n" +
" <context:component-scan base-package=\"vbah\"/>";
final static String contextA =
"<bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextA\"/>\n" +
"</bean></beans>";
final static String contextB =
"<bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextB\"/>\n" +
"</bean></beans>";
public static void main(String[] args) throws IOException {
//create a single context file
final File contextFile = new File("src/resources/spring-config.xml");
//write the first context into it
FileUtils.writeStringToFile(contextFile, header + contextA);
//create a spring context
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
new String[]{contextFile.getPath()}
);
//echo "fromContextA"
System.out.println(context.getBean("test"));
//write the second context into it
FileUtils.writeStringToFile(contextFile, header + contextB);
//refresh the context
context.refresh();
//echo "fromContextB"
System.out.println(context.getBean("test"));
}
}
EDIT:
Can you answer the questions below:
As I understand BeanPostProcess allow you to modify already existed bean instances at runtime by wrapping the object with proxy. Am I right?
AbstractApplicationContext#refresh() drop all singleton beans and recreate them.
But If I want to change the definition of prototype/custom scoped bean?
If I've got two beans: A and B. A has reference to B. If I change the bean definition in such way that it doesn't contain definition of B. Than B instances will be destroyed, but new instances won't be created. Than A will get a null dependency. Am I right?
StaticApplicationContext and BeanFactoryPostProcessor both allow me to change a bean definition in runtime. But what are the difference, pros/cons?
[Main question] Why Spring has 3 mechanism to achieve the same goal. Can you make a brief compoarison (or usecases examples) between AbstractApplicationContext#refresh(), StaticApplicationContext and BeanFactoryPostProcessor please.
Is it safe do to so (see code below)?
You'll have to define safe.
The AbstractApplicationContext#refresh() method javadoc states
As this is a startup method, it should destroy already created
singletons if it fails, to avoid dangling resources. In other words,
after invocation of that method, either all or no singletons at all
should be instantiated.
Basically every bean in your context will be destroyed and all references to them will be dropped, making them candidates for garbage collection. You need to make sure that those beans have appropriate ways to release any resources they might have. There are different ways to do that
Make your class implement the DisposableBean interface.
Add a destroy-method attribute to your <bean> or #Bean definition.
Annotate a method with #PreDestroy.
Note that refresh() will typically eagerly refresh your ApplicationContext, ie. re-instantiate all the beans immediately. You may notice some slow down in your application while that happens.
I've read that it is possible to achieve bean definition change in
runtime with help of StaticApplicationContext or BeanPostProcessor or
BeanFactoryPostProcessor? So what is the difference?
StaticApplicationContext is one of the ApplicationContext classes where you register the bean definitions yourself. In your example, the bean definitions are parsed from your XML file and registered behind the scenes. With StaticApplicationContext, you use registerBeanDefinition(..) or the other registerXxx() methods to explicitly register a bean definition.
A BeanFactoryPostProcessor has access to the BeanFactory being used and therefore all the bean definitions that have been registered. As such, you can retrieve any BeanDefinition you want and modify it. As the javadoc for BeanFactoryPostProcess#postProcessBeanFactory(..) states
All bean definitions will have been loaded, but no beans will have
been instantiated yet. This allows for overriding or adding properties
even to eager-initializing beans.
You can change the bean definition before the ApplicationContext actually uses it.
Finally, a BeanPostProcessor doesn't change the bean definition. You can use a BeanPostProcessor to change how a bean is created but the underlying BeanDefinition will stay the same.
For your edit (which is bigger than the actual answer :) )
As I understand BeanPostProcess allow you to modify already existed
bean instances at runtime by wrapping the object with proxy. Am I
right?
It's not just for proxying, you can do anything you want with the object: modify its properties, register it in some other context, make it null, etc. This goes around the bean definition.
AbstractApplicationContext#refresh() drop all singleton beans and
recreate them.
But If I want to change the definition of prototype/custom scoped
bean? If I've got two beans: A and B. A has reference to B. If I
change the bean definition in such way that it doesn't contain
definition of B. Than B instances will be destroyed, but new instances
won't be created. Than A will get a null dependency. Am I right?
In an ApplicationContext, you declare your bean definitions. If you're going to change a bean definition, change it in a BeanFactoryPostProcessor or declare it differently in the context configuration.
For dependencies, if you destroy the B bean definition, there won't be a bean to inject into A and Spring will complain, throwing NoSuchBeanDefinitionException. Bean injection never injects null unless you explicitly tell it to.
StaticApplicationContext and BeanFactoryPostProcessor both allow me to
change a bean definition in runtime. But what are the difference,
pros/cons?
The two serve completely different purposes. StaticApplicationContext is an ApplicationContext implementation. Here, you declare bean definitions. A BeanFactoryPostProcessor serves to modify those bean definitions in any way, based on whatever condition you care to implement.
Why Spring has 3 mechanism to achieve the same goal. Can you make a
brief comparison (or usecases examples) between
AbstractApplicationContext#refresh(), StaticApplicationContext and
BeanFactoryPostProcessor please.
The goal is not the same. An ApplicationContext is different than a BeanFactoryPostProcessor and comes into play at a different time in the context life cycle (see that nice graph you had in a previous question).
I don't have use cases for you. Learn what each of the above can do and you'll know when to apply them when you get specific requirements.

Spring beans and changing bean parameter in application life cycle

I have a web application that is based on Spring. There is defined a bean that holds some class MyClass that is passed also with beans to MyEndpoint that extends AbstractMarshallingPayloadEndpoint.
MyClass has set some boolean parameter in beans to true.
If my application will change this parameter programically to false, does next request will have it also set to false or it will contains a default bean parameter - true ?
It depends on the scope of the bean (which will default to singleton, if you don't specify one).
If it is of singleton scope, there is one instance of that bean in the application context, and each time you ask for that bean, you get that single instance. If you change it in a request with this scope, then the change will be maintained.
If it is of prototype scope, a new instance is given to you (created with the same parameters) each time you ask the application context for it. If you change it in a request with this scope, then the change will be ignored when you get another instance of this object.
These are the two most commonly used (at least with my time in Spring). There are other scopes (request, session, globalsession), but you should read the documentation on them that Spring provides.
If you want this property to change dynamically according to your application business logic and not only to be reset on every new request (otherwise Request scope will do the magic) consider Factory Methods (especially Lookup Method Injection)

Categories

Resources