how to avoid model code duplication with JSF and JPA - jsf

I'm new to JSF and am wondering if I got things right. Let's say I have a simple CMS that makes it possible to write pages.
First, I define a JPA entity called Page:
#Entity
public class Page {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column
private Long id;
#Column private String title;
#Column private String content;
// getters & setters ...
}
Then I would like in a view to create Page-s. For that, it looks like I need a page bean of some sort. For now I handled things like this:
#Model
public class PageBean {
private Page page = new Page();
public String getTitle() {
return page.getTitle();
}
public void setTitle(String title) {
page.setTitle(title);
}
// rest of properties & getters & setters ...
public void save() {
// persist using EntityManager
}
}
My question is the following one: given that my JPA entity model and the model I want to use in the views are most of the time exactly the same, is there a way of avoiding to have to create a batch of getters & setters in the PageBean?
I read somewhere that you should not use a same bean as JPA entity and JSF model bean (because JSF does repeated calls to getters that may affect JPA), yet I do wonder if there is not a simpler way that would help avoiding this kind of code duplication. Especially when you've got an application with a large model and in many instances do not require anything special in the view beans, it looks like this can get quite cumbersome.

[...] given that my JPA entity model and the model I want to use in the views are most of the time exactly the same, is there a way of avoiding to have to create a batch of getters & setters in the PageBean?
I don't see the point of using a wrapper around an Entity and adding such a layer is indeed duplication. Just use the entity from your JSF page. Yes, this introduce some sort of coupling between the view and the domain but, in general, modifying the database usually means adding or removing fields on the view. In other words, I don't buy the "decoupling" argument and I've written enough extra layers, mapping code, boilerplate code, etc to favor the simple approach when possible.
I read somewhere that you should not use a same bean as JPA entity and JSF model bean (because JSF does repeated calls to getters that may affect JPA)
I'd be interested if you could provide a reference but a wrapper class (delegating calls to the entity) is not going to change anything if there is a problem somewhere.
Just in case, some additional resources:
EclipseLink/Examples/JPA/JSF Tutorial

It's not code duplication. The are no algorithms duplicated. The business logic is still in one place.
What your bean is doing is just connecting the View to the Domain model. This is good, it's part of the MVC pattern.
If you were using your JPA entity as your backing bean, you would be breaking the MVC pattern. For example, if one day instead of displaying a plain String you would need to add a Date to this String because the view requires so (i.e. interface requirements), are you going to write this view logic inside the JPA class? That does not make sense, mixing domain model and view model.
On the other hand, why the view has to know about how the domain is implemented? What if the domain values format change? (For example you save a timestamp String instead a date class in de Database for performance reasons). All you would need to do is just rewrite the method in the backing bean, it would take the timestamp and adapt it to a Date so everything would work as it was before. Just one change outside the JPA class. If you had it in the JPA class you would end up maintaining both logics in just one class (interface logic and domain logic).
What if you want to develop a new view (for example for mobile version)? Are you gonna add even more code to the JPA class? It would be better to keep the JPA as it was and create another Bean (that extends a common bean for both views) for the mobile version.
If after all this, you still want to not to write the getters and setters, you can do
#{myBean.page.title}
all you need is a getPage() inside the backing bean.

Related

Primefaces: <p:dataTable>'s data source change or concurrency operation will cause the inconsistent parameter passing from jsf-el to backing bean [duplicate]

