Injecting EJB in struts2 action? - dependency-injection

Am using struts2 , EJB 3.0 ...
My requirement is to call the EJB layer from struts2 action class .
I hope there are two ways in achieving this :
1.Using #EJB annotation in Action class
2.Using JNDI look up
I tried both ,
but the problem with JNDI lookup is , eventhough am using correct naming , am getting NameNotFoundException . So the ultimately , my team moved to other method which is using #EJB annotation .
But when am using #EJB annotation am getting null out of it , I think its not injected :
am getting the NullPointerException
code :
#EJB(mappedName="BeanLocal/local")
BeanLocal bean ;
Can any one suggest me what i have to do further ...
Also if there is anylink in SOF , please do refer me as i found nothing related to this

You can't use the traditional dependency injection in Struts 2 action classes because actions aren't managed. However there is a way to achieve this by using the CDI plugin or Guice.
You can also use JNDI look up but the syntax depends on your server. Your best option is to check the documentation according to what you have (JBoss 7.1, Glassfish...)

I had this same problem and here is how I solved it.
As Shinosha said, the #EJB annotation will not work since the action classes are managed by the Struts container.
In order to use JNDI lookup, I had to make the bean #Remote and specify a mappedName. Then the code is as follows (it depends on the server your are using, in my case Weblogic):
Context ctx = new InitialContext();
MyBean bean= (MyBean) ctx.lookup("MyBeanMappedName#myapp.MyBean");
The lookup string should be the fully qualified name of the bean.

I wrote following interceptors to solve this issue. Have a look and share any feedback you may have :
http://gauravwrites.blogspot.com/2014/11/ejb-injection-in-struts2-interceptor.html

Related

How to access a local interfaces from one project into another within the same ear project

I have a web project that has FacesValidator, this validator needs to access an EJB service to verify if a record exists. Unfortunately, I cannot inject my enterprise beans since the validator is not a managed-bean, so I'm trying to access it via InitialContext. I've tried different combination from http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html but failed.
What works is this format:
java:global/myProject-ear-1.0.0/myProject/MyService!com.czetsuya.myProject.service.membership.MyService,
My question is can it be simplify? Seems too long.
Thanks,
czetsuya
Look at the server logs. A bit decent EJB container (at least, Glassfish 3 and JBoss 6/7 do), logs all available JNDI names of the EJB during EJB deployment step. Provided that the validator is properly been put in the WAR and the EJB has a #Local interface, then the shortest JNDI name would be the java:app one which should in your case have been java:app/myProject/MyService.
A completely different alternative is to just make the validator a JSF or CDI managed bean instead, so that you can just use the #EJB annotation.
#ManagedBean // Or #Named.
#ApplicationScoped // Provided that the instance doesn't have any state.
public class MyValidator implements Validator {
#EJB
private MyService myService;
// ...
}
and reference it by binding instead of validatorId:
<f:validator binding="#{myValidator}" />
Note that from JSF 2.2 on, you should be able to inject #EJB in a #FacesValidator (and #FacesConverter).
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired

Spring Webflow Serialization error on object holding reference to JPA Data Repository (JSF Integration)

Spring Webflow: 2.3.1
Spring Data: 1.0.2
JSF: 2.1.9
Primefaces: 3.3.1
I'm trying to combine Spring Data JPA Repositories with JSF DataModel, in this case, Primefaces with LazyDataModel. This happens in a WebApp integrating Spring with JSF, using Spring Webflow.
The problem is when i use a JpaRepository inside LazyDataModel that lives in ViewScope of Spring Webflow:
Could not serialize flow execution; make sure all objects stored in
flow or flash scope are serializable
org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshot.(SerializedFlowExecutionSnapshot.java:75)"
Without the JpaRepository inside LazyDataModel, i cannot get the correct page and use the Pagination model of spring data. I already found someone with the same problem, but unfortunately no one answered:
http://forum.springsource.org/showthread.php?116022-Webflow-Serialization-error-on-object-holding-ref-to-JPA-Data-Repository
Thanks for you help in advance
Best regards
JSimas
Already found a solution for this problem!
Whenever you need to add a reference to a Spring Data JPA Repository in an object that will live in your spring webflow context, just to declare the JPA repository as transient! Then you need to add the following annotations in the object that contain the transient reference:
#Configurable - to mark the class to be configured on the fly (this will add some overhead to your application, be careful to use this annotation only when you need)
#Autowired - add this to the transient JPA Repository
So, if you're extending a DataModel JSF base class, and you want to add some JPA repository, here is an example:
#Configurable
public class XptoLazyDataModel extends LazyDataModel<Xpto> {
#Autowired
private transient JpaRepository<Xpto> repository;
(...)
}
And there you go. Hope that this can help someone.
Best regards
It also occurred to me that I should apply the transient keyword to my JPA repository field, as you have. This solved the problem, however, I did not need to use #Configurable or #Autowired.

