CDI (Weld) + DeltaSpike + Converstation - cdi

I'm currently trying to get CDI (Weld to be more precise) to work with JSF 2 and a long running conversation. I'm starting the conversation in #ConversationScoped my backing bean. I'm also creating a #ConversationScoped entity manager. Sadly the entity I'm editing in my backing bean always get's a LazyInitializationException when JSF is trying to write a #ManyToMany mapped field. It seems that the entity get's detached from the entitymanager. In my EntityManagerProducer (see below) the method createEntityManager() is not called bevore the LazyInitializationException is thrown, so I'd assume that the entitymanager is actually session scoped. But from what I understand my code does not generate an extended persistence context (since I could not figure how to do that programmatically).
As far as I know DeltaSpike does not yet offer anything for dealing with long running conversations in JSF. Can anybody suggest a method on how to implement long running conversations with CDI using Weld + DeltaSpike (preferably on a Tomcat with weld-servlet)?
#ApplicationScoped
public class EntityManagerProducer {
#Inject
#PersistenceUnitName("myUnit")
private EntityManagerFactory emf;
#Produces
#ConversationScoped
public EntityManager createEntityManager() {
return emf.createEntityManager();
}
public void closeEm(#Disposes EntityManager em) {
em.close();
}
}

The lazy initialization exception actually does not come from extended persistence contexts or CDI or DeltaSpike. It's simply the same behaviour as described here: selectManyCheckbox LazyInitializationException on process validation
JSF 2 clones the PersistentBag of my entity causing it to get detached. I also worked around by sprinkling lot's of
<f:attribute name="collectionType" value="java.util.ArrayList" />
throughout my JSF code.

Having the EntityManager in a conversation scope is only one side of the equation, what scope are your entities in ?
In order to avoid detaching the entities they should also be conversation scoped.
As a side note :
I found that instead of dealing with entities in a long running scope , it is much easier to reattach them in each request scope.

Related

How to instantiate a backing bean on page load