I've a data table as below:
<h:dataTable value="#{bean.items}" var="item">
I'd like to populate it with a collection from the database obtained from a service method so that it is immediately presented when the page is opened during an initial (GET) request. When should I call the service method? And why?
Call it before page is loaded. But how?
Call it during page load. How?
Call it in the getter method. But it is called multiple times.
Something else?
Do it in bean's #PostConstruct method.
#ManagedBean
#RequestScoped
public class Bean {
private List<Item> items;
#EJB
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public List<Item> getItems() {
return items;
}
}
And let the value reference the property (not method!).
<h:dataTable value="#{bean.items}" var="item">
In the #PostConstruct you have the advantage that it's executed after construction and dependency injection. So in case that you're using an EJB to do the DB interaction task, a #PostConstruct would definitely be the right place as injected dependencies would not be available inside a normal constructor yet. Moreover, when using a bean management framework which uses proxies, such as CDI #Named, the constructor may or may not be called the way you expect. It may be called multiple times during inspecting the class, generating the proxy, and/or creating the proxy.
At least do not perform the DB interaction job in the getter, unless it's lazy loading and you really can't do anything else. Namely, it would be invoked during every iteration round. Calling the service method during every iteration round is plain inefficient and may end up in "weird" side effects during presentation and postbacks, such as old values from DB seemingly still sticking around in the model instead of new submitted values.
If you rely on GET request parameters, then use <f:viewParam> and <f:viewAction> instead. See also Creating master-detail pages for entities, how to link them and which bean scope to choose.
If you want to preserve the model (the items property) across postbacks on the same view (e.g. CRUD table/dialog), then make the bean #ViewScoped, else the model won't be in sync with the view when the same model is concurrently edited elsewhere. See also Creating master-detail table and dialog, how to reuse same dialog for create and edit.
If you utilize JPA's #Version feature on the model, then you can catch OptimisticLockException to deal with it and show a message like "The data has been edited by someone else, please refresh/review if the desired changes are as intended". See also Letting the presentation layer (JSF) handle business exceptions from service layer (EJB).
See also:
Why JSF calls getters multiple times
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
JSF Controller, Service and DAO

preRenderView not working during a method call [duplicate]

I've a data table as below:
<h:dataTable value="#{bean.items}" var="item">
I'd like to populate it with a collection from the database obtained from a service method so that it is immediately presented when the page is opened during an initial (GET) request. When should I call the service method? And why?
Call it before page is loaded. But how?
Call it during page load. How?
Call it in the getter method. But it is called multiple times.
Something else?
Do it in bean's #PostConstruct method.
#ManagedBean
#RequestScoped
public class Bean {
private List<Item> items;
#EJB
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public List<Item> getItems() {
return items;
}
}
And let the value reference the property (not method!).
<h:dataTable value="#{bean.items}" var="item">
In the #PostConstruct you have the advantage that it's executed after construction and dependency injection. So in case that you're using an EJB to do the DB interaction task, a #PostConstruct would definitely be the right place as injected dependencies would not be available inside a normal constructor yet. Moreover, when using a bean management framework which uses proxies, such as CDI #Named, the constructor may or may not be called the way you expect. It may be called multiple times during inspecting the class, generating the proxy, and/or creating the proxy.
At least do not perform the DB interaction job in the getter, unless it's lazy loading and you really can't do anything else. Namely, it would be invoked during every iteration round. Calling the service method during every iteration round is plain inefficient and may end up in "weird" side effects during presentation and postbacks, such as old values from DB seemingly still sticking around in the model instead of new submitted values.
If you rely on GET request parameters, then use <f:viewParam> and <f:viewAction> instead. See also Creating master-detail pages for entities, how to link them and which bean scope to choose.
If you want to preserve the model (the items property) across postbacks on the same view (e.g. CRUD table/dialog), then make the bean #ViewScoped, else the model won't be in sync with the view when the same model is concurrently edited elsewhere. See also Creating master-detail table and dialog, how to reuse same dialog for create and edit.
If you utilize JPA's #Version feature on the model, then you can catch OptimisticLockException to deal with it and show a message like "The data has been edited by someone else, please refresh/review if the desired changes are as intended". See also Letting the presentation layer (JSF) handle business exceptions from service layer (EJB).
See also:
Why JSF calls getters multiple times
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
JSF Controller, Service and DAO

JSF 2.1 - getting FacesContext strategy

I am developing webapp where my MVC controller is JSF 2.1. I have several methods that are based on
FacesContext.getCurrentInstance()
I use this to
put/retrieve values from Flash scope
add messages on view
get request params map
examples:
public void addInfoMessage(String title, String description){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO,title, description));
}
and
public void putFlashMessage(String code, String value){
FacesContext.getCurrentInstance().getExternalContext().getFlash().put(code, value);
}
etc.
I'm just wondering where is proper place to put this methods if I use this on every single managed bean? I consider two options:
a) create class "JSFUtils", where all method are public and static
b) create super class "ManagedBean" with no declared scope and no declared #ManagedBean annotation, but with these public methods. Every managed bean should be child of these class so it will have inherited these methods.
An utility class is the recommended approach. Instead of reinventing your own, you can use an existing JSF utility library, such as OmniFaces which has Faces and Messages utility classes for the purpose.
String foo = Faces.getRequestParameter("foo");
Messages.create(summary).detail(detail).add();
Messages.addGlobalInfo(summary); // Without detail.
Faces.setFlashAttribute(key, value);
You can indeed also abstract it away as a "super bean", but this is not reusable and you would keep repeating yourself in every JSF project. Also, a class can extend from only one class. So if your bean happen to need to extend from another super class, then you're lost.
I would recommend a utility class for the purpose simply because you allow the flexibility to extend other useful classes, such as those that have some common logic that you'd like to share across other beans.
Having said that, a JSFUtils class can grow quite cluttered with time with many many methods and can become very unmanageable. It would be better to categorize the util methods and put them in separate static utility classes.

