difference between AjaxCommandButton and HtmlAjaxCommandButton - java

I just have a question about the difference between those two classes :
org.ajax4jsf.taglib.html.jsp.AjaxCommandButton
org.ajax4jsf.component.html.HtmlAjaxCommandButton
I am actually using HtmlAjaxCommandButton to create dynamically Ajax commandbuttons, and it works fine, but when using the other class org.ajax4jsf.taglib.html.jsp.AjaxCommandButton, it seems that it has another purpose! I just want to clear things up!
What is the difference between them? And when do we should use this and not the other?

The one in taglib package is a subclass of UIComponentTag which thus represents the sole JSP tag <a4j:commandButton>. It basically definies all available attributes. The one in component package is a subclass of UIComponent which thus represents the concrete JSF component which is associated with the JSP tag. The JSF component definies the decoding (postback processing) and encoding (HTML rendering) behaviors via the renderer. The JSP tag is basically the "mediator" between the JSF component tree and the JSP file.
When dynamically creating JSF components, you should not be manually creating JSP tags. They are not supposed to end up in the JSF component tree.
Note that Facelets, the successor of JSP, does not require those UIComponentTag classes anymore. They are totally absent in Facelets.

Related

jsf dynamic component via binding called too early [duplicate]

There are lot of materials out there differentiating value attribute and binding attribute in JSF.
I'm interested in how both approaches differ from each other. Given:
public class User {
private String name;
private UICommand link;
// Getters and setters omitted.
}
<h:form>
<h:commandLink binding="#{user.link}" value="#{user.name}" />
</h:form>
It is pretty straight forward what happens when a value attribute is specified. The getter runs to return the name property value of the User bean. The value is printed to HTML output.
But I couldn't understand how binding works. How does the generated HTML maintain a binding with the link property of the User bean?
Below is the relevant part of the generated output after manual beautification and commenting (note that the id j_id_jsp_1847466274_1 was auto-generated and that there are two hidden input widgets).
I'm using Sun's JSF RI, version 1.2.
<form action="/TestJSF/main.jsf" enctype="application/x-www-form-urlencoded"
id="j_id_jsp_1847466274_1" method="post" name="j_id_jsp_1847466274_1">
<input name="j_id_jsp_1847466274_1" type="hidden" value="j_id_jsp_1847466274_1">
Name
<input autocomplete="off" id="javax.faces.ViewState" name="javax.faces.ViewState"
type="hidden" value="-908991273579182886:-7278326187282654551">
</form>
Where is the binding stored here?
How does it work?
When a JSF view (Facelets/JSP file) get built/restored, a JSF component tree will be produced. At that moment, the view build time, all binding attributes are evaluated (along with id attribtues and taghandlers like JSTL). When the JSF component needs to be created before being added to the component tree, JSF will check if the binding attribute returns a precreated component (i.e. non-null) and if so, then use it. If it's not precreated, then JSF will autocreate the component "the usual way" and invoke the setter behind binding attribute with the autocreated component instance as argument.
In effects, it binds a reference of the component instance in the component tree to a scoped variable. This information is in no way visible in the generated HTML representation of the component itself. This information is in no means relevant to the generated HTML output anyway. When the form is submitted and the view is restored, the JSF component tree is just rebuilt from scratch and all binding attributes will just be re-evaluated like described in above paragraph. After the component tree is recreated, JSF will restore the JSF view state into the component tree.
Component instances are request scoped!
Important to know and understand is that the concrete component instances are effectively request scoped. They're newly created on every request and their properties are filled with values from JSF view state during restore view phase. So, if you bind the component to a property of a backing bean, then the backing bean should absolutely not be in a broader scope than the request scope. See also JSF 2.0 specitication chapter 3.1.5:
3.1.5 Component Bindings
...
Component bindings are often used in conjunction with JavaBeans that are dynamically instantiated via the Managed
Bean Creation facility (see Section 5.8.1 “VariableResolver and the Default VariableResolver”). It is strongly
recommend that application developers place managed beans that are pointed at by component binding expressions in
“request” scope. This is because placing it in session or application scope would require thread-safety, since
UIComponent instances depends on running inside of a single thread. There are also potentially negative impacts on
memory management when placing a component binding in “session” scope.
Otherwise, component instances are shared among multiple requests, possibly resulting in "duplicate component ID" errors and "weird" behaviors because validators, converters and listeners declared in the view are re-attached to the existing component instance from previous request(s). The symptoms are clear: they are executed multiple times, one time more with each request within the same scope as the component is been bound to.
And, under heavy load (i.e. when multiple different HTTP requests (threads) access and manipulate the very same component instance at the same time), you may face sooner or later an application crash with e.g. Stuck thread at UIComponent.popComponentFromEL, or Threads stuck at 100% CPU utilization in HashMap during JSF saveState(), or even some "strange" IndexOutOfBoundsException or ConcurrentModificationException coming straight from JSF implementation source code while JSF is busy saving or restoring the view state (i.e. the stack trace indicates saveState() or restoreState() methods and like).
Also, as a single component basically references the rest of the entire component tree via getParent() and getChildren(), when binding a single component to a view or session scoped bean, you're essentially saving the entire JSF component tree in the HTTP session for nothing. This will get really costly in terms of available server memory when you have relatively a lot of components in the view.
Using binding on a bean property is bad practice
Regardless, using binding this way, binding a whole component instance to a bean property, even on a request scoped bean, is in JSF 2.x a rather rare use case and generally not the best practice. It indicates a design smell. You normally declare components in the view side and bind their runtime attributes like value, and perhaps others like styleClass, disabled, rendered, etc, to normal bean properties. Then, you just manipulate exactly that bean property you want instead of grabbing the whole component and calling the setter method associated with the attribute.
In cases when a component needs to be "dynamically built" based on a static model, better is to use view build time tags like JSTL, if necessary in a tag file, instead of createComponent(), new SomeComponent(), getChildren().add() and what not. See also How to refactor snippet of old JSP to some JSF equivalent?
Or, if a component needs to be "dynamically rendered" based on a dynamic model, then just use an iterator component (<ui:repeat>, <h:dataTable>, etc). See also How to dynamically add JSF components.
Composite components is a completely different story. It's completely legit to bind components inside a <cc:implementation> to the backing component (i.e. the component identified by <cc:interface componentType>. See also a.o. Split java.util.Date over two h:inputText fields representing hour and minute with f:convertDateTime and How to implement a dynamic list with a JSF 2.0 Composite Component?
Only use binding in local scope
However, sometimes you'd like to know about the state of a different component from inside a particular component, more than often in use cases related to action/value dependent validation. For that, the binding attribute can be used, but not in combination with a bean property. You can just specify an in the local EL scope unique variable name in the binding attribute like so binding="#{foo}" and the component is during render response elsewhere in the same view directly as UIComponent reference available by #{foo}. Here are several related questions where such a solution is been used in the answer:
Validate input as required only if certain command button is pressed
How to render a component only if another component is not rendered?
JSF 2 dataTable row index without dataModel
Primefaces dependent selectOneMenu and required="true"
Validate a group of fields as required when at least one of them is filled
How to change css class for the inputfield and label when validation fails?
Getting JSF-defined component with Javascript
Use an EL expression to pass a component ID to a composite component in JSF
(and that's only from the last month...)
See also:
How to use component binding in JSF right ? (request-scoped component in session scoped bean)
View scope: java.io.NotSerializableException: javax.faces.component.html.HtmlInputText
Binding attribute causes duplicate component ID found in the view
each JSF component renders itself out to HTML and has complete control over what HTML it produces. There are many tricks that can be used by JSF, and exactly which of those tricks will be used depends on the JSF implementation you are using.
Ensure that every from input has a totaly unique name, so that when the form gets submitted back to to component tree that rendered it, it is easy to tell where each component can read its value form.
The JSF component can generate javascript that submitts back to the serer, the generated javascript knows where each component is bound too, because it was generated by the component.
For things like hlink you can include binding information in the url as query params or as part of the url itself or as matrx parameters. for examples.
http:..../somelink?componentId=123 would allow jsf to look in the component tree to see that link 123 was clicked. or it could e htp:..../jsf;LinkId=123
The easiest way to answer this question is to create a JSF page with only one link, then examine the html output it produces. That way you will know exactly how this happens using the version of JSF that you are using.

How to get the DOM of a JSF 2.0 component's generated HTML from the backing bean?

I have a JSF-page containing only a PrimeFaces Calendar component, backed by a view scoped bean.
<p:calendar value="#{calendarBean.today}" mode="inline" showOtherMonths="true" pages="1" binding="#{calendarBean.model}" />
The generated HTML for this component contains a table that I'd like to adjust. More specifically, I want to put icons dynamically into this calendar by adding some HTML-code under the td-tags of the targeted days.
From the CalendarBean I can fetch from some service a list of objects representing days "with icons". I need this list to decide which days to alter in the table. I tried to get the HTML DOM in my backing bean, but I don't understand how. The UIComponent tree (that I get via the binding property) only contains the JSF-components, not the generated HTML. I start to doubt if this is even the way to approach the problem.
My google-skills seem to fall short here. Can anybody help me?
The concrete functional requirement is not entirely clear, so it's hard to propose the right way for this, but there are in general varous ways to alter the look'n'feel of the JSF/PrimeFaces-generated HTML.
Use custom CSS. Icons could simply be set as CSS background images.
Use custom JS. JS has instant access to the entire HTML DOM tree.
Use custom JSF renderer. Extend the PrimeFaces CalendarRenderer class and override the encodeXxx() method(s) accordingly.
The backing bean is supposed to be the controller between the view (the XHTML file) and the model (the javabean entity class holding the data which is to be presented to the enduser or to capture the submitted data from enduser). It isn't supposed to manipulate the HTML.

Spring-MVC Common Model Attributes Used in Tags or Page Fragments

It's common to have many pages in a website that request the same model attributes, for example, a header that renders the current users name, or a column that needs a few server based pieces of information.
...
<body>
<mytaglib:header/>
...
<jsp:include page="footer.jsp"/>
...
</body>
The simplest solution is that every controller method you write that returns views that use the header, or footer also add all of attributes needed by components contained within it, but as the site grows it can become difficult to handle, particularly when you start dealing with pages that don't all have exactly the same components.
Is there a way to encapsulate the logic that adds to the model based on sub-pages or tags?
Well, you could do that in a few ways. The following pop in mind:
Put your logic in a Filter that places the information in request scope;
Spring has something similar to a Filter called an Interceptor. You can place your logic here and again save it in request scope.
Have the logic behind a custom tag that is inserted into your pages. There is a disadvantage to this because you must insert the tag in each JSP. If you are using a decorator filter like SiteMesh then you could place this once in your decorator JSPs and be done with it.
Have the logic in a parent controller that all your controllers will extend.
Do you use a framework in particular? If you only use servlets I would suggest you to create a base servlet class, if using spring I will suggest you to create a Base SPring MVC Controller. ANd you can set these attributes from the base class or use filters :)

