• Post Reply Bookmark Topic Watch Topic
  • New Topic

JSF request scoped action beans

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

If I have the next request scoped JSF bean for example:




1.In struts for example the Action classes are singletons and I think is the way it has to be because they contain business logic and is the same logic for every user but in JSF because of you mix properties from a form and methods with business logic, these beans have to be request scoped like the above one but is very wierd that a bean which contains business logic(saveUser()....) be request scoped;I dont see it effective, is like creating a new servlet each time you want to save a user but I think is the way JSF works, right?

2 To avoid the mixing of form properties in a bean with business logic, some people say to have the form beans request scoped and actions beans session scoped.
- Is this right?
- How then can you get the request form bean in the action bean?
- The scopes in JSF are request, session and view so you cannot create singleton action beans, the best you can get is a session action bean, right?. Once again I dont see the point of creating action beans with session scoped,they should be application scoped if it existed

Thanks
 
K. Tsang
Bartender
Posts: 3610
16
Firefox Browser Java Mac OS X
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hmm good questions.

In JSF there is that FacesServlet class which is the controller. The managed beans you write are the models. The actions and business logic go in the model.

Depending on your preference, the actions (methods triggered from view) can be separated from business logic (eg CRUD methods). Under this scenario, the CRUD method class isn't really a managed bean but regular POJO.

