I have project running spring with tiles2 and Thymeleaf template engine.
In tiles I want to display an authentication navbar depending if the user is authenticated or not, to do so I'm using apache-tiles EL to choose which navbar will be selected.
here is my tiles definition
`<definition name="abstract.layout" template="/layouts/abstractLayout" templateType="thymeleaf" >
<put-attribute name="navbar" type="definition" expression="${principal} !=null ? 'authenticated.navbar' : 'guest.navbar'" />
<put-attribute name="title" value="company" type="string" />
<put-attribute name="description" value="E-Commerce Platform" type="string" />
<put-attribute name="sidebar" value="/layouts/fragments/sidebar/sidebar::content" type="thymeleaf" />
<put-attribute name="footer" value="/layouts/fragments/footer::content" type="thymeleaf" />
<put-list-attribute name="thirdPartyCssFiles" >
</put-list-attribute>
<put-list-attribute name="customCssFiles">
</put-list-attribute>
<put-list-attribute name="pluginJsFiles">
</put-list-attribute>
<put-list-attribute name="customJsFiles">
</put-list-attribute>
</definition>`
When I'm evaluating the tile, the variable ${principal} isn't found in the evaluation context.
My questions are:
How to get the spring-security principal object and how to know if the user is authenticated?
Is there a way to use SPEL instead of EL or ONGL in expressions?
Thank you
Related
it's a bit similar to this problem https://issues.jboss.org/browse/RF-11469
I have a template containing a composite defined like this:
<h:form id="transfer_list">
<ccs:criteriaPanel header="Critère de recherche"
filterAction="#{controller.filter()}">
<form:criteriaForm bean="#{controller.transferCriteria}"
rendered="#{! empty controller.transferSearchForm}"
mode="UPDATE"
controller="#{controller}" />
</ccs:criteriaPanel>
</h:form>
Controller is defined with a ui:param in the template child.
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
template="/pages/transfer/transferList.xhtml">
<ui:param name="controller" value="#{transferListOpenController}" />
</ui:composition>
Here is the composite impl (criteriaPanel):
<cc:interface>
<cc:attribute name="header" default="#{i18n['HEADER_SEARCH_CRITERIA']}" />
<cc:attribute name="filterAction" method-signature="java.lang.Object filter()" />
<cc:attribute name="update" default="#(.ui-datatable)" />
</cc:interface>
<cc:implementation>
<div id="#{cc.clientId}">
<p:panel header="#{cc.attrs.header}" toggleable="true">
<cc:insertChildren />
<f:facet name="footer">
<p:commandButton id="search_btn"
value="#{i18n['BUTTON_FILTER']}"
action="#{cc.attrs.filterAction}"
icon="ui-icon-search"
update="#{cc.attrs.update}" />
<p:commandButton value="#{i18n['BUTTON_CLEAR_FILTER']}"
action="#{cc.attrs.filterAction}"
process="#this"
immediate="true"
update="#{cc.attrs.update}">
<p:ajax update="#form" resetValues="true" />
</p:commandButton>
</f:facet>
<p:defaultCommand target="search_btn" />
</p:panel>
</div>
</cc:implementation>
Clicking on the button "filterAction" result into this:
javax.faces.FacesException: #{cc.attrs.filterAction}:
javax.el.PropertyNotFoundException: Target Unreachable, identifier
[controller] resolved to null at
com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
at
org.primefaces.application.DialogActionListener.processAction(DialogActionListener.java:45)
at javax.faces.component.UICommand.broadcast(UICommand.java:315)
I use Tomcat 8.5 for this and Mojarra 2.2.13. It works if I don't put the whole thing in a composite component (criteriaPanel)
UPDATE
Sample available here: https://github.com/Rapster/primefaces-test/tree/issue-sof-45834296
Works fine with MyFaces 2.2.11 and Mojarra 2.2.8-23 and 2.3.2 (I don't know how impactful upgrading to 2.3 can be though...) From what I read here https://stackoverflow.com/a/42656386/4605161, Mojarra 2.2.8 is aimed for WebLogic but it seems I will need this one (and i'm running on Tomcat)
WORKAROUND
Writing this make it work (but that's a workaround i'd rather use template):
<ui:composition xmlns="http://www.w3.org/1999/xhtml">
<ui:param name="controller" value="#{testView}" />
<ui:decorate template="/template.xhtml">
</ui:decorate>
</ui:composition>
Funny thing is if I put ui:param inside ui:decorate I'll end up with the same exception
Should be fixed in 2.2.15, see github.com/javaserverfaces/mojarra/issues/4271
after a desperate period of trials and errors i come to you looking for help, since now i am even unsure if i am doing it all wrong.
My code below displays some fields from a user profile in read only input text boxes. The data comes from a bean as ArrayList of "field" objects, whos properties are described in the ui:param directives.
The user can click an unlock/lock button next to the box to start/finish editing her data.
I want to trigger input validation when the user presses enter after editing or clicks the lock button.
But whatever i tried, after editing and pressing enter or clicking the button, the changed value is not written back and my custom validator is not triggered. Somehow it seems that after clicking the button the then rendered input box is not bound to the field? However, the validator works (and all attributes get passed to it) if used in an input text that is always rendered - and i don't understand it :)
Please have a look at it. If i did not explain my intent well enough or if you need more code, please let me know.
Edit: the annotations of the backing bean:
#ManagedBean( name = "beanProfile" )
#RequestScoped
The jsf code:
<ui:composition>
<ui:param name="i18n" value="#{field.i18n}" />
<ui:param name="val" value="#{field.value}" />
<ui:param name="req" value="#{field.required}" />
<ui:param name="min" value="#{field.min}" />
<ui:param name="max" value="#{field.max}" />
<ui:param name="validationType" value="#{field.validationType}" />
<ui:param name="useHidden" value="#{field.hidden}" />
<ui:param name="locked" value="#{field.locked}" />
<ui:param name="fullName" value="#{beanProfile.name}" />
<h:form id="profileFrm">
<h:outputText value="#{msg.role_profile} " styleClass="headingOutputText" />
<h:outputText value="#{fullName}" styleClass="headerTitle" />
<p />
<h:panelGroup>
<ui:repeat var="field" value="#{beanProfile.userFields}">
<h:panelGrid columns="2">
<h:outputText value="#{msg[i18n]}" styleClass="headerTitle" />
<h:message showDetail="true" for="visInput" styleClass="warn"
rendered="#{!useHidden}" />
<h:message showDetail="true" for="invisInput" styleClass="warn"
rendered="#{useHidden}" />
</h:panelGrid>
<h:panelGrid columns="2" columnClasses="nameColumn">
<h:inputText id="visInput" required="true" value="#{val}"
rendered="#{!useHidden}" readonly="#{locked}" >
<f:validator validatorId="customValidator" />
<f:attribute name="requiredField" value="#{req}" />
<f:attribute name="minLen" value="#{min}" />
<f:attribute name="maxLen" value="#{max}" />
<f:attribute name="type" value="#{validationType}" />
</h:inputText>
<h:inputSecret id="invisInput" required="true" value="#{val}"
rendered="#{useHidden}" readonly="#{locked}">
<f:validator validatorId="customValidator" />
<f:attribute name="requiredField" value="#{req}" />
<f:attribute name="minLen" value="#{min}" />
<f:attribute name="maxLen" value="#{max}" />
<f:attribute name="type" value="#{validationType}" />
</h:inputSecret>
<h:commandLink id="lock" action="#{beanProfile.lock(field)}"
rendered="#{!locked}" title="#{msg.profile_lock}">
<h:graphicImage height="16" width="16"
name="images/padlock_unlocked.svg" alt="#{msg.profile_lock}" />
</h:commandLink>
<h:commandLink id="unlock" action="#{beanProfile.unlock(field)}"
rendered="#{locked}" title="#{msg.profile_unlock}">
<h:graphicImage height="16" width="16"
name="images/padlock_locked.svg" alt="#{msg.profile_unlock}" />
</h:commandLink>
</h:panelGrid>
</ui:repeat>
</h:panelGroup>
<p />
<h:commandButton id="submitProfileBtn" value="#{msg.cmd_submit}"
styleClass="button" includeViewParams="true"
action="#{beanProfile.submitProfile()}" />
</h:form>
</ui:composition>
The origin of your problem is that you are using the RequestScoped scope for your backing bean containing the Model, so when you want to do a postback request in order to execute the backing bean method the binding just have dissapeared (not in the server memory) and the JSF lifecycle doesn't execute as expected. The solution is to use a longer scope as the ViewScoped scope. Ideally you should use the CDI compatible viewScoped scope, so you have to use JSF 2.2.x version.
Thank you lametaweb, you led me in the right direction.
Being unable to use the #ViewScoped annotation i found the link
how-to-install-cdi-in-tomcat
and followed BalusC's directions for using CDI in Tomcat. Then i had to let all the java classes implement the Serializable interface.
Now i can use the #ViewScoped annotation and the validator gets triggered.
As a follow-up to the question I had asked before, now that primefaces 5.2 is available, I cannot seem to get the tree to be navigated using arrow keys. As I mentioned before, in the showcase, one can use the arrow-keys to navigate, expand or collapse nodes. Using exactly the same code locally does not however allow this arrow-keys navigation.
Is there a specific attribute i need to add to the tree element?
How does one enable arrow-keys navigation, expand and context?
here is the tree snippet:
<p:tree value="#{treeEventsView.root}" var="doc" selectionMode="single" selection="#{treeEventsView.selectedNode}" dynamic="true">
<p:ajax event="expand" update=":form:messages" listener="#{treeEventsView.onNodeExpand}" />
<p:ajax event="collapse" listener="#{treeEventsView.onNodeCollapse}" />
<p:ajax event="select" listener="#{treeEventsView.onNodeSelect}" />
<p:ajax event="unselect" listener="#{treeEventsView.onNodeUnselect}" />
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed" ariaLabel="Folder" >
<h:outputText value="#{doc.name}"/>
</p:treeNode>
<p:treeNode type="document" icon="ui-icon-document">
<h:outputText value="#{doc.name}" />
</p:treeNode>
<p:treeNode type="picture" icon="ui-icon-image">
<h:outputText value="#{doc.name}" />
</p:treeNode>
<p:treeNode type="mp3" icon="ui-icon-video">
<h:outputText value="#{doc.name}" />
</p:treeNode>
</p:tree>
This is not working in my application. It still accept numbers also.
<p:inputText id="Name" value="#{dependbean.name}" maxlength="30">
<pe:keyFilter mask="alpha"></pe:keyFilter>
</p:inputText>
Move the <pe:keyFilter> outside of the <p:inputText> and use the for attribute to point which component is the filter defined for.
<p:inputText id="Name" value="#{dependbean.name}" maxlength="30" />
<pe:keyFilter mask="alpha" for="Name" />
Try
<p:inputText id="Name" value="#{dependbean.name}" maxlength="30">
<pe:keyFilter regex="/[ABC]/i"></pe:keyFilter>
</p:inputText>
Make sure the you have the element added in the beginning of the file
<html ...
xmlns:pe="http://primefaces.org/ui/extensions">
if still doesn't work, make sure the pom.xml file has the dependencies from primefaces extensions.
If not, add this to the pom between tags:
<!-- https://mvnrepository.com/artifact/org.primefaces.extensions/primefaces-extensions -->
<dependency>
<groupId>org.primefaces.extensions</groupId>
<artifactId>primefaces-extensions</artifactId>
<version>6.0.0</version>
</dependency>
Is it possible to pass dynamic values in tiles.xml as we do in struts.xml in Struts2? I have used ${parameter} to get dynamic values in config file but it doesnt seem to work. Any ideas?
You can pass wildcards to tiles from your struts actions, I've used this to do similar things for dynamic projects where each client might have a different CSS file for instance.
In your struts action you would have a tiles result type and you can pass the value such as:
<action name="{eventURL}/update" class="org.groundworkgroup.struts.actions.admin.UpdateEventSettings">
<result name="login" type="tiles">/login.tiles</result>
<result name="input" type="tiles">/admin.${#session.bean.pageID}.${#session.bean.fileID}.tiles</result>
<result name="success" type="tiles">/admin.${#session.bean.pageID}.${#session.bean.fileID}.tiles</result>
</action>
And then in your tiles.xml you would "plug in" the wildcards:
<definition name="/admin.*.*.tiles" extends="adminLayout">
<put-attribute name="title" value="Welcome" />
<put-attribute name="jsfile" value="{1}/js/{2}.js" />
<put-attribute name="cssfile" value="{1}/css/{2}.css" />
<put-attribute name="body" value="/WEB-INF/content/sites/admin/main.jsp" />
<put-attribute name="menu" value="/WEB-INF/content/sites/admin/menu.jsp" />
</definition>
In this particular example the struts action pageID is the project directory where the files are located and in the tiles.xml it is placed as wildcard {1}. The fileID is the filename associated with this particular action or user represented in the tiles.xml by {2}. You can use this set up to pass dynamic values to your tiles in order to control for example page states or JSP's to render or like in this example, custom css and js files.