what to use, managed beans (backing beans) or entity beans? - jsf-2

I see a lot of examples marking beans as entity beans (#Entity) & named beans (CDI), so as to avoid creating 2 classes (managed bean & entity bean) and also to make use of Bean Validation so that validation can be performed on both client & server.
So should I be using a single class or not, are there any issues or should I be having my managed beans or service layer create entity beans using the data from managed beans ?

The #Named or #ManagedBean annotations are typically used to let the bean container (CDI/JSF) create an instance of a bean on demand when referenced by expression language in JSF.
For an #Entity bean, it often doesn't make that much sense to just get an arbitrary new instance. An #Entity is very strongly connected to a persistent identity. Such an entity is therefor requested from the Entity Manager and not from a bean container.
The typical pattern is to have a (slim) backing bean that's named making a call to a service (which is in turn typically #Stateless in Java EE). The service then returns entities.
In some very trivial systems people sometimes do make the service named and thus directly available to EL. However, eventually you often want to let the "backing code" generate faces messages or handle (table) selections, which are all things that should not be the concern of a pure business service.
Another common shortcut is letting the backing bean contain business code directly (e.g. the entity manager that retrieves the entities). This makes the business code hard to re-use, but if the app is trivial and there's no need for re-use you might get away with it.
But letting the entity -be- the backing bean is rare and anti to the common Java EE patterns.
Just note that the backing bean can return the entity directly, so bean-validation can still be used. There is no need whatsoever for the strange 'scatter/gather' pattern that crept up a long time ago (See the second example in this question).
E.g.
#ViewScoped
#ManagedBean
public class BackingBean {
private SomeEntity myEntity; // + getter
#EJB
private Service service;
#PostConstruct
public void init() {
myEntity = service.getSomeEntity();
}
public void save() {
service.save(myEntity);
FacesContext.getCurrentInstance().addMessage(..., ...);
}
}
Assuming SomeEntity in an #Entity annotated bean, bean validation can now be used on a Facelet like:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
>
<h:body>
<h:form>
<h:inputText value="#{backingBean.myEntity.name}" />
<h:commandButton value="Save" action="#{backingBean.save}" />
</h:form>
</h:body>
</html>
If there's a constraint on SomeEntity.name it will be validated.

Related

EL session attribute and managed bean access

I am confused about expression language 2 bean-view communication syntax.First of all.Is it possible to have one more managed bean with same name but different scobes.if it is what about accessing them via expression language
on the other hand;
consider there is an attribute in session called DemoBean and there is a session Scobed managed bean called DemoBean as well,
if I try to access this bean via EL like this #{DemoBean} // refers bean or attribute?
they say #{sessionScobe} is the way to access session attributes but
just #{sessionattributename} is valid ? and when I put an object to the session map is it referanced or copied?
JSF's aim is to manage session attributes itself for you. That means you should forget about keeping/recovering session map attributes manually, because you'll be able to do it using JSF's mechanisms.
When you want to keep some info for the whole application, use #ApplicationScoped annotation into your managed bean. You can do the same for sessions, requests or concrete views, using #SessionScoped, #RequestScoped and #ViewScoped annotations.
So, if you want to store some attribute in session:
#ManagedBean
#SessionScoped
public class SessionScopedBean{
public String sessionAttribute;
//Getter and setter
}
You can recover/change the value of the attribute of the bean using the FacesContext:
FacesContext context = FacesContext.getCurrentInstance();
SessionScopedBean bean = (SessionScopedBean) context.getApplication()
.evaluateExpressionGet(context, "#{sessionScopedBean}", SessionScopedBean.class);
bean.setSessionAttribute("value");
Remember JSF beans are by default named with bean's name with the first character lowercased. And remember also this bean will be null at the first hit if you don't initialize yourself. You can do it in an easy way using a PreRenderViewEvent in the bean you want to initialize and executing it for example in your login page. That ensures the bean will keep alive for the rest of the session.
Finally, that's the way you'll access your session attribute from your view:
#{sessionScopedBean.sessionAttribute}

Setting ManagedBean values in another ManagedBean's method

If I am navigating from page one to page two, When I click on Page one's submit button, control goes to the managed bean written corresponding to page one, I want to fetch some result from database and show them to page two, If I set the Database values into the Managed bean corresponding to page two in the first Managed Bean's action method, then will I be able to get those on page two.
Please suggest if my approach is right?
You can inject let's say bean named Bean1 into Bean2 this way
#ManagedBean
#RequestScoped
public Bean2 {
#ManagedProperty(value="#{bean1}")//this is EL name of your bean
private Bean1 injectedBean;
public void setBean1(Bean1 value) {
injectedBean = value; //provide setter for it
}
#PostConstruct
private void init() {
List<YourData> list = injectedBean.getDBData(); //now you can fetch your list
}
Note that you have to provide setter for injection and scope of the injected bean should be always same or higher then the your beans scope (in this case Bean1 has to be at least RequestScope)
P.S. Also you could have some kind of DAO bean which could do all the database database operations for you (it can be EJB bean or even JSF Managed Bean) and then inject it to every ManagedBean which will require cooperation with your DB.

Passing a JSF2 managed pojo bean into EJB or putting what is required into a transfer object

Currently i am calling EJB 3 Session Beans from JSF 2. However, i am not sure if i should be passing JSF managed beans into EJB?
Assuming that whatever on the form (and thus the backing bean) was everything i needed to persist through the EJB layer, should i clone out all the attributes by hand into a transfer object, or is there a better way of doing this?
The backing bean though POJO is heavily annotated with JSF lifecycle tags (Such as #ManagedBean) and resides in the Web project while the EJBs reside separately in the EJB project.
It sounds like as if you've tight-coupled the model with the controller like as shown in most basic JSF tutorials. You should decouple the model from the controller into its own class. As you're using EJBs, the chance is big that you're also using JPA (how else would EJBs be really useful for persistence?), you can just use the existing JPA #Entity class as model.
E.g.
#Entity
public class Product {
#Id
private Long id;
private String name;
private String description;
private Category category;
// ...
}
with
#ManagedBean
#ViewScoped
public class ProductController {
private Product product;
#EJB
private ProductService service;
public void save() {
service.save(product);
}
// ...
}
which is to be used as
<h:form>
<h:inputText value="#{productController.product.name}" />
<h:inputTextarea value="#{productController.product.description}" />
<h:selectOneMenu value="#{productController.product.category}">
<f:selectItems value="#{applicationData.categories}" />
</h:selectOneMenu>
<h:commandButton value="Save" action="#{productController.save}" />
</h:form>
I was trying to do the same with CDI and the main diffrence (excluding using #Named instead of #ManagedBean) was that I had to initialize my transport object in the Controller class.
So instead of:
private Product product;
I had to use:
private Product product = new Product();
Maybe it will help someone :)

Question about multi-threading and EntityManager

I have been developing my web-app using JPA 2.0 implementation EclipseLink 2.2.0. I finally got around to running multi-threaded code and I got this exception:
java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager.
The objects that have all the javax.persistence calls in my application are defined as application scoped, like this:
#Model
#ApplicationScoped
public class LocationControl implements Serializable {
#PersistenceContext private EntityManager em;
#Resource private UserTransaction utx;
// etc
And of course all the managed beans (usually RequestScoped or ConversationScoped) that want to access the data base do so like this:
#Inject private LocationControl lc;
So my question is this: Did I get that Exception through the use of #ApplicationScoped DAO? I had thought that it would be more efficient that way, since the container would not have to be continually re-creating this object on every request if it did not have a scope, and the DAO has no state of its own. However if the EntityManager and UserTransaction object have to be separate instances for each user, then that would be a problem.
Alternatively, I could use syncrhonized on the DAO methods, but I think that would cause thread lockups in the container (GlassFish).
Any advice appreciated.
#Model annotation was originally created to annotate request scoped beans, here is how it's defined:
#Named
#RequestScoped
#Stereotype
#Target({TYPE, METHOD, FIELD})
#Retention(RUNTIME)
public #interface Model {}
You can of course override '#RequestScoped' with another annotation but '#ApplicationScoped' it's not a good choice as everyone in the application would modify the state of the same injected EntityManager. I think it would be best to leave it #RequestScoped in most cases, sometimes, for example for a login/logout data bean '#SessionScoped' could be an option but I cannot see a scenario for '#ApplicationScoped' dao.
If you don't want to use #Model at all and you use full Java EE container, then the stateless EJB ,as BalusC said, would be a great option for Dao too.

JSF 2.0 pass data between beans (or pages?)

I'm working with JSF 2.0
I have a form in my admin section where I am going to select some users in a list.
The form (selectusers.xhtml) is adding these users to a list in a bean (SelectUsers.java).
After I have selected some user(s), I will pass the list of the user(s) from SelectUsers.java to another bean (AddAddressBean.java) and continue add information in another form (addadress.xhtml) which set other properties related to AddAddressBean for each user.
I do not know how to implement it. I would like that AddAddressBean.java shall be independent (so I can use it together with other beans), so I prefer that AddAddressBean.java shall not know about other beans.
Can you please help me? =)
B.R Carl
Several quick things come to mind :
Perhaps you could have a single bean only for those related pages, using #SessionScoped or the shorter CDI's #ConversationScope, or and this is the best of the three, the DeltaSpike #ViewAccessScoped
When clicking the button on page 1 where it'll take you to page 2, in the 1st bean, you can make use of Flash object to store objects you want to pass, and in the second bean's #PostConstruct method, you could get all the objects from the Flash object
If you dont mind using session scope, you can still have 2 beans, and one bean can refer to another bean using the jsf way(#ManagedProperty), or the Java EE inject way(#Inject) or the spring way if you use spring (#Autowired)
This how i implemented (used ConversationScoped as #bertie said ).
bean 1:
#Named("conversationBean1")
#ConversationScoped
public class ConversationBean1 implements Serializable {
//---start conversation----
}
bean 2:
#Named("conversationBean2")
#ConversationScoped
public class ConversationBean2 implements Serializable
{
#Inject
private ConversationBean1 conversationBean1;
}

Resources