Why does the #PostConstruct method not get called using BeanManager.getReference() to obtain an instance?

We are currently moving from JSF-ManagedBeans to CDI. Unfortunately we have made excessive use of the EL-Resolver in the past in order to gain static access to session scoped beans managed by JSF.
Since CDI dependency injection is not available everywhere I rewrote the existing static lookup to make use of the BeanManager (Using SEAM-Solder extending BeanManagerAware).
Iterator<Bean<?>> iterator = beans.iterator();
Bean<T> bean = (Bean<T>) iterator.next(); // possible NPE, I know :)
CreationalContext<T> creationalContext = beanManager.createCreationalContext(bean);
T contextual = (T) beanManager.getReference(bean, type, creationalContext);
return contextual;
The code works and returns a container managed instance of the desired bean. BUT: the methods annotated with #PostConstruct do not get called using getReference(). Perhaps you guys know how to do it. Couldn't find anything googling the issue :-/
Best regards!
You should be using Application#evaluateExpressionGet() for this. Not only for CDI beans, but actually also for JSF beans you previously had.
FacesContext context = FacesContext.getCurrentInstance();
Bean bean = (Bean) context.getApplication().evaluateExpressionGet(context, "#{beanName}", Bean.class);
// ...
Much cleaner, however, is to just use CDI's #Inject or JSF's #ManagedProperty instead.
See also:
Get JSF managed bean by name in any Servlet related class

Castle windsor property injection

Im a windsor noob and im having some problems getting dependency injection to work. im using a asp.net web application.
I have done the following
public interface IHandler{
...
}
public class Handler : IHandler{
...
}
then i try to register the code in global.asax application_start
container.Register(Component
.For(typeof(IHandler))
.ImplementedBy(typeof(Handler))
.Named("handler"));
When i want to use the Handler i create a property
public IHandler handler{get;set;}
but when i try to use it, it is null? why? am i missing someting?
Best regards
UPDATE
The only thing i doto register/resolve is the following:
container.Register(Component
.For(typeof(IHandler))
.ImplementedBy(typeof(Handler))
.Named("handler"));
and:
container.Resolve<IHandler>();
Do i need to do something else, Does it work to run this att application start?
UPDATE 2
Can the problem ocour because im trying to dependency inject on an ascx controll?
Make sure the component that has the IHandler property is also registered (and resolved) in Windsor.
You said this is for an ASP.NET application. The default lifestyle of Windsor components is singleton. Are you sure you want this component shared like that? You may want a transient or per-web-request lifestyle for this component.
Try removing the name from the registration, like this:
container.Register(Component
.For(typeof(IHandler))
.ImplementedBy(typeof(Handler)));
Alternatively, if you must name the component, you can use ServiceOverrides for the consuming class:
container.Register(Component
.For<SomeConsuer>()
.ServiceOverrides(new { handler = "handler" }));
If you are going to be registering several interfaces/services, then I recommend registering by convention (this is recommended in the docs). Consider this:
container.Register(
AllTypes.FromAssemblyNamed("Assembly")
.Where(Component.IsInNamespace("Assembly.Namespace"))
.WithService.DefaultInterface()
.Configure(c => c.LifeStyle.Transient));
This method performs matching based on type name and interface's name. More info Registering Components By Convention

Injecting entity manager into managed bean

It is possible to inject entity manager (or its factory) into jsf managed bean using #PersistenceContext (or #PersistenceUnit)?
I Tried it but nothing, I obtain a NullPointerException.
Yes it is possible. This is the syntax.
#PersistenceContext
EntityManager em;
You need to have a persistence.xml in your project. Btw: I'm running Glassfish 3.
After this you can then use methods like em.createNamedQuery.
Also remember the injection takes place after the constructor so if your trying to do database functions in the constructor this will not work. You will have to add the #PostConstruct annotation to a method. This is probably the problem your having.

Resources