JSF 2.0 EL handeling nulls for resource keys - jsf-2

Just a quick question for you guys.
I have a resource key that is stored as a string in a managed bean and I'd like to get it to resolve to the value in a particular mapped Resource Bundle.
Here is what I started with:
<h:outputText value="#{msgs[bean.someVal]}"/>
I immediatly noticed that when someVal was null I would get the following exception:
javax.el.PropertyNotFoundException: /webpage.xhtml at line 118 and column 188 value="#{msgs[bean.someVal]}": Property '' not found on type java.util.PropertyResourceBundle
So I tried to set up a ternary like this:
<h:outputText value="#{bean.someVal == null ? '' : msgs[bean.someVal]}"/>
But I got the same error only quoting the new value.
I'm running JSF2.0 (Apache) on Tomcat6.
Anyone got any ideas? I'm pretty stumped on this one..
Let me know if you need more info, I hope this is enough to go on.. I'm thinking this is just something dumb that I'm doing ;)

Property '' not found
You've there an empty string. An empty string is not the same as null.
Use the empty check instead. It will check if the value is not null and if it is not an empty string.
<h:outputText value="#{empty bean.someVal ? '' : msgs[bean.someVal]}" />
An alternative, by the way, is to provide a custom ResourceBundle implementation on #{msgs} which doesn't throw the exception, but instead returns null or an empty String on handleGetObject() method.

Related

multiple expressions for single condition result

I have to change the header string of primefaces dialog, acording to a variable state in my backing bean. The condition would be the following (pseudo code):
#{backingBean.editing ? resourceBundle.edit_string resourceBundle.item.id : msg.add_string}
and the short snippet example:
<p:dialog id="dokDialog" header="#{backingBean.editing ? resourceBundle.edit_string resourceBundle.item.id : msg.add_string}" ...>
<!-- content -->
</p:dialog>
In this example I want to display either value #{msg.edit_string} #{resourceBundle.item.id} or #{msg.add_string} according to boolean value of #{backingBean.editing}.
What I want to do is to show either Editing Item 01 or New Item in the title.
Also I get the following exeption because I have two expressions (resourceBundle.edit_string resourceBundle.item.id) for one result:
Caused by: org.apache.el.parser.ParseException: Encountered " <IDENTIFIER>
Thanks!
resourceBundle.edit_string resourceBundle.item.id - it's a wrong expression. You need to concatenate
String.concat may help if you are using an appropriate version of EL: resourceBundle.edit_string.concat(' ').concat(resourceBundle.item.id)

Grails GSP null safety check trouble

I am trying to populate a text field on my GSP as such:
<label>Phone(aaa-bbb-cccc):</label>&nbsp<g:textField name="phone" style ="border-radius: 5px"
value="${recordToEdit.telephones = [] ? null : recordToEdit.telephones.first()}"></g:textField><br>
but it still tell me I can't access first() on an empty list. telephones is a List of Strings each being a phone number.
as #gross-jonas pointed out, the recordToEdit.telephones = [] ? .. : .. is terribly wrong already, unless it's a typo
the check you are trying to make should look like:
value="${recordToEdit.telephones ? recordToEdit.telephones.first() : ''}"
or
value="${recordToEdit.telephones?.getAt( 0 ) ?: ''}"
You can just use the Null Safe Operator (?.) as
${recordToEdit.telephones?.first()}
for null checks, which is not sufficient.
UPDATE
for empty list checks and null checks,
${ recordToEdit.telephones ? recordToEdit.telephones[0] : '' }
will be good.
Dude, didn't you just mean == instead of = ?
It looks like you are overwriting your telephones which get issued successfully instead of comparing it.

rich:autocomplete strange behaviour

We are upgrading from jsf 1.2 to jsf 2.
We are using apache myfaces 2.1 and rich faces 4.3.
We are facing very strange issue with <rich:autocomplete>. Below is the xhtml code.
<rich:autocomplete mode="cachedAjax" minChars="2" autocompleteMethod="#{bean.getData}"
var="result" value="#{bean.inputData}">
<h:column>
<h:outputText value="#{result}" />
</h:column>
</rich:autocomplete>
Following is the scenario , when an input is entered in an autocomplete input box , suggetions are shown - that is bean.getData method is called.
Surprisingly , after any of the suggestion is selected , bean.getData method is called again with chosen option value , which I believe is not the correct behaviour
since user has selected an option and not typed any input.
I don't want the bean.getData method to be called again. Is there any alternative ?
Please help.
EDIT 1
Since I am running a db query to get suggestion values , they are different than the actual input value typed to get suggestions. That is if I type "at" , my sugegstions could be "check me" . I understand that once prefix for search is changed , suggestions are evaluated again , but here i am not changing the prefix but selecting the entire suggestion value.
EDIT 2
Providing the context the issue occured with.
When autoCompleted method is called , it populates a hashMap with all the suggestions with CustomUserObject as the value.
Below is the code for this :
public List<String> getData(FacesContext context, UIComponent component, String input) {
Map<String, CustomUserObject> userMap = new HashMap<String, CustomUserObject>();
//get users from db
List<CustomUserObject> users = bean.fetchUserList(input);
//put users in map
for (CustomUserObject user : users) {
userMap.put(user.id, user) ;
}
List<String> userList = new ArrayList<String>();
//convert the list to List<String>
if(userList != null && !userList.isEmpty()){
//convert the List<CustomUserObject> to List<String>
}
return userList;
}
Now because of the issue mentioned in the question , getData is called again and corrupts userMap.
This map is used to retrieve correct CustomUserObject by comparing it with selected Suggestion like below :
if(userMap != null && !userMap.isEmpty()){
for(CustomUserObject user : userMap.values()){
if(selectedSuggestion != null && selectedSuggestion.equals(user.name)){
//match is found
//set variables to update ui at re-render
}
//no match found
//set variables to update ui at re-render
}
}
EDIT 3
In addition to above issues , it seems that there is no "nothing label" attribute for rich:autocomplete which was present for rich:suggestionBox which comes into picture when there is no result found.
This issue alongwith above issue is really making a difficult job to get this component working same as rich:suggestionBox

