• Post Reply Bookmark Topic Watch Topic
  • New Topic

Model of backing beans: a separated class or just properties?

 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hy,

Reading a lot and because of your answers about JSF, I tkink I have a clearer idea about how it works but one of the things you mentioned was to have a single pojo with the properties and action methods. As I have seen in some examples like http://www.mkyong.com/jsf2/jsf-2-0-spring-hibernate-integration-example/, a good design is to have the model and the action methods in one just single bean and the model not to be a separated class but a few properties like this:





Some questions:

1. If you are using hibernate or any other ORM like the above example(http://www.mkyong.com/jsf2/jsf-2-0-spring-hibernate-integration-example/), why not to use the hibernate pojo bean directly like it represented the form instead of using properties?:





2. Why is it said that JSF represents the purest MVC? Spring separates the model from the view too and Struts does too. I dont really understand it

Thanks again
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The reason you don't use the hibernate POJO (ORM Model) as your JSF UI Model is because JSF isn't flexible enough to present such things. JSF backing beans are constructed using their-no-argument constructor, then injected with any Managed Properties that may have been defined. There's no place in there to find and retrieve a specific instance of a database row object and make that be the backing bean. However, it is fairly simple to have a JSF backing bean present a hibernate Model object as one of its properties. So while it's slightly more indirect, you can easily use Hibernate POJOs with JSF.

The different between JSF, Spring, and Struts is that JSF is defined entirely in terms of M/V/C, with no missing functionality and no special architectural requirements on behalf of the Model or View (user-defined components).

I haven't studied Spring (specifically Spring MVC) enough to know if the same can be said for it. Struts implements what's known as "Model 2" architecture, which was their attempt to implement MVC, but acknowledges that it isn't a 100% accurate implementation. As I've said elsewhere, several of the designers of Struts were involved with the design of JSF because they didn't thing that Struts could be amended to get a closer implementation.
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hy,

I dont understand when you say " The reason you don't use the hibernate POJO (ORM Model) as your JSF UI Model is because JSF isn't flexible enough to present such things" . You mean the views that are attached to this hibernate bean cant get the values from it because its an hibernate bean but hibernate bean is just a pojo, isnt it?.

What you mean when you say "JSF backing beans are constructed using their-no-argument constructor, then injected with any Managed Properties that may have been defined. There's no place in there to find and retrieve a specific instance of a database row object and make that be the backing bean" is that if I wanted to initializate a backed bean with a hibernate bean and I want to to take this hibernate bean from the ddbb is not possible, but in the constructor in the backed bean I could call a service and get it, I mean is possible but a very wierd design, right?

Thanks
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't literally connect a hibernate POJO to JSF because JSF cannot do the necessary find/fetch for you. A JSF Managed Bean can do that, and we do it all the time, but that doesn't present the Hibernate POJO directly to JSF, it presents it via whatever backing bean contains it. In other words:

Hibernate bean: Person(Fred Smith) cannot be bound by JSF automatically to "#{personBean}".

Managed bean: MyPerson can, however fetch the Person(Fred Smith) Hibernate bean and expose it as a properly, For example, "#{personBean.person}".
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry but I dont know if I understood it, I dont want to connect a jsf view directly to a hibernate pojo bean because as you said is not a managed bean, what I mean is to connect a hibernate bean inside a backed bean, is this possible?

For example:


#{backBean.person.name}
#{backBean.person,surname}

1 Could it be "person" a hibernate bean inside of the backed bean or person has to be a managed bean?

2.You mean to make a hibernate bean a managed bean has no sense so the above example has no sense?

Thanks




 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The "person" property doesn't have to be a managed bean. It can be a hibernate POJO. It often is.

Let's say you want to display a welcome page. I'll assume that somewhere in your backing bean, you determine what person bean you want and you fetch it in to be your "person" property.

Then you can code:


And it will produce a web page that says:

Hello, Fred Smith
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, understood. In the example from this URL page http://www.mkyong.com/jsf2/jsf-2-0-spring-hibernate-integration-example/, he doesnt use the hibernate pojo bean as a property of the backbed bean but a few properties instead of the hibernate bean.

1. Why in the example he doesnt use the hibernate pojo directly intead of using properties? Is the example a better approach?

2. Is not necessary and the people dont make the hibernate pojo a managen bean, right? To use it, in the constructor of the backed bean, you should create an object of the hibernate bean and inject it to the property of the backed bean and thats it, right?

3. So form beans as properties of backed beans, its not needed to make them managed beans, right?


Thanks
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I couldn't tell what you mean by doing a quick read of the article. Usually, I find mkyong useful, but that was a truly horrible example of a dataTable. He didn't use a dataModel, and his model data reference was a method call instead of a value reference. Another thing that's really nasty about it is that he's got the datasource defined within the webapp instead of best-practice use of a server-supplied pool.

A Managed Bean is simply a POJO whose creation (and sometimes destruction) is managed by JSF. Any object can be a Managed Bean, providing it has a no-argument constructor (since that's what JSF will use) and (optionally) properties that can be set as Managed Properties as part of the construction process. JSF backing beans are Managed beans, since JSF has to be able to construct them in case no external constructor (such as a non-JSF servlet instantiating a session or application scope object) has already done so.

Hibernate beans have to be POJO-style as well, since Hibernate uses a no-argument constructor to setup a bean when it reads database row values into it.

The reason that Hibernate beans cannot usually be JSF Managed Beans, however, is that JSF has no ability to invoke Hibernate CRUD or finder methods.

As far as the higher-level implementation stuff goes, I actually do pretty much the same thing that he did, except for using annotations instead of xml files such as the customer.hbm.xml. Plus, I use JPA, not traditional Hibernate.

I call my "CustomerBo" by the name of CustomerService, since I got my original concepts from a different source. And actually, it is really a set of services, not an object that you really want there. My Service level is where the transactions are bounded. They differ from the lower-level DAOs in that they work with sets of related data (working sets) doing business persistence instead of table-level stuff like the DAOs do. And that's essentially what he's doing.

But I repeat:

is an abomination. It should read like so:


The rest of the datatable and backing bean code can remain unchanged, since this is a read-only table display. For a table with clickable rows, you'd want to wrap customerList inside a JSF DataModel so that JSF could track which row the user selected.
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hy,

1. Why "<h:dataTable value="#{customer.getCustomerList()}" var="c" ... " is not right? The other way the method getCustomerList() will be call too so why this is so bad?

2 How would you use a data model for getting the customer list? Why to use DataModel class instead of a List object with customers objects?

3 . But to create the hibernate pojo bean as a property of the backed bean, you would create it in the constructor of the backed bean or you would use this approach: http://www.mkyong.com/jsf2/injecting-managed-beans-in-jsf-2-0/ ? Can you show me with a little code what would be your approach for it?

Thanks
 
Tim Holloway
Bartender
Posts: 18412
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. Because a View Template isn't supposed to be software, it's supposed to be data. And, more importantly, the "value=" attribute isn't a function call, it's a property reference.

Consider this:



See the difference?

The original JSP spec had an expression language (EL) that permitted certain types of read-only substitution using expressions like "${value}". JSF, however, needs true references (read AND write), so they came up with a "reference" notation, which is "#{value}"

Yes, you can code an expression call in this particular case, but it's a special case. Besides, it pollutes the Separation of Concerns concept by putting server-oriented logic in the View. It's also more typing to do "getXXX()" than to simply reference "xxx", for those of us who are lazy.

2. JSF uses POJOs wherever it can. But action methods weren't designed to take arguments, so there had to be some way of determining which row in a table the client had selected for the action when you had a command button or link in the table clicked on. To allow the underlying data to remain POJO, the DataModel wraps it with the necessary context information. So that the action method can tell which row was selected by invoking the DataModel's getRowData() method (or rowIndex, if you prefer). A plain list or array wouldn't have a "getRowData()" method.

It's true that by crude brute force you can forcibly parameterize your View definition to do the same thing without a DataModel as of JSF2, but that's what it is. Crude brute force attempts to make JSF look like "The Way We've Always Done It" instead of leveraging JSF's power to simplify this common task. And JSF is still going to build a DataModel, regardless, but you won't have access to it, so it's at least as much work on the server's part and less power available to the developer when using force.

3. It depends on what you are doing and how you get there. A lot of times I have a CRUD backing bean, which, due to quirks in how JSF is put together may also be responsible for a table view of the object in question.

Most often, I'll be navigating from somewhere else, and in the backing bean of the original page, one of the injected (Managed) properties will be the bean that handles this table and its CRUD functions. As an example, let's say we have a Person edit page and we want to edit that person's Address (which is a 1-to-1 relationship for this example).

In the Person edit page, there will be an "Edit Address" button that invokes the "personBean.doEditAddress" method:



JSFUtils is just a class I made up to hold common JSF functions so that they wouldn't litter my backing beans with a lot of JSF-specific details. Returning "null" means that the current page is re-displayed instead of the "Edit Address" page.

Over in the AddressBean class, the "beginEdit(int addressId)" method is where I ask the database to fetch the address record with ID "addressId" and set the addressBean.address property to the returned Hibernate object instance so that it could then edit the details. If that record cannot be found, this method returns "false".

I almost never do any database work in the constructor, since the actual persistence methods are usually injected and therefore their "set" methods haven't been invoked yet. A @PostConstruct method has the persistence objects injected, but it's generic and only invoked the first time after the bean is constructed. Good enough, perhaps for View scope, but not if addressBean was session scoped, as it would have to be in order to get injected into personBean.

So the general-purpose method beginEdit(int addressId) allows me to re-use this bean over and over. It often will invoke a method named init() that clears any local variables (and is also often invoked by the constructor). A beginAdd() method is similar, except that instead of fetching a Hibernate object, it constructs a new, empty one and sets a flag that tells the "doSave" method I create for my "Save" button to do an "add" instead of an "update".
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!