About the scopes, there is application scope in (discussed here

Setting the correct scope of those managed beans depends on the purpose and the bean life cycle. If you expect the user to only use BeanA for this jsf view only then give it view scope. If the data is only the particular request, give it request scope. You get the idea.
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok,

So there is an application scope. My idea would be to have the next bean or model bean which would have the CRUD methods of entity User like the next one. This would be a managed application scoped bean:







1. This would be a good design?
2. How can I do in order the UserBean class knows about the UserForm bean? Using FacesContext.getCurrentInstance....... or is bad design?
3. In order to use form beans, why instead of creating new beans not use the hibernate java beans if we were using hibernate, right?

Thanks

 
Tim Holloway
Bartender
Posts: 18417
58
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
JSF is a lot different than Struts. Some of the JSF designers were Struts designers who didn't like certain things about Struts and JSF is the result.

Struts is based on the idea of flowing continuously from one URL to another. JSF is based on the idea of displaying a form and continuing to work with that form until the user gets all the data in the form correct. It can then (and only then) post the form data into the backing bean and invoke the action method.

The mechanism that does this is called "postback" and it is the reason that Request scope is almost 100% useless in JSF.

Request scope objects are created and destroyed on each URL request. JSF requires longer-term existence for most of its objects. In JSF1, that meant Session scope. In JSF2, View scope was added, which is basically a Session scope that automatically deletes itself when you navigate to a new View, so you won't have a lot of dead session objects littering your app. Not quite the same as Request scope, but close enough.

JSF is also based on an architectural concept known as Inversion of Control (IoC). IoC means that JSF apps aren't supposed to "go out and get things", they are supposed to have things injected into them. This is also the basis for the Spring Framework, which is one reason why it's common to combine the 2 technologies in a JSF-based webapp.

So here are some ground rules:

1. Forget Request Scope. It will only cause trouble.
2. JSF is based on POJO IoC. The more JSF-specific code your JSF webapp contains, the more likely it is that you are doing it wrong. Many JSF backing beans contain no javax.faces objects other than the datamodel classes. Some don't even need those. Struts, by comparison, required that its form and action classes be extensions/implementations of Struts base classes.
3. JSF backing beans are not Controllers in the MVC architecture. In JSF, the Controllers are the FacesServlet and the View tags and are pre-supplied for you . You only need to code View Template and Model (this is one of the things that Struts wasn't good about).
4. The JSF Model data is a UI model. While you can (and often will) connect your "real" Model (which may include ORM persistence Model objects) into JSF Models, it's often the case that the JSF Model is just a façade for the real data. The primary purpose of the JSF Model is to facilitate operation of the MVC mechanism. Hence such things as the javax.faces.DataModel decorator class that can take a plain array or ordered collection and wrap it with the necessary information for proper cursoring through the View.

One thing that confuses people is that JSF backing beans often contain both data (properties) and logic (action methods and listeners) in the same bean. JSF is a nearly 100% pure implementation of the Model/View/Controller architecture, but MVC itself is strictly concerned with using Controllers to keep the Models and Views in sync with each other. In the real world, we need to do something with that Model data, and that's what the Action methods are for. To provide (or invoke) business logic, which is something external to MVC. It is a bit confusing that these methods are typically bundled into the same bean as the model, but one of the key design features of JSF was the reduction of the number of classes required to do useful work.
 
Dieter Quickfend
Bartender
Posts: 543
4
Java Netbeans IDE Redhat
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You have to forget about struts and request/session data. You have to consider that, even though servlets were stateless, they involved just as much session-based state as JSF does. With JSF 2.x, you can use conversation state to optimize session management, which means you don't keep objects in the session longer than necessary, and if your processes are well-defined, you should have less data in the session as before. A few pojo's per user is not a big issue, you should really worry about keeping large DB-resultsets in the session. And this mostly for applications with high usage.

JSF is designed to do away with the request/session model and be more concerned with what your view needs at a given time.

If you're using JSF, you should worry more about defining your stateful conversations and less worried httpSession size. JSF was built so you don't have to deal with that anymore.

It was also built to prevent all the issues and workarounds and boilerplate code associated with mandatory stateless application design. State isn't a bad thing. As long as your scoping is well-designed, you'll be fine.
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, thanks a lot. A few more questions:


1. So normally the backed beans will be session scoped and doesnt matter how many users the application has, right?

2 The properties in these backed beans then will be session scoped but, there is not danger these to be session scoped because of multiple threads?

2. in order not having two classes, one "form bean" and other "action bean" like struts does, jsf mixes both, right?

3 Why JSF stores the values from a form in UIComponents and in the properties of backed beans? Why not only in backed beans?

4. When in the cycle of JSF, there is a validation error, when JSF renders the view and finds something like this: "<h:inputText required="true" value="#{userBean.name}" , where JSF gets the value of "#{userBean.name}"?, from UIComponents or backed beans?. I think from UIComponents, right?

Thanks

 
Tim Holloway
Bartender
Posts: 18417
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jorge Martinez wrote:Ok, thanks a lot. A few more questions:


1. So normally the backed beans will be session scoped and doesnt matter how many users the application has, right?


It matters in that each user has a session and the beans are not shared between sessions (that's what application scope is for), so the more users, the more sessions and thus more beans. As long as you have resources to hold the beans, it doesn't matter, though.

Jorge Martinez wrote:
2 The properties in these backed beans then will be session scoped but, there is not danger these to be session scoped because of multiple threads?


Yes, there is danger, but normally users won't be hitting the beans with multiple threads. It can happen if, for example, the bean processing takes a long time and the user double-clicks the submit button. Generally it's not something you need to worry about, although for a shopping cart checkout, I'd take extra care so as to avoid duplicating an order/bill.

Jorge Martinez wrote:
2. in order not having two classes, one "form bean" and other "action bean" like struts does, jsf mixes both, right?


Essentially true. Except that in JSF, the data is guaranteed validated before the action can fire. In Struts you had to do your own validating.

Jorge Martinez wrote:
3 Why JSF stores the values from a form in UIComponents and in the properties of backed beans? Why not only in backed beans?


Don't mess around with UIComponent internals until you really know what you are doing. Remember Rule #2 from my list, which I normally actually list as JSF Rule #1. The backing beans are the Model in MVC. The UIComponent tree is simply the working storage used to marshal/unmarshall data. It holds potentially invalid data coming in and it's used by the renderer for data going out, but the valid, authoritative data is in the Model (backing bean) itself.

Jorge Martinez wrote:
4. When in the cycle of JSF, there is a validation error, when JSF renders the view and finds something like this: "<h:inputText required="true" value="#{userBean.name}" , where JSF gets the value of "#{userBean.name}"?, from UIComponents or backed beans?. I think from UIComponents, right?


When JSF first renders the View, it renders the "name" property of userBean. If validation fails, the invalid value is retained in the View. If validation succeeds, the (valid) value is posted by JSF to the backing bean. From the application logic's point of view, invalid form submits don't exist, only valid forms. So what's going on in the Component tree is (or should be!) of no concern to application logic. Which is me basically restating what I just said for #3.

Jorge Martinez wrote:
Thanks


¡De nada! It's what we're here for!
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hy,

First of all, really thanks. You are being very helpful:

So, my conclusions of the advantages of using JSF would be(please correct me and add others if you consider it):

1. The view is based in UIComponents like swing so this is helpful, right, I mean, with tags based in components you can render HTML.
2. Because of the UIComponents state is saved in session per user, you can customize the view for each user if you needed to; like hiding or not render a button for example and all this with java code!!
3. Validators and converters prepared to use. I dont really consider it a advantage because with the JSR 303 specification, you already have bean validation frameworks like hibernate validator
4. Views based in events like java swing
5. The application scope, when would it be useful to use then?
6. You dont extend any class from others so are independent classes


Disadvantages:(please correct me and add others if you consider it)
1. You dont attach the validators to the backed beans, for example, with annotations. I think the validators should be attached to the backed beans and not to the UIComponents
2. The number of model backed beans are created is proportional to the number of users


Thanks

 
Dieter Quickfend
Bartender
Posts: 543
4
Java Netbeans IDE Redhat
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jorge Martinez wrote:
Disadvantages:(please correct me and add others if you consider it)
1. You dont attach the validators to the backed beans, for example, with annotations. I think the validators should be attached to the backed beans and not to the UIComponents

In fact, nothing is stopping you from adding validation to your backed beans. You can add client side validation and server side validation wherever/whenever you want. For me the best method of validation is actually validating your domain model using annotations. Because altogether, it's your domain model that has to know what can go in or not. You can also validate when submitting your data to a business transaction and you have specifications for what must come in. You can validate that. If you have sufficient requirements.

2. The number of model backed beans are created is proportional to the number of users

That is true, if your applications is session-scoped. In a conversation-scoped application, all conversation state is proportional to the amount of business processes started. The two can, however (and normally are), be mixed and matched between what should be in session scope (for example user details) and conversation scoped (for example, travel booking).


It's also maybe a good idea to say that, if you're using conversation scoped backing beans, clicking the submit button means you've finished your business process and thus your conversation scoped state is sent and removed. This means that when the user clicks the submit button again, an exception will be thrown and there can be no double submit. Your backing bean will throw an exception and the corresponding error message will be shown to the client.

This is an example of the inherent benefit of correct scoping. Before, using session scope or client-side state, there were only workarounds, which are unsafe. if you disable your button on click, a malicious user can still write a script that calls this method again and again to overload your application. With conversation state, your data is no longer there, and the container will throw an exception instead of calling your submit button again. And you don't have to do anything for this behavior.

 
Tim Holloway
Bartender
Posts: 18417
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1. Rather than UIComponents (a JSF-specific class), say, rather UI components (an abstract term). JSF is very big on abstraction. Repeating myself, you generally shouldn't be working with JSF's internals directly.

2. Well, that's true, but beyond that, MVC specifically was designed with the idea that there need not be a 1-to-1 correspondence between Models and Views. The same Model (raw data) can, for example, be displayed as both a table and a graph on the same webpage. Conversely, a JSF form might manage data from more than one backing bean (for example, userNameBean and userAddressBean).

3. The JSF validators provide validation at the front line of the UI. Until recently, they were basically the only validation option available, although JSR 303 changed that. They still provide the ability to fine-tune validation (including message text) at the UI, and allow validation of objects that might not have JSR-303 support. Converters are a different matter. JSF at the server level is working with binary objects. The client has to work with text-only HTML. The converters, both implicit, explicit, and user-written handle the process of marshalling and unmarshalling text.

4. Only up to a point. Swing doesn't have to deal with the form-based batch-style processing imposed by HTML. Some of the same effect can be achieved in JSF2 via AJAX, but the Swing event set is richer than what JSF is permitted.

5. Application scope, as its name implies is anything shared by all users in the web application. I typically use it for menu selection lists and similar things.

6. They're POJO objects, as opposed to framework-specific objects. You can certainly use inheritance and interfaces to as part of the design of a JSF managed bean if you want to. But it can be any base class and any interface(s), not merely ones defined for JSF. This is the single biggest variation from Struts.

On disadvantages, validators can be located on backing beans, courtesy of JSR-303. But you can also make them dependent on the View definition.

DIsadvantage #2 is true of all session-scoped objects, be they JSF, Struts, or even plain JSP/servlet. Backing beans hold state, however. You could only hold state in the Struts actions if you were careful to allow for concurrency, and the form objects were proportional to the number of users being actively serviced. True, they didn't persist past the request, but that meant that neither did their state.

 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, really thanks for your support. Just these other considerations:

1) Because of you mix in backed beans the properties of a form and actionMethods, I should say because of the properties, this bean has to be session scoped and not application scoped because if it was application scoped it wouldnt be thread safe because of the properties, right?

2) I have seen many examples where the backed beans are request scoped and not session. In terms of memory for the server, to be request scoped is a good thing and better than session and this is why some examples do it, right?

3) Are there some known problems for making the backing beans request scoped?

