This week's book giveaway is in the Servlets forum.
We're giving away four copies of Murach's Java Servlets and JSP and have Joel Murach on-line!
See this thread for details.
The moose likes JSF and the fly likes Passing JSF variable to JSTL c:out doesn't work Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » JSF
Bookmark "Passing JSF variable to JSTL c:out doesn Watch "Passing JSF variable to JSTL c:out doesn New topic
Author

Passing JSF variable to JSTL c:out doesn't work

Bert Bertens
Greenhorn

Joined: Feb 16, 2010
Posts: 14
Hi,

I need to display "driver.png"-image when the route.driver.email is the same email as the user logged in, otherwise the "passenger.png"-image.

I figured following code would be suitable:



However, I can't pass the variable #{route.driver.email} to JSTL "driverEmail", because this is the output:
driverEmail1: testEmail
Login: testEmail, Driver:
<image passenger.png>

so "driverEmail" is null.

I wonder if anyone has a better solution for this problem, or can tell me what I am doing wrong?

Regards
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15950
    
  19

Bert Bertens wrote:
I wonder if anyone has a better solution for this problem, or can tell me what I am doing wrong?


What you are doing wrong is mixing JSTL with JSF. I won't say you should never do that, but I haven't found a good reason to use JSTL on a JSF page ever and I've been working with JSF since about 1985.

There's nothing a <c:out> can do that an <h:outputText> can't do.

To display an element conditionally, use the JSF tag's "rendered" attribute. You don't need to wrap the tag with conditional logic. You can select between 2 alternatives images using a "bean.x" property by using the 'rendered="#{bean.x}"' attribute on the first image and 'rendered="#{! bean.x}"' on the second. If you have more than 2 alternatives, I'll leave that as an exercise for you.


Customer surveys are for companies who didn't pay proper attention to begin with.
Bert Bertens
Greenhorn

Joined: Feb 16, 2010
Posts: 14
Tim Holloway wrote:
What you are doing wrong is mixing JSTL with JSF. I won't say you should never do that, but I haven't found a good reason to use JSTL on a JSF page ever and I've been working with JSF since about 1985.

I thought that this was the best way to do the condition, since I'm working with 2 parameters.

Tim Holloway wrote:
There's nothing a <c:out> can do that an <h:outputText> can't do.
To display an element conditionally, use the JSF tag's "rendered" attribute. You don't need to wrap the tag with conditional logic. You can select between 2 alternatives images using a "bean.x" property by using the 'rendered="#{bean.x}"' attribute on the first image and 'rendered="#{! bean.x}"' on the second. If you have more than 2 alternatives, I'll leave that as an exercise for you.

The problem is that this is in a datatable, a List<Route> gets rendered (var="route"). I could add a property in the Route-class and return a boolean if the driver's email is the email of the user logged in, but that would be a bad OO-design I guess, so I can't do rendered="#{route.isDriver}".
The backing bean is appropriate I think for checking if the user is the driver of the #{route}, but I can't call the #{routeBean.isDriver}-method and specify a parameter, and then return the appropriate image, or can I?

Also, 1985 JSF? Isn't that a bit early?
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15950
    
  19

Bert Bertens wrote:
Tim Holloway wrote:
What you are doing wrong is mixing JSTL with JSF. I won't say you should never do that, but I haven't found a good reason to use JSTL on a JSF page ever and I've been working with JSF since about 1985.

I thought that this was the best way to do the condition, since I'm working with 2 parameters.

Nope. <h:outputText value="Login: #{loginBean.email},Driver: ${loginBean.driver.email}"/>
Bert Bertens wrote:
Tim Holloway wrote:
There's nothing a <c:out> can do that an <h:outputText> can't do.
To display an element conditionally, use the JSF tag's "rendered" attribute. You don't need to wrap the tag with conditional logic. You can select between 2 alternatives images using a "bean.x" property by using the 'rendered="#{bean.x}"' attribute on the first image and 'rendered="#{! bean.x}"' on the second. If you have more than 2 alternatives, I'll leave that as an exercise for you.

The problem is that this is in a datatable, a List<Route> gets rendered (var="route"). I could add a property in the Route-class and return a boolean if the driver's email is the email of the user logged in, but that would be a bad OO-design I guess, so I can't do rendered="#{route.isDriver}".
The backing bean is appropriate I think for checking if the user is the driver of the #{route}, but I can't call the #{routeBean.isDriver}-method and specify a parameter, and then return the appropriate image, or can I?


