Can a managed bean extends a DTO - jsf

I have 2 classes (managed beans) in my business that of type X, the 2 classes merely have the same attributes except for 3 attributes, can i make a DTO contains all the attributes in the 2 beans and let them extends this DTO or i have to group the attributes in the DTO and associate it with the 2 beans so that each bean could set and get its attributes, i want to know the appropriate solution from the point of design, another question is it a correct design for the managed bean and the DTO to have a relation directly.

You could do that but it'd be error-prone, violating the MVC paradigm and simply a bad practice as far as I'm concerned.
Consider and compare two simple cases. First case is a bean extending a DTO and the second case is a bean containing a DTO.
Managed bean that extends a DTO
public class ContactDto {
private String name;
}
public class ContactBean extends ContactDto {
//has name inherited
private boolean renderedAdminPanel;
public void action { }
}
In this case who will be producing managed beans? When will they be instantiated and how? Will your DAO be tightly coupled with ContacyBean? What if you decide to give up using DTOs and use detached entities instead?
All of it increases discrepancies in your architecture and makes it at the very least less manageable.
Now let's consider the alternative approach.
Managed bean that contains a DTO
public class ContactBean {
private ContactDto contactDto;//all fields contained inside
#PostConstruct
public void init() {
//get data from your service based on injected parameter's value and assign it to your DTO
}
private boolean renderedAdminPanel;
public void action { }
}
In this case all logics is crystal clear. Also, you don't need to write 'extras', because all of your properties will be available in EL context with an additional accessor. Your object's lifecycle is predictable and well-formed.
Ultimately, a DTO is a DTO and you wouldn't like to spice it up with additional and possibly secure information, like injected current user, contexts, session variables, etc. to pass that information around. Keep it simple and in its own place.

Related

How to have one instance of Backing Bean per Browser tab?

My environment: Java 7/JSF 2.1/PrimeFaces 6.1.
My goal: to have a certain page of my application instantiated many times, one for each browser tab, each one with a different context.
My problem: everytime I open a second browser tab requesting from the same url, but with different object id, the previous one is destroyed, so only one backing bean instance is kept alive.
How do I know that: In my backing bean I have one method annotated with #PosConstruct and other with #PreDestroy, so I can track the life cicle of the instances.
My backing bean is annotated as follows:
#ViewController
public class MyBackingBeanMB extends AbstractBackingBeanMB {
private static final long serialVersionUID = 1L;
// many fields and methods
}
The #ViewController annotation is provided by the application framework I have to use. Such an annotation is declared as:
#Named
#Controller
#Stereotype
#ViewScoped // For me, this should do the trick, but...
#Target(value={TYPE})
#Retention(value=RUNTIME)
#Inherited
public #interface ViewController {
}
Update 1:
The #Controller annotation is also provided by the framework I use and is declared as:
#InterceptorBinding
#Inherited
#Target({ TYPE, METHOD })
#Retention(RUNTIME)
public #interface Controller {
}
Any ideas of what could be wrong?
TIA.
After some digging in the Internet I found Apache DeltaSpike, which provider a new kind of managed bean scope, WindowScoped.
Managed beans annotated with #WindowScoped` operate just like I wanted, providing me with the exact behaviour I needed and it is absolutely compatible with the framework I have to use.

CDI Bean Scoping during Injection is not working

I want to give on-the-go scope to a pojo bean in CDI during injection.
I created a plain bean and injected the same as #javax.enterprise.context.ApplicationScoped in a #javax.faces.bean.ViewScoped Managed Bean like this:
#Inject
#ApplicationScoped
Pojo pojo;
// POJO Class
Class Pojo {
private String var;
public Pojo() {
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
}
The Pojo bean's populated values could not be restored in a new view bean when I inject using the same syntax.
But it works when I use #ApplicationScoped in the class declaration instead, followed by non-scoped injection, like this:
#ApplicationScoped
Class Pojo {
private String var;
Injection:
#Inject
Pojo pojo;
The former case gets resolved when I make a producer and qualifier but I feel this would be an overhead I should do without. Being new to CDI, I want to ask what I am really missing here.
Scope and Context management are a very powerful feature in CDI. It is also part of the business logic of the components (an #ApplicationScoped bean won't be developed the same way than a #RequestScoped), that's why the scope is link to bean definition.
An injection point is only a place where you consume a bean and not a place where you define it, so there is no way to define the scope of a bean at the injection point at spec level.
Now if you really want to use this feature you could develop a portable extension to add this possibility. But you'll probably have to work on a qualifier system as well since scope is not used in bean resolving process (i.e. 2 beans with the same type in different scope will be in conflict for a given injection point if they don't have specific qualifier).

using more than one managed bean in same jsf page

If I have page, lets say includes two different customers informations, how can I use two different managed beans (which is same java class) in the same page?
As a summary, in the same page I want to hold information of one customer in one bean, another in another bean.
I want to hold information of one customer in one bean, another in
another bean.
Another bean for same purpose is duplication, and If you are thinking it logical. Every page have its page's state (life). when you try #{bean.customer} it will return same value. Because its object is same.
I would suggest to improve your code use another class for the view, layer your application. like
//Base class
public class Customer {
private String id;
/*
*Other fields
*/
//getter Setters
}
#ManagedBean
#RequestScoped
public class PageBackingBean implements Serializable{
List<Customer> customer = new ArrayList<>(); //can Hold more than one customer
public PageBackingBean(){
Customer cus1 = DataBase.loadByCustomerId(id);
customer.add(cus1);
Customer cus2 = DataBase.loadByCustomerId(id);
customer.add(cus2);
}
}

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.

how to avoid model code duplication with JSF and JPA

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.

Resources