In Struts 1.3, what's the best way for the Controller to fill the View with variables?

I've just inherited some old Struts code.
If Struts (1.3) follows the MVC pattern, how do the Action classes fill the View with variables to render in HTML ?
So far, I've seen the Action classes push variables in (1) the HTTP request with
request.setAttribute("name", user.getName())
(2) in ActionForm classes, using methods specific to the application:
UserForm form = (UserForm) actionForm;
form.setUserName(user.getName());
and (3) a requestScope variable, that I see in the JSP layer (the view uses JSP), but I can't see in the Action classes.
<p style='color: red'><c:out value='${requestScope.userName}' /></p>
So, which of these is considered old-school, and what's the recommended way of pushing variables in the View in Struts ?
My Struts days are long over, but as far as I remember we used to place one view-specific bean (which would work as a holder for fine-graner beans or collections of beans) into the request scope within our Action.perform() implementation. This view-specific bean would then be rendered by the view.
As Struts 1.3 is considered old-school, I'd recommend to go with the flow and use the style that already is used throughout the application you inherited.
If all different styles are already used, pick the most used one. After that, pick your personal favourite. Mine would be 1 or 3 - the form (2) is usually best suited for data that will eventually be rendered inside some form controls. If this is the case - use the form, otherwise - don't.

Mixing jsp and jsf