I think you're making the common, but incorrect assumption that a datatable has to be bound to the domain data. A JSF datatable is a Model object, and its primary purpose isn't domain data, it's to server as the Model part of MVC. And, just like the Model objects in, say, Swing, the JSF model objects are go-betweens with personalities of their own, not just placeholders.

In particular, a very useful practice is to front a domain object with a decorator that provides additional rendering information. Such as, in your case, whether a given domain row object should display image A or image B. Another common use is to handle the grief that you get when domain objects are referencing "boolean" items whose database fields are number or character items (since a lot of DBMS's don't support native boolean types). A JSF checkbox needs a true boolean as its value object, so the alternatives are a custom converter or adding something to the same effect to the model decorator.

BTW, you don't "call" a routeBean.isDriver on your JSF view. You reference the routeBean's driver property. That's an important distinction to make since A), "routeBean.isDriver" won't work as a value attribute, and B), value objects are lvalues. Meaning that not only is "isDriver invoked, but setDriver, as well. All the calling (or invoking, in OO terminology) is done by the framework. The JSF tags are specifications, not code.

Bert Bertens wrote:
Also, 1985 JSF? Isn't that a bit early?

Yup. Not everyone who's "Over the Hill" is "Behind the Times" :)
Bert Bertens
Greenhorn

Joined: Feb 16, 2010
Posts: 14
Tim Holloway wrote:
I think you're making the common, but incorrect assumption that a datatable has to be bound to the domain data. A JSF datatable is a Model object, and its primary purpose isn't domain data, it's to server as the Model part of MVC. And, just like the Model objects in, say, Swing, the JSF model objects are go-betweens with personalities of their own, not just placeholders.

If I understand correctly, I must bound the datatable to a Collection. In my case, a Collection of Route-objects. I still don't understand how I can 'decorate' this class so I can choose the appropriate image. Is 'decorating' the rendering of the h:datatable component you are referring to?

Tim Holloway wrote:
BTW, you don't "call" a routeBean.isDriver on your JSF view. You reference the routeBean's driver property. That's an important distinction to make since A), "routeBean.isDriver" won't work as a value attribute, and B), value objects are lvalues. Meaning that not only is "isDriver invoked, but setDriver, as well. All the calling (or invoking, in OO terminology) is done by the framework. The JSF tags are specifications, not code.

Good point.

Tim Holloway wrote:
Yup. Not everyone who's "Over the Hill" is "Behind the Times" :)

I meant that I don't think JSF existed back then, since Servlets originate from 1997 :) But I get the point.
bostian tov
Ranch Hand

Joined: Mar 11, 2010
Posts: 32
I have simmilar problem. I would like to set background color for rich:datatable for 1 row. So 1 row will have one color, other rows some other color. Is there a way that i could do this? That is simmilar to c:if ? Or some other way
I have information about selected row in bean.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15950
    
  19

Bert Bertens wrote:
I meant that I don't think JSF existed back then, since Servlets originate from 1997 But I get the point.


Urk. I'll stack my technical expertise against anyone's. But don't ever depend on me to have a proper sense of time.

I meant 2005. In 1985, C++ was being developed in AT&T Bell Laboratories, and the next year it would become available for outside licensing. Which I did, creating the C++ for Commodore Amiga, marketed under the SAS label. And Java hadn't been invented yet.

Sorry about that.
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15950
    
  19

bostian tov wrote:I have simmilar problem. I would like to set background color for rich:datatable for 1 row. So 1 row will have one color, other rows some other color. Is there a way that i could do this? That is simmilar to c:if ? Or some other way
I have information about selected row in bean.


For regular alterations such as ledger lines, the dataTable has the rowClasses attribute. For irregular alterations, try providing a row class name using an EL reference to a backing bean property that supplies the computed class name as required for that row.

Although in the case of dataTable, I don't believe that the rows are directly defined/accessed, so you may have to consider alternatives.
Bert Bertens
Greenhorn

Joined: Feb 16, 2010
Posts: 14
Tim Holloway wrote:
Urk. I'll stack my technical expertise against anyone's. But don't ever depend on me to have a proper sense of time.

Alright. I wish the website I'm making didn't have a proper sense of time, unfortunately, it has to be done by Friday. This is of course a minor thing not working, but I would like to see it finished.

I still don't understand how to implement your decorator-solution, could you please further explain it?

If this isn't going to work I'm gonna add a boolean-attribute 'isDriver' to the Route-class and work the getter out something like this:

But I wouldn't like that solution since it's uncatholic. (is that an expression?)
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15950
    
  19