XSLT 2.0. Loop inside a Function

Hitting my wall here...
I've got the following data where a Primary Employee may have multiple dependents. I need to create a function that will match the Employee's SSN (ab:SSN) against the Dependent_SSN and determine if one of them is a 'Spouse'. If so, then we'll return the Dependent_SSN of the 'Spouse'.
If not, we'll move on and return the next non-'Spouse' Dependent_SSN.
I'm trying to create a function as I think I'll need this more than once. The code snippet resides inside of an existing template that is doing other looping functionality.
I've tried this but Oxygen returns an error:
<xsl:function name="ab:PQB">
<xsl:param name="EE_SSN">
</xsl:param>
<xsl:for-each select="/ab:Report_Data/ab:Report_Entry[ab:Employee_ID=$EE_SSN]/ab:Report_Data/ab:Report_Entry[ab:Employee_ID=$EE_SSN]ab:dependents/ab:Dependent_SSN">
</xsl:for-each>
The Error returned is :
"Engine name: Saxon-PE 9.3.0.5
Severity: fatal
Description: Unexpected token name "wd:dependents" beyond end of expression"
I know I need to test the higher level SSN against looping through the dependents, but like I said "I'm against my wall" :)
Data is here:
<ab:Report_Entry>
<ab:SSN>888881006</ab:SSN>
<ab:Last_Name>Smith</ab:Last_Name>
<ab:First_Name>Kimberly</ab:First_Name>
<ab:dependents>
<ab:Dependent_SSN>888881009</ab:Dependent_SSN>
<ab:Relation ab:Descriptor="Spouse">
</ab:Relation>
</ab:dependents>
<ab:dependents>
<ab:Dependent_SSN>888881004</ab:Dependent_SSN>
<ab:Relation ab:Descriptor="Child">
</ab:Relation>
</ab:dependents>
<ab:dependents>
<ab:Dependent_SSN>888881003</ab:Dependent_SSN>
<ab:Relation ab:Descriptor="Child">
<ab:ID ab:type="Related_Person_Relationship_ID">Child</ab:ID>
</ab:Relation>
</ab:dependents>
<ab:dependents>
<ab:Dependent_SSN>888881001</ab:Dependent_SSN>
<ab:Dependent_ID>1032D-4</ab:Dependent_ID>
<ab:Relation ab:Descriptor="Child">
<ab:ID ab:type="Related_Person_Relationship_ID">Child</ab:ID>
</ab:Relation>
</ab:dependents>
</ab:Report_Entry>
Thank you to any advice!
You might want to define the type of the input parameter and the type of the function result and then you should write a function body returning a value of that type. Currently your description sounds rather procedural, that is not going to work with XSLT/XPath.
As for the error, I think in the path /ab:Report_Data/ab:Report_Entry[ab:Employee_ID=$EE_SSN]/ab:Report_Data/ab:Report_Entry[ab:Employee_ID=$EE_SSN]ab:dependents/ab:Dependent_SSN you need one more slash /ab:Report_Data/ab:Report_Entry[ab:Employee_ID=$EE_SSN]/ab:Report_Data/ab:Report_Entry[ab:Employee_ID=$EE_SSN]/ab:dependents/ab:Dependent_SSN to have a syntactically correct path. That should avoid the syntax error you get but is not likely to return the result you want.

Request parameter if struts2 if tag

I have another probably basic problem. happy if u can help.
there is a request parameter 'action'. if I write :
<label><s:property value="%{#parameters.action}"/></label>
the value appears (it is 1)
So itry to test now :
<s:if test="%{#parameters.action == '1'}">YES 1</s:if><s:else>NOT 1</s:else>
NOT 1 appears.
I have tries all the syntaxes I found on the net for the test. Nothing changes, NOT 1 still displays
Thank you
This is because:
the value of %{#parameters.action} is an array, not a single value, and
the value will be type-converted to a number (not sure why; need to look in to that)
The correct expression would be:
<s:if test="%{#parameters.action[0] == 1}">YES 1</s:if><s:else>NOT 1</s:else>
The correct expression would be:
<s:if test="#parameters.action[0] == 1">YES 1</s:if><s:else>NOT 1</s:else>
The request parameters is a map of [Strinf, String[]], So you have to access it like above

Resources