I know that injection using the #EJB annotation is only possible in an EJB class, a servlet, or a JSF managed bean, but in the same time I need to have an instance of a some injected business interface in a POJO class, so I thought of doing the following:
in my JSF managed bean
#EJB BusinessInterfaceLocal businessInterface;
private void someMethod(){
PojoInterface pojo = new PojoClass(this.businessInterface);
}
and in my POJO class I have this constructor
BusinessInterfaceLocal businessInterface;
public PojoClass(BusinessInterfaceLocal businessInterface){
this.businessInterface = businessInterface;
//The following throws a Null Pointer Exception
this.businessInterface.someMethodCall();
}
Shouldn't the above work correctly? but it doesn't, the businessInterface object at the PojoClass is evaluated to null, and thus throwing a null pointer exception.
I was hoping if anyone could point me out, on what I'm doing wrong.
Thanks in advance.
verification
Is it possible you create the PojoClass before the EJB gets injected. By that I mean, where do you invoke "someMethod"? Is it in the constructor of the managed bean? A variable simply does not lose its referenced value.
You said you could see the BusinessInterfaceLocalbean isn't null in the Managed bean, can you verify you create the Pojo after that check?
Alternative solutions:
solution 1
You can use the POJO as a stateless bean, I don't see any problems in doing that, unless of course you are trying to use the POJO outside of your EE container, which is, by the looks of it not the case.
Making the POJO stateless would make you able to inject the EJB.
solution 2
OR a JNDI lookup, implemented as followed:
#Stateless(name="myEJB")
public class MyEJB {
public void ejbMethod() {
// business logic
}
}
public class TestEJB {
public static void main() {
MyEJB ejbRef = (MyEJB) new InitialContext().lookup("java:comp/env/myEJB");
ejbRef.ejbMethod();
}
}
With the code you show above, the only way that a NullPointerException could be thrown at the line indicated is if the businessInterface field in the managed bean is null. References cannot mysteriously become null when passed from one object to another, and the PojoClass doesn't do anything which would cause the variable to become null. I suggest you do some debugging or logging to definitively determine the value of the field in the managed bean at the point at which the constructor is called. If it is null, then the problem is with injection into the bean, and is not anything to do with the POJO, and you should fix that.
If the exception being thrown is actually from deeper than the line you show, then this could be a problem with the use of an EJB proxy in the wrong context. As you may know, a reference to an EJB is typically not a reference to the EJB itself, but rather to some sort of proxy which passes method calls on to the EJB; the proxy exists so that the container can step in and do things like start transactions, check authorization, and so on. The proxy may need to call on certain contextual resources to do its work which are available when the EJB is accessed from the managed bean but not, for some non-obvious and twisted reason, from the POJO. The unavailability of those resources could lead to a NullPointerException. Now, i think it is highly unlikely that simply passing a reference from a managed bean to a POJO would get you into that situation; this would only happen if you did something like accessing the managed bean from a different thread. So, it's probably not this!
The problem was caused by me trying to use the businessInterface object in the constructor, while the container injects the ejb only after it's done instantiating the managed bean,
reference to a similar question https://stackoverflow.com/a/6537228/1249304
What I did is that I created a method and annotated it with the #PostConstruct annotation, this way after the container is done with instantiating the managed bean, the annotated method gets called and the businessInterface object is no longer null
#PostContsruct
public void onInit(){
//businessInterface is no longer null
businessInterface.someMethod();
}
Related
I am re-writing my question to hopefully make more sense and get some help.
I have a Controller, 2 ClassRepository, and 2 Service classes (one of which is not annotated with #Service as I get an error when I annotate it, so instead I just use it as a class)
The class not annotated with #Service I simply pass the rateRepository object from the annotated Service to the unannotated service.
If I execute the following code in my annotated service
String zone = rateRepository.getPurolatorZone(request.getShipToZip().substring(0,3));
it works great.
however in my unannotated class where i instantiate the class
InternationalRateService internationalRateService = new InternationalRateService(this.rateRepository);
UPDATE:
I annotated my InternationalRateService class with #Service and decided to autowire the repository itself, and I still get a null pointer exception on the getPurolatorZone method.. I dont understand why it works in one service but not the other when they are set up the same.
Second Update:
as it turns out, im an idiot because i didn't even think to check that it was possible that the string i pass to the repository was what was actually throwing the error. Turns out I never set the local shiptozip variable so. yea im an idiot .
Spring will inject dependencies only in spring managed beans. If you create an object with new then it's not spring managed bean.
In your case, object of InternationalRateService is not managed, as you created by new operator.
So, inject InternationalRateService in your controller, so that all dependencies are injected
Similar questions have been asked, but don't quite address what I'm trying to do. We have an older Seam 2.x-based application with a batch job framework that we are converting to CDI. The job framework uses the Seam Contexts object to initiate a conversation. The job framework also loads a job-specific data holder (basically a Map) that can then be accessed, via the Seam Contexts object, by any service down the chain, including from SLSBs. Some of these services can update the Map, so that job state can change and be detected from record to record.
It looks like in CDI, the job will #Inject a CDI Conversation object, and manually begin/end the conversation. We would also define a new ConversationScoped bean that holds the Map (MapBean). What's not clear to me are two things:
First, the job needs to also #Inject the MapBean so that it can be loaded with job-specific data before the Conversation.begin() method is called. Would the container know to pass this instance to services down the call chain?
Related to that, according to this question Is it possible to #Inject a #RequestScoped bean into a #Stateless EJB? it should be possible to inject a ConservationScoped bean into a SLSB, but it seems a bit magical. If the SLSB is used by a different process (job, UI call, etc), does it get separate instance for each call?
Edits for clarification and a simplified class structure:
MapBean would need to be a ConversationScoped object, containing data for a specific instance/run of a job.
#ConversationScoped
public class MapBean implements Serializable {
private Map<String, Object> data;
// accessors
public Object getData(String key) {
return data.get(key);
}
public void setData(String key, Object value) {
data.put(key, value);
}
}
The job would be ConversationScoped:
#ConversationScoped
public class BatchJob {
#Inject private MapBean mapBean;
#Inject private Conversation conversation;
#Inject private JobProcessingBean jobProcessingBean;
public void runJob() {
try {
conversation.begin();
mapBean.setData("key", "value"); // is this MapBean instance now bound to the conversation?
jobProcessingBean.doWork();
} catch (Exception e) {
// catch something
} finally {
conversation.end();
}
}
}
The job might call a SLSB, and the current conversation-scoped instance of MapBean needs to be available:
#Stateless
public class JobProcessingBean {
#Inject private MapBean mapBean;
public void doWork() {
// when this is called, is "mapBean" the current conversation instance?
Object value = mapBean.getData("key");
}
}
Our job and SLSB framework is quite complex, the SLSB can call numerous other services or locally instantiated business logic classes, and each of these would need access to the conversation-scoped MapBean.
First, the job needs to also #Inject the MapBean so that it can be loaded with job-specific data before the Conversation.begin() method is called. Would the container know to pass this instance to services down the call chain?
Yes, since MapBean is #ConversationScoped it is tied to the call chain for the duration starting from conversation.begin() until conversation.end(). You can think of #ConversationScoped (and #RequestScoped and #SessionScoped) as instances in ThreadLocal - while there exists an instance of them for every thread, each instance is tied to that single thread.
Related to that, according to this question Is it possible to #Inject a #RequestScoped bean into a #Stateless EJB? it should be possible to inject a #ConservationScoped bean into a SLSB, but it seems a bit magical. If the SLSB is used by a different process (job, UI call, etc), does it get separate instance for each call?
It's not as magical as you think if you see that this pattern is the same as the one I explained above. The SLSB indeed gets a separate instance, but not just any instance, the one which belongs to the scope from which the SLSB was called.
In addition to the link you posted, see also this answer.
Iv'e tested a similar code to what you posted and it works as expected - the MapBean is the same one injected throughout the call. Just be careful with 2 things:
BatchJob is also #ConversationScoped but does not implement Serializable, which will not allow the bean to passivate.
data is not initialized, so you will get an NPE in runJob().
Without any code samples, I'll have to do some guessing, so let's see if I got you right.
Would the container know to pass this instance to services down the call chain?
If you mean to use the same instance elsewhere in the call, then this can be easily achieved by making the MapBean an #ApplicationScoped bean (or, alternatively, and EJB #Singleton).
it should be possible to inject a ConservationScoped bean into a SLSB, but it seems a bit magical.
Here I suppose that the reason why it seems magical is that SLSB is in terms of CDI a #Dependent bean. And as you probably know, CDI always creates new instance for dependent bean injection point. E.g. yes, you get a different SLS/Dependent bean instance for each call.
Perhaps some other scope would fit you better here? Like #RequestScoped or #SessionScoped? Hard to tell without more details.
I would like to have a (singleton) bean initialized only after it is actually used (instead of when it is only autowired). Let say I have a Client that I want to initialize only when I want to call any of its methods
#Component
#Lazy(true)
public class Client {
#PostConstruct
void init() {}
void action(){}
}
And I have a Service class that sometimes use it (and maybe sometimes not).
#Service
public class Service {
#Autowired
Client client;
void action1WithClient(){}
void action2WithClient(){}
void actionWithoutClient(){}
}
As it is now, the client is initialized right on the application startup without actually being used due to #Autowired and the fact that Service is eagerly loaded.
Currently only solution that comes to my mind is to do kind of double-checked locking with explicitly asking for Client bean from spring application context when someone tries to use (ie. without #Autowired) or (maybe even better) to do "manual" lazy loading inside the Client.
Question: Is there a "spring" way to postpone the initialization of client until any of its method is actually called (e.g. something like lazy loading is working for hibernate collections)?
I am using Spring 4.
Ah, ok, I should read the javadoc more properly... Solution seems to add anotation "each" autowired dependeny:
#Autowired
#Lazy
Client client;
Anyway - if anybody knows if it is possible to omit such declarations, since it might be error prone - one can easily forget to use #Lazy at each injection point.
Edit:
The easiest way is #ComponentScan(lazyInit = true, basePackages=...).
Previous answer:
There is http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/aop/target/LazyInitTargetSource.html
A bean wrapped with LazyInitTargetSource will not be created until the first actual usage.
How to nicely wrap most of your beans with this wrapper? One possible way is to create your own BeanFactoryPostProcessor...
We are using Spring's TransactionInterceptor to set some database partition information using ThreadLocal whenever a DAO method marked with the #Transactional annotation is executed. We need this to be able to route our queries to different database partitions.
This works fine for most DAO methods:
// this causes the invoke method to set a thread-local with the host name of
// the database server the partition is on
#Transactional
public int deleteAll() throws LocalDataException {
The problem is when we need to reference the DAO proxy object itself inside of the DAO. Typically we have to have the caller pass in the proxy-dao:
public Pager<Foo, Long> getPager(FooDao proxyDao) {
This looks like the following in code which is obviously gross.
fooDao.getPager(fooDao);
The problem is that when we are inside of FooDao, the this is not the proxy DAO that we need.
Is there a better mechanism for a bean to discover that it has a proxy wrapper around it? I've looked at the Spring AOPUtils but I see no way to find the proxy for an object. I don't want isAopProxy(...) for example. I've also read the Spring AOP docs but I can't see a solution there unless I implement my own AOP native code which I was hoping to avoid.
I suspect that I might be able to inject the DAO into itself with a ApplicationContextAware utility bean and a setProxyDao(...) method, but that seems like a hack as well. Any other ideas how I can detect the proxy so I can make use of it from within the bean itself? Thanks for any help.
A hacky solution along the lines of what you have suggested, considering that AspectJ compile time or load time weaving will not work for you:
Create an interface along these lines:
public interface ProxyAware<T> {
void setProxy(T proxy);
}
Let your Dao's implement the ProxyAware implementation, now create a BeanPostProcessor with an Ordered interface to run last, along these lines:
public class ProxyInjectingBeanPostProcessor implements BeanPostProcessor, Ordered {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (AopUtils.isAopProxy((bean))){
try {
Object target = ((Advised)bean).getTargetSource().getTarget();
if (target instanceof ProxyAware){
((ProxyAware) target).setProxy(bean);
}
} catch (Exception e) {
// ignore
}
}
return bean;
}
#Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
It is ugly, but works.
There is a handy static utility AopContext.currentProxy() method provided by Spring which returns a proxy to object from which it was called.
Although using it is considered a bad practice, semantically the same method exists in Java EE as well: SessionContext.getBusinessObject().
I wrote few articles about this utility method and various pitfalls: 1, 2, 3.
Use Spring to inject a bean reference into the bean, even the same bean, just as you would for any other bean reference. No special action required.
The presence of such a variable explicitly acknowledges in the class design that the class expects to be proxied in some manner. This is not necessarily a bad thing, as aop can change behavior that breaks the class contract.
The bean reference would typically be for an interface, and that interface could even be a different one for the self-referenced internal methods.
Keep it simple. That way lies madness. :-)
More importantly, be sure that the semantics make sense. The need to do this may be a code smell that the class is mixing in multiple responsibilities best decomposed into separate beans.
I'm pretty new to the Springframework (as you will guess) and ran into a situation, where help is desperatly needed.
I do hava a J2EE application here, running on tomcat with lots of old code. Anyway, we decided to use the Spring framework for certain tasks. For example we want to store a security object (containing the username and other authentication related properties) as a session scoped bean.
As there is plenty of old code calling the constructor of this "security object" my question is as following:
Will that object be obtained from the session (in any magic way spring is capable of) or will the constructor call generate a completely new object?
I've read something about "autowire mechanism"... would that help me any further?
Thanks for your answers and time!
If you use the new operator, then you are constructed the object yourself and the constructor is called. Spring is not involved when creating an object via new.
If your code creates an instance of the security object by calling the constructor of the class i.e. by calling new Security(), it will get a new instance everytime.
Declare a bean for your security object in your spring applicationContext.xml file. To make the security object session scoped, you'll need to declare its scope as session and make it a proxy:
<bean id="securityObject" class="com.xyz.Security" scope="session">
<aop:scoped-proxy /> <!-- important -->
</bean>
Now, instead of calling new Security(), the client will get the Security object from Spring application context (see line 1):
void someMethod() {
//...
Security securityObject = applicationContext.getBean("securityObject"); // 1
securityObject.doSomething(); // 2
//...
}
Spring will take care of creating instances of Security for each session. The object returned by the call at line 1 is not an actual Security object but instead it is a proxy object. When securityObject.doSomething() is called on line 2, the proxy object will look up the actual object created for that session and delegate the call to it. This will be managed by Spring.
Note that to get the bean at line 2, you will first need a handle to the ApplicationContext object. How you will get that object will depend on where the calling code is. Edit: An easy way to get it uniformly is by implementing the ApplicationContextAware interface.
Note: Instead of getting the bean from application context, you can get it wired by Spring, but that will require you to declare beans for all the clients that need the security object. Since you are modifying an existing application, I think the above approach is better.