Can Thymeleaf access the Spring servletContext? - spring-webflow-2

I wonder if anyone can help. We are in the process of converting a Spring Webflow 2 application from using a jsp based view layer, to a Thymeleaf based view.
For this most part this is OK, but now I'm struggling to get Thymeleaf to access an object that we've put in the servletContext.
So, we have an object that is put in the servletContext as part of a bean (implementing ServletContextAware and InitializingBean)
For the sake of simplicity, lets say it is a string:
public class ReferenceDataBuilder implements ServletContextAware, InitializingBean {
public void setServletContext(ServletContext p_context) {
p_context.setAttribute("referenceData", "test text" );
}
In our jsp based views, we can access the referenceData object like this:
<p><c:out value="${referenceData}"/></p>
By the magic of Spring EL, it knows the various scopes it has access to (servletContext, flowScope, flashScope etc), and (I'm guessing?) searches each scope until it finds a matching property. The result is that:
<p>test text</p>
is rendered within the view.
In our thymeleaf template, we are trying to do the same thing:
<p th:text="${referenceData}"/></p>
But this simply returns an empty string. The view renders an empty string:
<p></p>
(but I think the EL is actually being returned as a null)
I'm pretty sure that if the referenceData object were a property of a scope such as flowScope or flashScope this would work - but its not, its a property of servletContext.
Does anyone know if thymeleaf can access the servletContext via EL? Perhaps theres a different syntax I need to use?
Cheers
Nathan

You could access usual maps via the #ctx object, which is of type SpringWebContext.
For example #ctx.locale, #ctx.httpServletRequest.contextPath, #ctx.servletContext or even #ctx.applicationContext for Spring applicationContext.
You could use direct method invocation
<p th:text="${#ctx.servletContext.getAttribute('referenceData')}">Whatever</p>
or the applicationAttributes variables map
<p th:text="${#ctx.servletContext.applicationAttributes.referenceData}">Whatever</p>
or event simpler using Spring implicit object
<p th:text="${application.referenceData}">Whatever</p>

Related

Evaluate EL expression from string as bean in JSF page

I am fairly new to JSF and am currently a frontend developer for a new project. I do not have access to the backend code and need to create a solution with the data I have access to on the page.
Currently I have a menu and there are security controllers on HTML elements to control visibility.
Example:
style="#{security.ConfigMenu?'visibility:visible':'visibility:hidden;width:0px;height:0px;padding-bottom: 0px;'}"
This page is hardcoded and need to make it more dynamic.
I need to evaluate this expression but use an array of beans stored as strings
var security = ["security.ConfigMenu", "security.AdminMenu", "security.Dashboardmenu"];
Need to handle #{mappSec.insightsConfigMenu'} with #{security[0]}
Is this possible?
I tried to replace the bean call with a string using the bean name
#{bean.method}
with
var bean = "bean.method";
#{bean}

Get rendered html code in Backing Component from Composite Component

How can I get the posted form data in the backing component in the
processUpdates method?
#Override
public void processUpdates(FacesContext context) {
//get here rendered html code
}
Or can I get the posted form data in the decode method?
[Edit]:
My goal is to get the posted form data - Not to get the generated html code (Sry I wasn't precisely)
It is unclear what you want to achive, yet. I mean, at high level.
UIComponent.decode and processUpdates are medium-level lifecycle APIs which should be overriden when you want to extend the framework.
If you just need to use the framework, you need a managed bean, not a backing component.
Furthermore, generally only components that extend UIInput need to hook in those phases, because they are bound to a value="#{...}" value expression (which in turn refers to a managed bean, in most cases), and need to synchronize those values with the bound expression.
I suspect you are uselessly complicating your life: hooking into medium or low-level APIs is a real pain if you don't have an excellent understanding about how the framework operates.
Anyway, the standard request parameters decode into input component is this:
String clientId = this.getClientId(context);
Map<String, String> requestMap = context.getExternalContext().getRequestParameterMap();
String newValue = requestMap.get(clientId);
if (newValue != null)
{
this.setSubmittedValue(newValue);
}
Please, post the full xhtml facelet code (not the composite one, but the facelet using that composite), so I can understand where you want to go and I can try to point you to the right tool to use.

How to create a RenderURL during action phase in a portlet?

In the method processAction(ActionRequest request, ActionResponse response), I insert a record into database and get the ID and then
I want to redirect to the view page of this record. So I need to create a RenderURL with a parameter value for that ID.
ActionResponse doesn't provide method to create a renderURL. Some codes in Liferay do similar things like:
create renderURL before accessing the actionURL
pass the renderURL as a parameter in the actionURL
However, at that time, I don't know the value of ID.
Other codes also use new PortletURLImpl() directly. My portlet cannot see that class.
Other codes also use new PortletURLImpl() directly. My portlet cannot see that class.
Because this class is in portal-impl.jar and also it is not recommended to use classes from this jar. Starting from Liferay 6.1, you won't be able to build your portlet from plugins-sdk if you classes point to portal-impl.jar.
Now to answer your question:
Any jsp is rendered by the render method or doView method (if using liferay's MVCPortlet) and this method would be called as part of the normal life-cycle of portlets.
Here are the steps you would need to take:
set a render parameter (using response.setRenderParameter() method) in your `processAction' method at the last which would be available in your render method, as follows:
actionResponse.setRenderParameter("myID", 1201);
Just for info: After using setRenderParameter you cannot use sendRedirect method
fetch this "myID" in your render method as you fetch any other request parameter:
//assuming your ID is a long
long myUserName = ParamUtil.getLong(renderRequest, "myID");
or
String strMyID = renderRequest.getParameter("myID");
long myID = Long.parseLong(strMyID);
After this, just use
include(renderPage, renderRequest, renderResponse);
were renderPage is nothing but a string containing the path to your jsp within docroot like /html/yourportlet/view.jsp
Just as an afterthought:
If you are using a Liferay IDE, then you can try creating a simple portlet project with MVCPortlet and then look at the generated portlet.xml's <init-param>
So basically you need to pass information from action-phase to render-phase, the development guide is a good place for explaining this in detail.
That's it.
Hope this helps.
Let me know if you have any confusion regarding this.
In action phase do the following:
ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute (WebKeys.THEME_DISPLAY);
PortletURL url = PortletURLFactoryUtil.create(request, this.getPortletName(), themeDisplay.getPlid(), PortletRequest.RENDER_PHASE);
For example, if you want to redirect to the login page and back, you can do the following:
response.sendRedirect("/c/portal/login?redirect=" + HttpUtil.encodeURL(url.toString()));
Definitely you can add or copy the parameters as required.
Instead of creating the renderURL you can include the view page include(viewTemplate,actionRequest,actionResponse). Or if you want to sent any parameter any want's to get it in doView then use actionResponse.setParameter(name,value) method
I create a RenderURL with a place holder as parameter value, like this:
<portlet:renderURL var="redirect">
<portlet:param name="ID" value="__ID__" />
</portlet:renderURL>`
In processAction:
String redirect = redirectParam.replace("__ID__", "123213");
actionResponse.sendRedirect(redirect) ;

Suggestion on JSF authorization

I learnt how to use container authentication with JDBC realm.
I searched a lot on internet but I couldn't find anything on JSF authorization except the following article.
JSF authorization
My goal is to avoid access to protected pages using direct links and to show/hide menu items and form components based on the authenticated user privileges.
The last part can be implemented using the rendered attribute of JSF tags but before creating my own dirty and high coupled solution I wonder if there are some specific best practices or libraries that can help. in fact the number of components to be conditionally rendered is quite high and I wouldn't like to write a specific function for each of them.
Perhaps I can create for each authenticated user a map with the names (id) of all the conditionally rendered components and a single function with a String parameter (the unique name/id of the component). Is that a good idea ? What alternatives do I have ?
I wouldn't like to add to the project other general purpose frameworks such as spring for using only a small part of them (the security one).
Thanks
Filippo
With the Expression Language version in Java EE 6 you should be able to use expressions like these:
<h:inputText rendered="#{facesContext.externalContext.isUserInRole('foo')}" />
With older versions, you can create a managed bean of this form:
public class RoleMap implements Map<String, Boolean> {
public Boolean get(Object key) {
ExternalContext extCtxt = FacesContext.getCurrentInstance()
.getExternalContext();
return extCtxt.isUserInRole(key.toString());
}
//TODO: other methods; mostly throwing UnsupportedOperationException
The test can then be expression in the form:
<h:inputText rendered="#{roleMap['foo']}" />
Third party frameworks offer other options, such as the Apache Tomahawk library's visibleOnUserRole component attributes.
Take a look at Apache Shiro, a dedicated security framework (and supposedly erasier to use than Spring Security).

What is the correct way to bind input value to JSF managed bean property?

I am new to JSF and managed beans. I have a managed bean with some private property with public setter and Getter methods. Now when I add the managed bean's properties to JSF forms, should I add the private methods directly or should I use call the property by Getter methods?
For example:
<h:inputText value="#{BeanName.userName}"/>
<h:inputText value="#{BeanName.getUserName()}"/>
Which one is correct in above?
Assuming that you're using JBoss EL or EL 2.2+, both ways would work fine in the initial display. But the first one is actually more correct because the second one would only get the value, but never set the value. If you want to collect input values, you should always go for the first way. The EL (Expression Language) will then automatically locate the getUserName() and setUserName() methods whenever needed.
The second way will never work when you're using standard JSF EL implementation since it doesn't support direct method calls.
To learn more about JSF, start at our JSF wiki page.
If in your java class you have something like
....
private String coolStuff;
public String getCoolStuff() {
return coolStuff;
}
....
Then in your jsf page you access it like so:
#{myBackingBean.coolStuff}
The framework automatically looks for a method called getCoolStuff()
Hope that helps
number 1 is correct from above it is the private field that you connect if you are using EL with JSF in your form.
You still need the getter and the setter which the managed bean calls to get the values so you can save them in a database ....etc

Resources