I have singleton bean in which I inject resource with #Resource annotation. When I try to retrieve that resource in the method called on event, the resource is null. What's going and why resource is not injected? What solution can be found for this? I can't refuse from using observers.
#Singleton
#javax.ejb.Startup
#Stateless
public class ScheduleManager implements IScheduleManager
{
#Resource
private TimerService timerService;
#Override
#Observer(value=EventConstants.SCHEDULE_CHANGE_EVENT)
public void reSchedule(PtSchedulesDTO schedule)
{
Collection<Timer> timers = timerService.getTimers();
//...
}
//...
}
I am not sure what framework or technology you are using but for annotation (#Resource) to work, usually something must be declared to look for that annotation. It could be declared in an xml file, where it gets pick up by the framework. Also you could also check if you have a TimerService class that you need to annotate or create a bean for the framework to be able to inject it in.
Related
I have several service like that:
#Singleton
public SimpleService {
...
}
I have Managed Bean #ViewScoped which should create some complex objects. These objects should execute business-logic. I need to pass these services to this object.
Example of Managed Bean:
#ManagedBean
#ViewScoped
public class ExampleBean {
#Inject
private SimpleService simpleService;
...
public void customLogic() {
// in this method I should create complex object which should have services and some data.
// current implementation
ComplexObject object = new ComplexObject(SimpleService simpleService, ...)
}
}
Services are injected to Managed Bean by #Inject annotation. For creating these objects - I'm using the constructor and pass these services as params. The question is: can I have better solution than passing services in constructor?
You can:
Inject by method:
private MyService myService;
#Inject
public void setMyService(MyService ms) {
this.myService = ms;
}
Inject by field:
#Inject
private MyService myService;
Fetch reference through CDI (not recommended, except in advanced usecases):
...
MyService myService = CDI.current().select(MyService.class).get();
...
Fetch reference through BeanManager (not recommended, except in advanced usecases or CDI 1.0):
...
BeanManager beanManager = CDI.getBeanManager(); // you can fetch a BeanManager reference by several other methods, I use CDI for simplicity here
MyService myService = beanManager.getReference(MyService.class);
...
If your #Singleton annotation is javax.ejb.Singleton and not javax.inject.Singleton, then your bean is actually a EJB and you can also use any mechanism that allows you to access EJB, such as #Resource annotations, or through the JNDI context.
Personally I tend to inject by method as I find it the most flexible option most of the time. In my opinion it is also the most "portable" to other frameworks (e.g: Spring)
Remember that when you use either the CDI.current() or the BeanManager methods to fetch #Dependent beans, you are responsible to manually destroy the fetched bean when you are done with it, so that you do not fall into this CDI-related memory leak. When using CDI.current() it is as easy as saving the Instance reference and invoking it afterwards:
...
Instance<MyService> msInstance = CDI.current().select(MyService.class);
MyService myService = msInstance.get();
...
msInstance.destroy(myService);
...
The BeanManager method is too low-level and should only be used in CDI 1.0 environments (back when the CDI class did not exist yet). You can read the linked StackOverflow question for more details.
What you are doing is perfectly fine. You are using the ManagedBean as a bridge to inject the services and then passing the injected variables to a ComplexObject that need the services.
The only restriction that should be considered is, could the ComplexObject class be a ManagedBean itself? That way you could inject everything directly on it, but if it is not possible, you may use the bean for that.
I prefer the inject by field option mentioned because I think it is a little more readable.
I'm using a configuration class that uses dynamic bean registration:
#Configuration
public class ConfigClass {
#Autowired
private GenericApplicationContext applicationContext;
#PostConstruct
private void init() {
System.out.println("init");
applicationContext.registerBean("exService", ExecutorService.class, () -> Executors.newFixedThreadPool(10), bd -> bd.setAutowireCandidate(true));
System.out.println("init done");
}
}
If I try to autowire the bean, application startup fails with error Field exService in com.example.DemoApplication required a bean of type 'java.util.concurrent.ExecutorService' that could not be found.
From the logs I can see that the init method on config class wasn't called before the error as the two system out statements were not printed out.
However, when I use applicationContext.getBean(ExecutorService.class) it does work without any issues.
Anyway I can get the bean to Autowire?
I'm deliberately not using the #Bean annotation because I need to register the beans dynamically based on certain conditions.
It could be because you are registering your bean in the middle of the context initialization phase. If your target bean initializes and auto-wires ExecutorService before ConfigClass #PostConstruct is invoked there simply is no bean available.
You can try forcing the initialization order:
#Component
#DependsOn("configClass")
public class MyComponent
#Autowired
private ExecutorService executorService;
However it would be cleaner to register a bean definition using BeanFactoryPostProcessor with BeanDefinitionBuilder:
#Component
public class MyBeanRegistration implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) {
BeanDefinitionRegistry reg = (BeanDefinitionRegistry) bf;
reg.registerBeanDefinition("exService",
BeanDefinitionBuilder
.rootBeanDefinition(ExecutorService.class)
.setFactoryMethod("newWorkStealingPool")
.getBeanDefinition());
}
}
You can do like this:
#Resource
#Lazy
private ExecutorService executorService;
It works.
Actually, I wrote the small infrastructure that deals with such issues. Here is the idea how to do this:
Create a class (lets call it MyClass) that incapsulates ExecutorService.class as a property and declare it as Bean (#Component). Even before that create an Interface (Lets call it MyInterface) that your new class would implement
Create a factory class (Lets call it MyFactory) with method MyInterface getInstance(String) that returnce an instance of your interface. In that factory crate a static property Map[String, MyInterface] and public static method that allows you to add instances of the interface to this map
In MyClass create a constructor that at the end will place newly created instance of itself into that map in the factory with the key of your class name ("MyClass")
Now The trick is that when Spring starts and initializes it creates all its beans. As your MyClass will be created its constructor will place its instance into a factory. So now anywhere in your code you can call:
MyInterface myInterface = MyFactory.getInstance("MyClass");
And you get your bean without worrying about instantiating it. Spring already did it for you. Big extra bonus is non-intrucivness - you don't have to explicitely work with Spring classes
I am trying to use and understand CDI, when I use #Inject in a simple pojo class, it throws me NPE.
example
Greeting.java
public Class Greeting {
public String greet() {
System.out.println("Hello");
}
}
Test.java
import javax.inject.Inject;
public class Test {
#Inject
private Greeting greeting;
public void testGreet() {
greeting.testGreet();
}
}
When I call testGreet() it throws NPE, why is the greeting instance null. Does #Inject way of adding dependency only be used in container managed bean?
Note: jar is not the problem here.
TL;DR:
#Inject-annotated fields are only populated for container-instantiated beans.
Long version:
The CDI container provides you a lot of utilities for easily injecting dependencies to your beans, but it doesn't work by magic. The container can only populate the annotated fields of a client bean if the client bean itself was instantiated by the container. When the container is instantiating the object the sequence of events is as follows:
Your bean's constructor is called.
#Inject-annotated fields (and some other
annotations, #PersistenceContext and #EJB for instance) are
populated.
#PostConstruct-annotated no-args method is called.
Your bean is finished.
You're facing a classic bootstrapping problem, how to move from non-container-managed code into container-managed code. Your options are:
Get access to an instance of BeanManager from your JavaEE container via JNDI lookup. This is technical and a bit clumsy.
Use a CDI extension library such as Apache DeltaSpike. (Example: BeanProvider.getContextualReference(Test.class, false);)
Modify your application to start in a situation where you can inject your Test class rather than calling new Test();. This can be done for example by setting up a startup singleton ejb, which calls your test in it's #PostConstruct-annotated initialisation.
Hope this helps.
You need a JavaEE container, and than you need to define Greeting and Test as managed beans. After that you can inject one in another.
Try to take a look at:
https://docs.oracle.com/javaee/6/tutorial/doc/girch.html
Your class should be implemented from Serializable for being injectable as a "CDI Bean"
I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.
I am using Seam to inject beans to my controller using #In annotation. The injected class has a custom annotation, when calling injectedClass.getClass().getAnnotation(annotationClass) it returns null.
When debug I found that Seam passes a proxy instance so getClass() returns InjectedClass_$$_javassist_seam_5 which doesn't have my custom annotation.
How I can get my custom annotation from the proxy class?
Here's how my classes look like:
#CustomAnnotation(value="myvalue")
#Name("myAnnotatedClass")
public class MyAnnotatedClass extends SuperClass {...}
#Scope(ScopeType.SESSION)
#Name("myController")
public class MyController {
#In("#{myAnnotatedClass}")
private MyAnnotatedClass myAnnotatedClass;
public void actionMethod(){
//call another class which call myAnnotatedClass.getClass().getAnnotation(CustomAnnotation.class)
//then do some reflection for MyAnnotatedClass fields
}
}
Good question.
When you call a method by using Seam, it is intercepted by a proxy. And this one enables #In or #Out-jection. But There is an exception to this rule: it does not work when you call an internal method
So try this code
#Name
public class Service {
#In
private MyAnnotatedClass myAnnotatedClass;
public void myInterceptedMethod() {
// internal method bypass interceptor
// So #In or #Out-jection is not enabled
internalMethod();
}
private void internalMethod() {
System.out.println(myAnnotatedClass.getClass().getAnnotation(annotationClass));
}
}
Added to original answer
You want to retrieve an annotation from your bean. But, because of method interceptor, myAnnotatedClass.getClass() returns a proxy object, not the bean class itself.
For each bean class, Seam creates a Component definition, in which is stored in the application context. The name of the attribute follows this pattern: component name plus .component. So if you have a bean like this one
#Name("myBean")
public class MyBean {
}
Its Componet definition is stored in the attribute myBean.component
So inside your method, you can use
Component myBeanComponentDefinition = (Component) Context.getApplicationContext().get("myBean.component");
Now you can call
myBeanComponentDefinition.getBeanClass().getAnnotation(CustomAnnotation.class);
regards,
If you want less "ComponentDefinition" overbloat, you could also use this which also works for CDI and Spring:
Class.forName(myBean.getClass().getCanonicalName().substring(0,myBean.getClass().getCanonicalName().indexOf("$"))).getAnnotation(MyAnnotation.class)