4) In this URL http://stackoverflow.com/questions/746047/jsf-backing-bean-structure-best-practices, its said the next:

"Controller Managed-Bean: Normally request scope. This type of managed-bean participates in the "Controller" concern of the MVC design pattern. The purpose of a controller bean is to execute some kind of business logic and return a navigation outcome to the JSF navigation-handler. JSF controller-beans typically have JSF action methods (and not actionListener methods)".

- why "Normally request scope"?, If it just has actionMethods, why not application scoped?


Thanks
 
Tim Holloway
Bartender
Posts: 18417
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Normally yes, you would want the backing beans to be session scoped, because otherwise multiple users would be setting/getting property information and this would cause conflicts. There are thread safety issues on application scope, but that's not the major problem. Application scope properties are subject to the same limitations as class-level properties in general Java code. If you have 1 "username" property and 8 users, only one of them can realistically store their name there unless you simply lock out all other users while that one user runs through the workflow.

Session scope objects are also subject to threading concerns, since an impatient client can send multiple requests at the same time (for example, by double-clicking a submit). But in practice, this isn't as much of a problem, since it's only 1 user. The main place you want to take care is if you're committing an order/transferring money and you don't want to get multiple orders/bills for the client.

You may have seen many request scoped backing beans, but chances are that you saw them in places where people were asking why they didn't work. The utility of request scope in JSF is very limited in JSF, because of its unique postback mechanism. In particular, any backing bean that contains JSF SelectItem or DataModel objects will have major problems, because the request scope mechanism destroys vital JSF context information and replaces it with uninitialized values on each request. That also extends to backing beans using implicit DataModel objects, which means any backing bean for any sort of dataTable UI element, whether you explicitly construct the DataModel yourself or you use an ordered collection (Array, List, etc.) and JSF constructs its DataModel automatically.

