Struts2 MessageResources in Apache Tiles - struts2

I'm trying unsuccessfully to use a Struts2 message resource in a tiles
2.1.4 expression. For example the following resource is available in
the JSP...
<s:text name="htmlheadHeading1"/><br/>
... but when I attempt to use the same resource in the tiles definition...
<put-attribute name="title" expression="${htmlheadHeading1}" />
... I get the error...
ELResolver cannot handle a null base Object with identifier 'htmlheadHeading1'
... Is there any way to do this??

This solution does not use tiles expressions but will work if you need to display localized text in JSP when key is passed through tiles definitions.
In tiles definition:
<put-attribute name="title" value="htmlheadHeading1" />
In your JSP then use Struts2 <s:set> tag to set title from tiles definition to local variable and then use it in <s:text> tag.
<s:set var="title">
<tiles:getAsString name="title" ignore="true"/>
</s:set>
<s:text name="%{#title}"/>

Related

How to pass a variable to s:text?

First things first, I'm not a seasoned Struts user. Here is my struts code:
<s:set var="foo" value="BAR">
<s:text name="key.for.foo">
<s:param><s:property value="foo" /></s:param>
</s:text>
Here is the properties file containing the key.for.foo text value:
key.for.foo=blah blah {0}
I expect the text below:
blah blah BAR
but I get
blah blah
What am I missing ?
You can try the below code
<s:text name="key.for.foo"><s:param value="#foo"/></s:text>
The usage of <s:set /> vars is covered in the tag documentation's example:
<s:set var="personName" value="person.name"/>
Hello, <s:property value="#personName"/>
Nutshell is that the Value Stack has multiple ways of looking things up: stuff pushed onto the stack (e.g., the action itself, <s:push /> properties), stuff in the servlet context (e.g., session and request attributes/properties), and named objects (e.g., <s:set /> objects, <s:iterator /> status value).

JSTL c:set and Struts s:set are undesirably formatting numbers

<c:set var="xmlDocumentId" value="${id}" scope="request" />
<s:set var="xmlDocumentId" value="%{id}" scope="request" />
are formatting id based on locale, setting xmlDocumentId to "12,345" while:
<c:out value="${id}" />
<s:property value="%{id}" />
are outputting "12345".
Any ideas how to break this behavior?
Because you are getting value with getText or <s:text> tag your long value gets formatted according to locale. To prevent this from happening convert your long to string.
With <s:set> tag you can call toString() method directly in value attribute.
<s:set var="xmlDocumentId" value="id.toString()" scope="request" />
For the concrete formatting algorithm take a look at java.text.MessageFormat class and its subformat method.
Once you know how to format numbers in Java, in Struts2 <s:property/> tag you can use getText() to format your number in the desired way, for example :
<s:property value="getText('{0,number,#,##0}',{id})"/>
Try this
<s:text name="id" > <s:param name="value" value="id"/> </s:text>

Build-in Grails tags do not work

During grails application upgrade from 1.3.8 to 2.3.9 I run into the problem that grails build-in tags are ignored.
For example lets say that GSP page has two tags:
<g:if test="${true}">OK</g:if>
<g:hiddenField name="test" />
then the result of execution will be:
OK
<g:hiddenField name="test" />
but expected result is :
OK
<input type="hidden" name="test" />
Basically tags from grails-web-2.3.9.jar are working fine but from grails-plugin-gsp-2.3.9.jar are completely ignored.
Any clue why this happens is appreciated. Thank you.
UPDATE:
I found that while executing TagLibraryLookup.afterPropertiesSet() method grailsApplication object is null, so the tag lib is not registered. Now it is not clear why it is null...
Solotion:
The problem was that within static constraints = { } of domain object it was a call of
ApplicationHolder?.getApplication().getMainContext()?.getBean(serviceName) method. It prevented the application from initialization of all required spring/grails beans by changing initialization sequence/flow.
You're missing some double-quotes here:
<g:if test=${true}>OK</g:if>
<g:hiddenField name="test" />
If you add them:
<g:if test="${true}">OK</g:if>
<g:hiddenField name="test" />
Does that help? Also, check for any changes to the default encoding that was made in Config.groovy after you upgraded.

Authorization in JSF2 components