I will elaborate somewhat. Jsf is kind-of extremely painful for working with from designer's perspective, somewhat in the range of trying to draw a picture while having hands tied at your back, but it is good for chewing up forms and listing lots of data. So sites we are making in my company are jsf admin pages and jsp user pages. Problem occurs when user pages have some complicated forms and stuff and jsf starts kickin' in.
Here is the question: I'm on pure jsp page. I need to access some jsf page that uses session bean. How can I initialize that bean? If I was on jsf page, I could have some commandLink which would prepare data. Only thing I can come up with is having dummy jsf page that will do the work and redirect me to needed jsf page, but that's kind of ugly, and I don't want to end up with 50 dummy pages. I would rather find some mechanism to reinitialize bean that is already in session with some wanted parameters.
Edit: some more details. In this specific situation, I have a tests that are either full or filtered. It's a same test with same logic and everything, except if test is filtered, it should eliminate some questions depending on answers. Upon a clicking a link, it should start a requested test in one of the two modes. Links are parts of main menu-tree and are visible on many sibling jsp pages. My task is to have 4 links: testA full, testA filtered, testB full, testB filtered, that all lead on same jsf page and TestFormBean should be reinitialized accordingly.
Edit: I've researched facelets a bit, and while it won't help me now, I'll definitely keep that in mind for next project.
have you looked into using facelets? It lets you get rid of the whole JSF / JSP differences (it's an alternate and superior view controller).
It also supports great design-time semantics with the jsfc tag...
<input type="text" jsfc="#{SomeBean.property}" class="foo" />
gets translated internally to the correct JSF stuff, so you can work with your existing tools.
You can retrieve a managed bean inside of a tag library using something like this:
FacesContext context = FacesContext.getCurrentInstance();
Object myBean = context.getELContext().getELResolver().getValue(context.getELContext(), null, "myBeanName");
However, you'd need to use the tag library from one of your JSF pages. FacesContext.getCurrentInstance() returns null when it's called outside of the FacesServlet.
To solve this one I'd probably create a JSF fragment that only includes your form, then use a <c:import> tag to include it in my JSF page.
That solution is probably a little fragile depending on your environment though.
EDIT: See Chris Hall's answer, FacesContext is not available outside the FacesServlet.
Actually, I've resolved this by removing bean from session, so it has to be generated again when jsf page is called. Then I pick up get parameters from a request in constructor.
Create a custom JSP tag handler. You can then retrieve the bean from session scope and then initialize it on the fly. See this tutorial for more details.

Categories