The StackOverflow posting in question is nonsense. Backing beans are not Controllers. They are Models. Action methods (and action listeners) are not Controller methods, they are business methods.

True Controller methods do nothing but transfer data between Model and View to ensure that their values match. They don't do anything else. In JSF, this function is done by the FacesServlet and the Controller methods that are pre-supplied as part of the JSF tags. You don't code any Controller logic.

What they are calling "Controller logic" is more accurately speaking, a mix of business logic and navigation logic. ActionListeners and action methods are fundamentally the same thing, and either or both may be used within a given backing bean, but in practice, I recommend using action methods, since they are POJO code, whereas ActionListeners are JSF-specific. POJO code is easier to test offline, makes the bean code easier to re-use, and less likely to be adversely impacted by future changes (if any) in JSF's basic architecture.

While it sounds attractive to put the "Controller logic" in application scoped beans and keep the UI Model stuff in separate session/view/request scoped beans, in practice, there's a problem. JSF is based on the Inversion of Control paradigm, where you don't go looking for data, data is presented to you. But IoC only works if the target bean has an equal or more transitory scope than the injected bean. In other words, you can inject session and/or application scope objects into a request scope bean, but you cannot inject session scoped objects into an application scope bean. That's because A) the more transient object will likely go out of scope without notifying the target and B) in the case of 199 users (sessions) and 1 application-scope logic bean, how do you manage connecting the logic to the proper session short of a massive synchronization bottleneck?

So, while mixing the UI Model and the Business/navigation logic in the same bean may be æsthetically annoying, it provides certain advantages.

1. There's no need for external injection of the related model data, since it's directly accessible within the bean.
2. There are no scope issues.
3. Instead of coding 2 classes, you code 1.

Granted, a 1-class-does-all approach is somewhat offensive, but since the designers of JSF were coming from a Struts background where a whole raft of classes were required for each form, they had a strong desire to keep the class count down.
 
Jorge Martinez
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Once again,really helpful!