"Uncatholic" is a perfectly good word, but probably not the best one to use here, since "catholic" is more in the lines of "universal". "un-kosher", if you will.

A Decorator is one of the Gang of Four (GoF) Design Patterns, and it's basically a proxy or wrapper for an object that "decorates" that object with additional properties. In this particular case, adding the "isDriver()" read-only property method to the setter/getter methods that it repeats from the object being decorated. From the sound of it, however, you have enough control over the base object that in your case you can just add isDriver to the original class and not need a separate decorator.

However, if you want to talk "un-kosher", if not dowright haram (going muslim just to complete the roster), Using FacesContext.getSession.getBean is not the way to go. If you need to access one JSF managed bean from another managed bean, use property injection (Inversion of Control).

As a general rule, the less JSF-specific code that's in a bean, the better.
Bert Bertens
Greenhorn

Joined: Feb 16, 2010
Posts: 14
Tim Holloway wrote:"Uncatholic" is a perfectly good word, but probably not the best one to use here, since "catholic" is more in the lines of "universal". "un-kosher", if you will.

A Decorator is one of the Gang of Four (GoF) Design Patterns, and it's basically a proxy or wrapper for an object that "decorates" that object with additional properties. In this particular case, adding the "isDriver()" read-only property method to the setter/getter methods that it repeats from the object being decorated. From the sound of it, however, you have enough control over the base object that in your case you can just add isDriver to the original class and not need a separate decorator.

However, if you want to talk "un-kosher", if not dowright haram (going muslim just to complete the roster), Using FacesContext.getSession.getBean is not the way to go. If you need to access one JSF managed bean from another managed bean, use property injection (Inversion of Control).

As a general rule, the less JSF-specific code that's in a bean, the better.


Ah, Ive only been properly introduced to design patterns since half a year, so I didn't immediatly see this implemented (since Hibernate returns Route-classes, and not RouteDecorator-classes). I also could be talking complete rubbish here and reread the book I have on design patterns, but for now I'll just go with the IoC-way.

Thanks for the multicultural help!
Tim Holloway
Saloon Keeper

Joined: Jun 25, 2001
Posts: 15950
    
  19

The decorator class is usually something you write, since the point of it is to add features that you need that the underlying object doesn't have. In the case of datatables, you can do things like create a list of decorators and fill it by enumerating the underlying object collection, constructing a decorator object for each underlying object, and inserting the decorator into the decorator list, which is then wrapped by a ListDataModel.

Which is a lot less fun than simply wrapping the underlying collection, since you can do that in a single line of code. But sometimes the extra work is worth the price.

Don't feel bad about the design patterns. Actually codifying and naming these critters was a relatively recent event, although some of these techniques I've been using for years. The iterator pattern got to be blatantly obvious when I moved to C++. Seemed like almost everything I did for a while had an iterator in it.

The GoF book is one of those tomes that should be at the heart of any good IT library. Sun also documented a set of uniquely J2EE design patterns, although some of them aren't as applicable when considering modern frameworks.
Bert Bertens
Greenhorn

Joined: Feb 16, 2010
Posts: 14
Tim Holloway wrote:The decorator class is usually something you write, since the point of it is to add features that you need that the underlying object doesn't have. In the case of datatables, you can do things like create a list of decorators and fill it by enumerating the underlying object collection, constructing a decorator object for each underlying object, and inserting the decorator into the decorator list, which is then wrapped by a ListDataModel.

Which is a lot less fun than simply wrapping the underlying collection, since you can do that in a single line of code. But sometimes the extra work is worth the price.

I think I'm gonna go the easy way for now, however, another problem that comes to mind is the IoC, how can I set the LoginBean-property on RouteDecorato-class.
In the faces-config.xml I can't create a bean for the Router-class, because what scope would I define. After all, I instantiate the Route-class in the RouteController-class, several times, before returning the total Collection to the JSF.
For now I use this:


Tim Holloway wrote:
Don't feel bad about the design patterns. Actually codifying and naming these critters was a relatively recent event, although some of these techniques I've been using for years. The iterator pattern got to be blatantly obvious when I moved to C++. Seemed like almost everything I did for a while had an iterator in it.

I don't, I enjoyed learning about them but have not yet been able to effectively use them in my design. Maybe I'll implement it here, but first I'm just gonna try and make the deadline for now.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Passing JSF variable to JSTL c:out doesn't work
 
Similar Threads
how to Autosave the changes when the page is changed?
Best choice for pagination?
Cannot set parameter in HTML:Link
Problem with equality test.
problem with c:set tag