In our project we have JSF2 pages used in internal network of a company. But we are going to open those pages to Internet. So pages will be available to everybody. But some fields will not be rendered if a user comes from Internet.
I know it is possible to write a rendered attribute for each component such as "userIsInRole". But additional "rendered" control doesn't seem to be efficient and elegant method. So I plan to mark the components which are going to be rendered online by using a custom attribute as shown below:
<h:inputText context="internet" />
...
In the renderer of the inputText or component code:
if(user is from Internet && context = "internet") {
return true; // or render... whatever
}
If a component is not marked as Internet, then it means it will be available (rendered) only from inside of the company.
Is it possible implement authorization by using JSF2 components according to a given attribute? Is there any better options? Or should I design separate pages for internet users?
We use: PrimeFaces + Spring in our project.
Thank you
This is ridiculous. What's the difference in effort of ultimately using
<h:inputText context="internet" />
versus
<h:inputText rendered="#{intranet}" />
?
If your sole problem is that you need to repeat the whole condition everytime ending up in ugly code like so
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
...
then just refactor the condition to a single request scoped variable
<c:set var="intranet" value="#{not (user.hasRole('internet') and context eq 'internet')}" scope="request" />
...
<h:inputText rendered="#{intranet}" />
<h:inputText rendered="#{intranet}" />
<h:inputText rendered="#{intranet}" />
...

Get id of parent naming container in template for in render / update attribute

I have a template and in its Definition I use several forms and buttons.
The problem is the definition (define) xhtml file does not know the component hierarchy.
And for example I want to update the element "table2" in a different form in the same define file.
Template Insert:
<p:tabView id="nav"> <!-- nav -->
<ui:insert name="content_nav">content navigation</ui:insert>
</p:tabView>
defines the first level of my hierarchy "nav"
Template define:
<ui:define name="content_nav">
<h:form id="form1"> <!-- nav:form1 -->
<h:dataTable id="table1"/> <!-- nav:form1:table1 -->
<p:inputText value="#{bean.value}"/>
<p:commandButton action="..." update="nav:form2:table2"/>
</h:form>
<h:form id="form2">
<h:dataTable id="table2"/> <!-- nav:form2:table2 -->
<!-- other elements -->
</h:form>
</ui:define>
In my define part I don't want to know "nav"!
How can I do this? or how can I move one naming component upwards?, or save the highest parent complete id in a variable?
sometimes i saw something like:
update=":table2"
But I could not find any informations about this?, the JavaEE 6 documentation just mentions the # keywords.
Ugly, but this should work out for you:
<p:commandButton action="..." update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2" />
As you're already using PrimeFaces, an alternative is to use #{p:component(componentId)}, this helper function scans the entire view root for a component with the given ID and then returns its client ID:
<p:commandButton action="..." update=":#{p:component('table2')}" />
ugly answer works well
update=":#{component.namingContainer.parent.namingContainer.clientId}:form2:table2
mainly more useful updating from opened dialog to parent datatable
You may use binding attribute to declare EL variable bound to JSF component. Then you may access absolute client id of this component by using javax.faces.component.UIComponent.getClientId(). See example below:
<t:selectOneRadio
id="yourId"
layout="spread"
value="#{yourBean.value}"
binding="#{yourIdComponent}">
<f:selectItems value="#{someBean.values}" />
</t:selectOneRadio>
<h:outputText>
<t:radio for=":#{yourIdComponent.clientId}" index="0" />
</h:outputText>
Try this:
<h:commandButton value="Click me">
<f:ajax event="click" render="table" />
</h:commandButton>
Additionally to the solutions above I had the problem, that I had to dynamically generate the to-be-updated components (many) based on server-side logic (with maybe harder to find out nesting).
So the solution on the server-side is an equivalent to update=":#{p:component('table2')}"1 which uses org.primefaces.util.ComponentUtils.findComponentClientId( String designId ):
// UiPnlSubId is an enum containing all the ids used within the webapp xhtml.
// It could easily be substituted by a string list or similar.
public static String getCompListSpaced( List< UiPnlSubId > compIds ) {
if ( compIds == null || compIds.isEmpty() )
return "" ;
StringBuffer sb = new StringBuffer( ":" ) ;
for ( UiPnlSubId cid : compIds )
sb.append( ComponentUtils.findComponentClientId( cid.name() ) ).append( " " ) ;
return sb.deleteCharAt( sb.length() - 1 ).toString() ; // delete suffixed space
}
called via some other method using it, e.g. like ... update="#{foo.getCompListComputed( 'triggeringCompId' )}".
1: first I tried without too much thinking to return public static String getCompListSpaced0() { return ":#{p:component('table2')}" ; } in an ... update="#{foo.getCompListSpaced0()} expression, which of course (after thinking about how the framework works :) ) is not resolved (returned as is) and may cause the issues with it some users experienced. Also my Eclipse / JBoss Tools environment suggested to write :#{p.component('table2')} ("." instead of ":") which did not help - of course.

Resources