I dont really understand when we post a form and later we go back to that page with the back button of the browser and we see the values we sent, this is because:

a) The cache of the browser
b)The values that were filled in the form bean inside of the back bean was session scoped and not request scoped
c) No matter if the values are filled in a request or session form bean because these values are taken in this case from the state of the UIComponents


Other bad thing to have a session scoped bean and a request scoped form bean inside it is that, if for example, I post a form, and later I want to go back to that form with the values I sent, because of the values were attached to a request scoped bean, I wont see these values in the form, right? or it has nothing to do with it?

Thanks





 
Tim Holloway
Bartender
Posts: 18417
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The "Back" button is an eternal problem. There are basically 2 things that could happen:

1. The browser can display the previous value of the page from its cache, thus displaying exactly what was in the forms as the client saw them. No communication with the server is done.

2. The request can be re-issued to the server, causing JSF to render the page using the current backing bean values.

Note that in neither case are the JSF UIComponents directly involved. It's likely that the browser will pop up a dialog informing you that the page requires a POST request, if case #2 applies.

Normally in my webapps, the forms are presented under secure transport (SSL), and in the case of the Tomcat webapp server, that means that there will be no local cache, because Tomcat adds a no-cache header to all responses for security reasons. I actually had to add special support just to get caching on my images and CSS, in fact.

You cannot inject a request scope bean into a session scope bean. JSF will reject it, because the request scope has a shorter lifespan (is more transient) than session scope. You can inject a session scope bean into a request scope bean, and occasionally I do it, but I do it knowing what my limitations are for request scope.

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

I know I dont have to think in terms of UIComponents but the next case:

- A user request a xhtml page with a form
- The user fills the information and sends a non post ajax request
- The validations fails in the server so the page is presented to the user again with the same values

1.If the backing beans properties have not been filled because of the validation failed, where is JSF taking the values which I sent? What I mean is, JSF in the cases where the validations fails, has to store the information in somewhere else

2.When you say "You cannot inject a request scope bean into a session scope bean. JSF will reject it, because the request scope has a shorter lifespan (is more transient) than session scope". You mean JSF will throw an exception when the application starts?

3.If I say to inject something in a bean, I mean, a dependency, and this dependency dissapears because it has a shorter life(request scope), it has non sense in JSF and in any framework, I mean, a class depends on something and this dependency dissapears would be a bad design in any framework, right?

Thanks
 
Tim Holloway
Bartender
Posts: 18417
58
Android Eclipse IDE Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tecnically, you don't request an xthml page. You make a URL request, and if its URL maps to the FacesServlet, the FacesServlet will de-construct the URL to produce the internal resource location of the corresponding xhtml, then it will use that as a View Template for the purposes of constructing the UIComponent tree. Which gets passed through the JSF lifecycle down to the renderer, which outputs an HTML web page.

You never send a non-POST form request in JSF. That's why they call it "postback". It's ALWAYS a POST.

If validations fail, various steps in the JSF lifecycle are short-circuited, including the value change listeners, data posting and action processor. The UIComponent tree is the internal "working storage" for JSF processing, and it will be used to re-render the failing page, including whatever validation messages were produced. The actual UIComponent tree may be destroyed once the response has been committed, but context is saved so that it can be reconstructed the next time the request comes in. There's an option in JSF as to whether that context is kept on the client side or the server side.

The incoming data values are temporarily stored in the UIComponent tree, but you shouldn't be working with them. The only authoritative data is that which is in the backing bean. If all validations pass, JSF will post the updated working values to the backing bean.

JSF works on a just-in-time basis, so an invalid scope injection will not fail until you actually request the invalid scope object. And yes, I think it's going to throw a FacesException. I don't remember for certain.

In java, nothing truly disappears until all references to the object have been deleted and the object can then be garbage-collected. But if you hold onto an object after it has gone out of scope, results may be unpredictable. Fortunately, like I said, JSF won't allow you to define such references to begin with.

A common fault among JSF newbies is that the have code that attempts to cache the FacesContext and use it later. However, the FacesContext exists only as long as the current JSF request/response cycle and is immediately destroyed at the end of that cycle. Attempts to obtain it from non-JSF code will fail (because it doesn't exist except under JSF). Attempts to reference a cached copy one the FacesContext went out of scope will fail in all sorts of unpleasant ways, as the next JSF request will have caused an entirely different FacesContext to be built.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!