Seam #Name on entity classes?

I've first seen annotating Seam entity classes here
http://www.developer.com/java/ejb/article.php/10931_3715171_5/Introducing-JBossreg-Seam.htm
and for whatever reason I've been doing so ever since:
#Entity
#Table (name= "GADGET")
#Name("gadget")
public class GadgetBean implements Serializable {
private String mDescription = "";
private String mType = "";
...
}
However, I do not use "entity components" like this anywhere in my views. Can anyone explain the use of this and what this gains? Is it a non-practice?
If you are not using any of these entity components in your views, you should remove the #Name annotation.
Seam is great, but seam components come with overhead in the way of interceptors firing every time you access a method in that class. Since you are not accessing these attributes in your view, there is no need to make them into seam components. You are incurring the interceptor overhead every time you use a getter or setter from your entity beans.
Seam-gen, the tool used to create seam projects, can also generate entities that are reverse-engineered from your database tables. By default, the seam-gen entity generator does NOT add the #Name annotation to these classes. That should tell you something!
Hope this helps.

Scalability and Thread Safety of Application Scoped ManagedBean Methods

During testing a weakness was exposed in how our app builds f:selectItems lists, specifically, entering really long names on some of our entities screws page alignment by making really wide selects.
Many of these selectItem lists are duplicated in multiple views and backing beans, so I'd like to consolidate their creation.
We already have an application scoped bean that provides List<SelectItem> for enums, and my initial thought was to place them there.
I have some questions, though. We're using jsf 1.2 (if that matters)
1) My understanding is that application scoped beans are singleton simply because a single instance is instantiated and placed in session context. They are not like EJB3 singletons in that only one thread can access any method, so multiple requests won't block trying to access different methods. Is that correct?
2) I suspect each method would have to be synchronized to prevent multiple threads calling the same method from clobbering each other. Is that the case even if the only class member accessed in the method is a threadsafe stateless #EJB?
Following is an implementation of one of them that would be used in 20 views. The implementations for 10 other entities would be similar. Also, the appropriate converters are registered.
public synchronized List<SelectItem> getAccountSelect(){
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
List<SelectItem> result=new ArrayList<SelectItem>(list.size());
for(Account row : list){
result.add(new SelectItem(row,
StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
return result;
}
Any advice appreciated
If it's really mandatory to do the data loading in a getter instead of in the constructor/postconstruct, then there's definitely no point of making it an application scoped bean. Just make it a request scoped one where you do the data loading job in the constructor/postconstruct.
In the jsf applications I work on we load almost all of our reference data (values for selectOneMenues primarily) in Application scope beans and we set up the values in the Constructor of those beans. The data is then available to other managed beans and views via getters but is globalized and centralized for the application. Since the values are only read via getters there is no need for synchronization.
We then expose the beans as mbeans through jmx with a reload method so that they can be updated as needed. The reload method(s) are synchronized so as to block during the short reloads.
In your example above it seems like you could just return a Collection of selectItems so as long as the values are setup in advance you can use this method and still serve multiple threads just fine:
public List<SelectItem> getAccountSelectItems() {
return this.accountSelectItems;
}
Just add this private member to your bean:
private List<SelectItem> accountSelectItems;
and set it up in the constructor:
public AccountBean() {
List<Account> list = new ArrayList<Account>(pemEJB.list(Account.class));
Collections.sort(list, new AccountByActiveByName());
this.accountSelectItems = new ArrayList<SelectItem>(list.size());
for(Account row : list) {
this.accountSelectItems.add(new SelectItem(row, StringUtil.prefixTruncate(row.getName(), MAX_ACCT_LENGTH, row.isActive())));
}
}
If on the other hand this is data that is constantly changing and needs to be updated you might be better off just loading it per session or per request, though you can reload it periodically in application scope using Quartz or some other timer to keep the data reads from your data source down if real time is not an essential requirement for this data in your app. If you are reloading the data then you will want to synchronize those operations if you're using application scope.

Resources