For a project we are migrating some java applications to WebSphere 8.5. In the process we are trying to get rid of some legacy frameworks. One of them is shale (apache attic). The only component from shale that is used is the view controller to instantiate a request scoped jsf managed beans for every page. Every bean has an init method that is called on page load. I'd like to use #PostConstruct on this method. The only problem I have that the bean gets instantiated when a method on the bean is called. Unfortunately the bean is not always called and the init method does populate data on a session scoped bean. There is a naming convention that links pages and beans so we could use a listener to instantiate the bean based on the request. Another solution might be changing the scope to viewscope (probably to much a hassle on websphere 8.5).
I was wondering if there is something I can do to make the PostConstruct work? And are there other options I'm missing?
edit:
I have a PhaseListener in place that performs the basic functionality. It matches the requested page to the corresponding bean (by naming convention). The following is used to instantiate the bean but it looks a bit ugly.
expressionFactory.createValueExpression(elContext, "#{" + managedBeanName + "}", Object.class)
Is there a more elegant way to do this?
Perhaps you could try using <f:event/> ?
In your view, you could add this to the page.
<f:event type="postAddToView" listener="#{backingBean.myInitMethod()"/>
https://stackoverflow.com/a/14004230/4706826
Gives you info on when the events get executed.
Put a #PostConstruct annotated method in the backing bean. This annotation tells the bean to execute the annotated method every time its constructor is being called.
Example:
#ManagedBean
#ViewScoped
public class MyManagedBean{
#PostConstruct
public void initView() throws Exception{
...initialize page values, execute database queries, etc.
}

#Inject-ed value null in #FacesComponent

I have the impression that CDI is not working with classes that have a #javax.faces.component.FacesComponent. Is this true?
Here's my example, that doesn't work. The MyInjectableClass is used at other points in the code where injection is not a problem, so it must be about the #FacesComponent annotation I think.
The class I want to inject:
#Named
#Stateful
public class MyInjectableClass implements Serializable {
private static final long serialVersionUID = 4556482219775071397L;
}
The component which uses that class;
#FacesComponent(value = "mycomponents.mytag")
public class MyComponent extends UIComponentBase implements Serializable {
private static final long serialVersionUID = -5656806814384095309L;
#Inject
protected MyInjectableClass injectedInstance;
#Override
public void encodeBegin(FacesContext context) throws IOException {
/* injectedInstance is null here */
}
}
Unfortunately, even for JSF 2.2 #FacesComponent, #FacesValidator and #FacesConverter are not valid injection targets (read What's new in JSF 2.2? by Arjan Tijms for more details). As Arjan points out:
It’s likely that those will be taken into consideration for JSF 2.3 though.
What can you do for now? Well, you've got basically two choices:
Handle CDI injection via lookup, or switch to EJB and do the simpler EJB lookup;
Annotate tour class with #Named instead of #FacesComponent, #Inject the component the way you did and register your component in faces-config.xml. As the UI component instance is created via JSF Application#createComponent(), not via CDI you will also need a custom Application implementation as well (exactly like OmniFaces has for those converters/validators).
And, by the way, you've got two issues with what you've got this far: (1) what is meant by #Named #Stateful when the former is from a CDI world and the latter is from EJB world and (2) are you sure you intend to keep state in a faces component that's basically recreated on every request?
#FacesCompnent is managed by JSF and injection is not supported into them.
Passing the value in from the XHTML page via a composite component attribute worked for us.

Injecting one view scoped bean in another view scoped bean causes it to be recreated

I need to use some data saved in a view scoped bean in an other view scoped bean.
#ManagedBean
#ViewScoped
public class Attivita implements Serializable {
//
}
and
#ManagedBean
#ViewScoped
public class Nota implements Serializable {
#ManagedProperty("#{attivita}")
private Attivita attivita;
// Getter and setter.
}
Now, maybe my theory about it is still quite poor, I have noticed that when #{attivita} is injected, the Attivita constructor is invoked and thus creating another instance. Is it the right behaviour? What about if I want to reference the same instance and not create a new one?
This will happen if you're navigating from one to the other view on a postback. A view scoped bean is not tied to a request, but to a view. So when you navigate to a new view, it will get a brand new instance of the view scoped bean. It won't reuse the same bean instance which is associated with a previous view.
I understand that the attivita bean is created on the initial view and reused on postback. I understand that nota bean is associated with the new view where you're navigating to. When injecting attivita in it, it will simply get a new and distinct instance even though there's another instance in the very same request. This is all expected (and admittedly a bit unintuitive) behaviour.
There is no standard JSF solution for this. CDI solves this with #ConversationScoped (the bean lives as long as you explicitly tell it to live) and the CDI extension MyFaces CODI goes a bit further with #ViewAccessScoped (the bean lives as long as the navigated view references it).
You could however workaround this by storing the bean as an attribute in the request scope.
#ManagedBean
#ViewScoped
public class Attivita implements Serializable {
public String submit() {
FacesContext.getCurrentInstance().getExternalContext()
.getRequestMap().put("attivita", this);
return "nota";
}
}
and
#ManagedBean
#ViewScoped
public class Nota implements Serializable {
private Attivita attivita;
#PostConstruct
public void init() {
attivita = (Attivita) FacesContext.getCurrentInstance().getExternalContext()
.getRequestMap().get("attivita");
}
}
Note that this is rather hacky. There may be better solutions depending on the concrete functional requirement. Also note that you should in the nota view reference the desired Attivita bean instance as #{nota.attivita} and not as #{attivita}, because it would give you a new and different instance, for the reasons already explained before.
Your attivita bean is #ViewScoped and that doesn't guarantee that your instance will be hold in session. You need a #SessionScoped bean. However, if you need attivita for some reason to be #ViewScoped, then you can pass params through them in other ways, e.g. using viewParam or using other #SessionScoped bean between them.
Page Params
http://mkblog.exadel.com/2010/07/learning-jsf2-page-params-and-page-actions/
JSF 2 Managed Bean Scopes
http://balusc.blogspot.com.es/2011/09/communication-in-jsf-20.html#ManagedBeanScopes

Java EE 6 and CDI

I'm just starting learning CDI and Java EE 6 but I found this piece of code that I want to fully understand.
#Stateful
#Model
public class MemberRegistration {
#Inject
private EntityManager em;
#Inject
private Event<Member> memberEventSrc;
private Member newMember;
#Produces
#Named
public Member getNewMember() {
return newMember;
}
}
Then... I saw that a jsf page referenced this newMember object like this:
<h:inputText value=#{newMember.name}/>
So my question is : It doesn't matter if I put an #Named annotation inside an variable of any object, it will be accessible anyway from JSF code?
Also, what's the usage of #Produces in this case, and finally is #Stateful preferred over #Stateless in Java EE 6? If that's the case why?
Despite its simplicity this bean sure does a lot of things ;)
Either the #Named (CDI) or #ManagedBean (JSF-native) annotation is required to make a bean known to JSF. However, Java EE has the concept of stereotypes, which are a kind of composite annotations that combine a number of other ones.
In this case #Model is such a stereotype, it combines #Named and #RequestScoped.
#Produces annotates a factory method; a method that knows where to get an instance of some type from. It can be combined with a so-called qualifier annotation, e.g. #Foo, after which you can use that annotation to inject something in some bean. In this case however it's combined with #Named, which makes newMember available to JSF. Instead of creating the bean as would happen when e.g. an #RequestScoped bean is encountered first, under the covers the getNewMember() method will be called when JSF wants an instance. See Dependency Injection in Java EE 6 for more info.
#Stateful is normally not preferred over #Stateless when used standalone. #Stateless beans are pooled and execute one method for a client (typically in a transactional context). Their stateful counterpart is not pooled and without CDI, the caller has to keep track of its life-cycle (by eventually calling an #Remove annotated method). Here, the bean is also assigned a scope (request, via #Model), so the container will take care of that.
The likely reason for using this annotation here is probably to make the bean's methods transactional. Although the fragment as given doesn't show its usage I guess there's a version of this class with more methods that make use of the EntityManager. Transactions will come into play there.
(Note, combining annotations this way gives the Java EE developer lots of power, but it does put several concerns in one bean which is contrary to the mantra that a bean should do one thing and do that well. An alternative is an #Model annotated bean focussing on view concerns only, that's injected with #Stateless beans that encapsulate the business logic instead of an EntityManager.)

Correct way of retrieving another bean instance from context [duplicate]

This question already has answers here:
Get JSF managed bean by name in any Servlet related class
(6 answers)
Closed 2 years ago.
We are using the following code to get the managed bean instance from the context.
FacesUtils.getManagedBean("beanName");
Is it the correct way of doing it?. If multiple users access the same bean what will happen?
How the bean instances are managed?
Since FacesUtils is not part of standard JSF implementation, it's unclear what it is actually doing under the covers.
Regardless, when you're already inside a managed bean, then the preferred way is to inject the other bean as managed property. I'll assume that you're already on JSF 2.0, so here's a JSF 2.0 targeted example.
#ManagedBean
#SessionScoped
public void OtherBean {}
#ManagedBean
#RequestScoped
public void YourBean {
#ManagedProperty("#{otherBean}")
private void OtherBean;
#PostConstruct
public void init() {
otherBean.doSomething(); // OtherBean is now available in any method.
}
public void setOtherBean(OtherBean otherBean) {
this.otherBean = otherBean;
}
// Getter is not necessary.
}
But when you're still on JSF 1.x, then you need to do it by <managed-property> entry in faces-config.xml as explained in this question: Passing data between managed beans.
If you happen to use CDI #Named instead of JSF #ManagedBean, use #Inject instead of #ManagedProperty. For this, a setter method is not required.
See also:
Communication in JSF2
Get JSF managed bean by name in any Servlet related class
Backing beans (#ManagedBean) or CDI Beans (#Named)?
As to your concern
If multiple users access the same bean what will happen? How the bean instances are managed?
They are managed by JSF. If a bean is found, then JSF will just return exactly this bean. If no bean is found, then JSF will just auto-create one and put in the associated scope. JSF won't unnecessarily create multiple beans.

Resources