How can I get portlet id in jsp page of it's configuration portlet?
From the level of specific portlet I can call in .jsp page:
String portletId = themeDisplay.getPortletDisplay().getId();
How can I get that id in configuration portlet's jsp?
If I understood you correctly this should give you portletId
final String portletResource = ParamUtil.getString(request, "portletResource");
final String portletId = PortletConstants.getRootPortletId(portletResource);
hello you can try this :
String portletId = themeDisplay.getPortletDisplay().getId();
String portletName = themeDisplay.getPortletDisplay().getPortletName();
String portletInstanceId = themeDisplay.getPortletDisplay().getInstanceId();
Don't forget:
<% ThemeDisplay themeDisplay = (ThemeDisplay) request.getAttribute(WebKeys.THEME_DISPLAY);
themeDisplay.getUser().getScreenName(); %>
Related
In a JSF backing bean (Managed Bean, Weld Bean, doesn't matter), I can get the context path the client is on by calling
FacesContext ctx = FacesContext.getCurrentInstance();
String path = ctx.getExternalContext().getRequestContextPath();
This gives me the path the client currently accesses, like /myapplication.
Is it also possible to get the current page, like /home.faces, and how?
You normally want to use UIViewRoot#getViewId() for this.
String viewId = facesContext.getViewRoot().getViewId();
This is in EL also available as follows:
#{view.viewId}
Exactly this value is reuseable in navigation case outcomes such as <h:link outcome> and <h:button outcome>.
Alternatively, you can also use HttpServletRequest#getRequestURI() to get whatever the enduser is actually seeing in the browser address bar.
String uri = ((HttpServletRequest) externalContext.getRequest()).getRequestURI();
Which is in EL also available as follows:
#{request.requestURI}
Exactly this value is reuseable in <h:outputLink value> or plain <a href>. Note that you can't use it as navigation case outcome.
Ok, got it, it's
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletRequest servletRequest = (HttpServletRequest) ctx.getExternalContext().getRequest();
// returns something like "/myapplication/home.faces"
String fullURI = servletRequest.getRequestURI();
String uri = ((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest()).getRequestURI();
String str = ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getRequestURI();
System.out.println(str);
I'm developing a dynamic form using Mojarra 2.2.5 and Primefaces 4.0 and i need to implement a datatable with dynamic content. Unfortunately when i try to submit form appears this error:
java.lang.NumberFormatException: Trying to extract rowIndex from clientId 'id_of_my_datatable:j_id1:j_id1'
I generated datatable by code using it, inspired by Primefaces Showcase (http://primefaces.org/showcase/ui/datatableDynamicColumns.jsf) and from (Stack Overflow discussion)
private DataTable addList(UIComponent parent, String labelStr, String id, List<ColumnModel> rowItems, List<Map<String, String>> values, String styleClass,
boolean isRequired, String updateComponents)
{
OutputPanel outputPanel = new OutputPanel();
outputPanel.setStyleClass("question_panel col-md-11");
if (labelStr != null)
{
addLabel(outputPanel, id, labelStr, "component_label col-md-11");
}
DataTable dataTable = new DataTable();
dataTable.setValue(values);
//mapModel = values;
//ValueExpression veTable = super.createValueExpression("#{composerTestBean.mapModel}", List.class);
//dataTable.setValueExpression("value", veTable);
dataTable.setVar("model");
dataTable.setId(id);
dataTable.setRowIndexVar("rowIndex");
Columns columns = new Columns();
columns.setValue(rowItems);
//columnModel = rowItems;
//ValueExpression veColumns = super.createValueExpression("#{composerTestBean.columnModel}", List.class);
//columns.setValueExpression("value", veColumns);
columns.setVar("column");
columns.setColumnIndexVar("colIndex");
HtmlOutputText headerText = new HtmlOutputText();
ValueExpression veHeader = super.createValueExpression("#{column.header}", String.class);
headerText.setValueExpression("value", veHeader);
columns.getFacets().put("header", headerText);
HtmlOutputText valueText = new HtmlOutputText();
ValueExpression veValue = super.createValueExpression("#{model[column.property]}", String.class);
valueText.setValueExpression("value", veValue);
columns.getChildren().add(valueText);
dataTable.getChildren().add(columns);
outputPanel.getChildren().add(dataTable);
parent.getChildren().add(outputPanel);
return dataTable;
}
As you can see I've also tried to use valueExpression and the property bean binding, but nothing is changed. setRowIndexVar() and setColumnIndexVar() methods are just attempts to resolve the question.
I also read that it could be a Mojarra bug on this discussion (it should be resolved) and in another one that is a Primefaces bug (I can't apply patches on project libraries).
Also I try to follow this post and this remove this exception but brings others problem to my page about update.
Do You think I'm doing something wrong? Or Is it just an unresolvable case?
Thanks in advance.
I want to access the resource map, not from my CCS file as in
background-image: url("#{resource['primefaces-supertheme:images/ui-icons_ffffff_0.png']}");
but from my bean. Is it possible with EL evaluation only?
The true Java variant would be Application#createResrouce() and then Resource#getRequestPath():
FacesContext context = FacesContext.getCurrentInstance();
Resource resource = context.getApplication().getResourceHandler().createResource("images/ui-icons_ffffff_0.png", "primefaces-supertheme");
String url = resource.getRequestPath();
// ...
Note that you could just evaluate EL programmatically. You can use Application#evaluateExpressionGet() for this.
FacesContext context = FacesContext.getCurrentInstance();
String url = context.getApplication().evaluateExpressionGet(context, "#{resource['primefaces-supertheme:images/ui-icons_ffffff_0.png']}", String.class);
// ...
If you happen to use JSF utility library OmniFaces, this can be simplified via Faces utility class as:
String url = Faces.evaluateExpressionGet("#{resource['primefaces-supertheme:images/ui-icons_ffffff_0.png']}");
// ...
I have an application with complex validations which I can only perform based on the model hierarchy, so I can not use JSF’s validation stage.
My problem is that I need to link back the validation errors to the gui (visually show the textfields that need attention). So I need to link UI Components with domain model items somewhere.
I was hoping to realise this using a PreRenderComponentEventListener :
my validatorcomponent stores Constraintvalidations where I have access to the object and property that needs attention.
I use the ValueExpression of the UIComponent to retrieve the correct object the Component binds to.
At first this seemed to work :
I have the following in a xhtml page :
<ui:composition template="/templates/mainTemplate.xhtml">
<ui:define name="content">
<ui:repeat value="#{contactController.contactManager.contactList}" var="contact">
<h:inputText value="#{contact.name}"/>
<h:inputText value="#{contact.firstName}"/>
<br/>
</ui:repeat>
</ui:define>
</ui:composition>
Now assume I have a list of contacts where one firstName fails.
ValueExpression’s expressionstring gives me “#{contact.firstName}” : I build a new ValueExpression from this one to retrieve the parent “#{contact}” and can check if the failing firstname is the one of the correct contact in the list.
So I do something like this in the Listener :
private Object extractParent(UIInput input) {
FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
ValueExpression orig = input.getValueExpression("value");
String parent = getParent(orig.getExpressionString());
ValueExpression valueExpression = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(faceletElContext,"#{"+parent+"}", Object.class);
return valueExpression.getValue(faceletElContext);
}
Now this only works when the repeat is in the top facelet.
As soon As my complex app uses include files and or this start to fail this because of 2 reasons :
The facelet context is the wrong one, not the one of the nested xhtml and thus it does not have the variable in it’s variableMapper
The variable is defined in the UIComponent’s valueexpression itself but that one is not accessible, has private access only so I can not use that one either.
So I am completely stuck ! Can someone provide me an alternative please ?
UPDATE after evaluation of response from #BalusC :
I tried with the ELContext but without success. I investigated a bit further and the core problem is that neither ELContext nor FaceletContext allows me access to variables defined in include files :
the ELContext does not have them
the FaceletContext seems to be the one of the last include file all the time and thus not the correct one.
I have a small testcase which proves this : When rendering the "contactinner" inputtext the ELContext has not this variable and the faceletcontext has the wrong xhtml hierarchy.
All help very very much appreciated.
test.xhtml :
<ui:composition>
<h:form id="myform">
<c:set var="itemContact" value="#{contactController.contact}"/>
<c:set var="itemPerson" value="#{contactController.person}"/>
<ui:include src="contact.xhtml"/>
<ui:include src="person.xhtml"/>
<h:commandButton action="#{contactController.process}"/>
</h:form>
</ui:composition>
contact.xhtml :
<ui:composition>
<c:set var="contactinner" value="#{itemContact}"/>
<h:inputText value="#{contactinner}"/>
</ui:composition>
person.xhtml :
<ui:composition>
<c:set var="personinner" value="#{itemPerson}"/>
<h:inputText value="#{personinner}"/>
</ui:composition>
faces-config.xml (extract) :
<system-event-listener>
<system-event-listener-class>TestSystemEventListener</system-event-listener-class>
<system-event-class>javax.faces.event.PreRenderComponentEvent</system-event-class>
</system-event-listener>
TestSystemEventListener (extract) :
public class TestSystemEventListener implements SystemEventListener {
#Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
UIInput input = (UIInput) event.getSource();
FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
FacesContext context = FacesContext.getCurrentInstance();
ValueExpression orig = input.getValueExpression("value");
}
Running this, when the evenlistener is launched for the inputext in the first xhtml #{contactInner} I get teh following data in the listener :
orig = {com.sun.faces.facelets.el.TagValueExpression#24201}"/xhtml/contact.xhtml #6,43 value=\"#{contactinner}\""
orig = {com.sun.el.ValueExpressionImpl#24220}"ValueExpression[#{contactinner}]"
expr = {java.lang.String#24270}"#{contactinner}"
varMapper = {com.sun.el.lang.VariableMapperImpl#24271}
vars = {java.util.HashMap#24275} size = 1
[0] = {java.util.HashMap$Entry#24278}"contactinner" -> "/xhtml/contact.xhtml #5,54 value=\"#{itemContact}\""
context = {com.sun.faces.context.FacesContextImpl#24200}
elContext = {com.sun.faces.el.ELContextImpl#24205}
functionMapper = {com.sun.faces.facelets.compiler.NamespaceHandler#24284}
variableMapper = {com.sun.faces.el.ELContextImpl$VariableMapperImpl#24221}
variables = {java.util.HashMap#24289} size = 2
[0] = {java.util.HashMap$Entry#24292}"itemContact" -> "/xhtml/test.xhtml #9,68 value=\"#{contactController.contact}\""
[1] = {java.util.HashMap$Entry#24295}"itemPerson" -> "/xhtml/test.xhtml #10,66 value=\"#{contactController.person}\""
faceletElContext = {com.sun.faces.facelets.impl.DefaultFaceletContext#24199}
faces = {com.sun.faces.context.FacesContextImpl#24200}
ctx = {com.sun.faces.el.ELContextImpl#24205}
facelet = {com.sun.faces.facelets.impl.DefaultFacelet#24151}"/xhtml/person.xhtml"
faceletHierarchy = {java.util.ArrayList#24206} size = 2
[0] = {com.sun.faces.facelets.impl.DefaultFacelet#23792}"/xhtml/test.xhtml"
[1] = {com.sun.faces.facelets.impl.DefaultFacelet#24151}"/xhtml/person.xhtml"
varMapper = {com.sun.faces.facelets.el.VariableMapperWrapper#24207}
target = {com.sun.faces.el.ELContextImpl$VariableMapperImpl#24221}
vars = {java.util.HashMap#24222} size = 1
[0] = {java.util.HashMap$Entry#24225}"personinner" -> "/xhtml/person.xhtml #5,52 value=\"#{itemPerson}\""
You should use the ELContext instance as obtained by FacesContext#getELContext(), not the FaceletContext.
private Object extractParent(UIInput input) {
ELContext elContext = FacesContext.getCurrentInstance().getELContext();
ValueExpression orig = input.getValueExpression("value");
String parent = getParent(orig.getExpressionString());
ValueExpression valueExpression = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createValueExpression(elContext, "#{" + parent + "}", Object.class);
return valueExpression.getValue(elContext);
}
A shorthand is by the way Application#evaluateExpressionGet().
private Object extractParent(UIInput input) {
FacesContext context = FacesContext.getCurrentInstance();
ValueExpression orig = input.getValueExpression("value");
String parent = getParent(orig.getExpressionString());
return context.getApplication().evaluateExpressionGet(context, "#{" + parent + "}", Object.class);
}
Following java code allows to access any object or variable from faces context:
ELContext elCtx = facesContext.getELContext();
ExpressionFactory exprFac = facesContext.getApplication().getExpressionFactory();
MyProperty myProperty = (MyProperty) exprFac.createValueExpression(elCtx, "#{somebean.someattr.someproperty}", MyProperty.class).getValue(elCtx);
I use the code from within my custom converter to read additional converting parameters from context.
The code works correctly if #{somebean} is defined as normal backing bean within JSF context.
Facelets allow to create 'shortcut' to JSF expressions. Example:
<ui:param name="shortcut" value="#{somebean.someattr.someproperty}" />
<div>#{somebean.someattr.someproperty} equals #{shortcut}</div>
In this case both #{somebean.someattr.someproperty} and #{shortcut} have the same value.
However these 'shortcut' names are not accessible using java code above. For example:
MyProperty myProperty1 = (MyProperty) exprFac.createValueExpression(elCtx, "#{somebean.someattr.someproperty}", MyProperty.class).getValue(elCtx);
// myProperty1 has expected value
MyProperty myProperty2 = (MyProperty) exprFac.createValueExpression(elCtx, "#{shortcut}", MyProperty.class).getValue(elCtx);
// myProperty2 is null
Is there a way to access a facelets context and to read 'shortcut' parameter values, defined on the current JSF page?
I had the same problem and have chosen the following approach:
/**
* Führt eine Expression im aktuellen Faces EL Context
* UND im Facelets El Context aus.
*
* #param facesContext
* #param expression
* #return object
*/
private static Object executeExpressionInUIContext (final FacesContext facesContext, final String expression) {
final ELContext elContext = facesContext.getELContext();
final Application application = facesContext.getApplication();
Object result = executeExpressionInElContext(application, elContext, expression);
if (null == result) {
FaceletContext faceletElContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
result = executeExpressionInElContext(application, faceletElContext, expression);
}
return result;
}
private static Object executeExpressionInElContext (Application application, ELContext elContext, String expression) {
ExpressionFactory expressionFactory = application.getExpressionFactory();
ValueExpression exp = expressionFactory.createValueExpression(elContext, expression, Object.class);
return exp.getValue(elContext);
}
"ui:param" is part of the Facelet view handling technology. Facelets extends JSF.
Both technologies use their own Context when storing variables.
Beside the Faces El Context there is a Facelet El Context (FaceletContext).
The stated method evaluates expressions in both contexts. Be aware that this will not work if two values are stored under the same name in each context.
It seems that facelet shortcuts do not exist in the context, where I try to access them.
I have made following workaround: On JSF page where my input element is placed, I have added a <f:param> element as child of the input with my converter.
<h:inputText id="myid" value="#{action.myinput}">
<f:converter converterId="myConverter" />
<f:param name="converterParameters" shortcut="#{somebean.someattr.someproperty}"/>
</h:inputText>
Then in converter I'm able to find UIParam element as one of the input children and read my shortcuts from it.
public Object getAsObject(FacesContext context, UIComponent component, String value) {
MyProperty myProperty = null;
try {
for (final UIComponent child : component.getChildren()) {
if ("converterParameters".equals(child.getAttributes().get("name"))) {
final ELContext elCtx = context.getELContext();
myProperty = (MyProperty) child.getValueExpression("shortcut").getValue(elCtx);
break;
}
}
if (myProperty == null) {
throw new NullPointerException("My property is undefined.");
}
} catch (Exception e) {
LOG.error("Cannot convert " + value + ". Use <f:param name=\"converterParameters\" "
+ "shortcut=\"#{here.comes.shortcut}\"/> for your input element. ", e);
throw new ConverterException("Cannot initialize converter.", e);
}
//...
}
The mapping of ui:param is not stored in context, it's in the VariableMapper of each individual ValueExpression.
So if you need to create ValueExpression programmatically, relying on another ValueExpression's varMapper, you can do something like this:
VariableMapper varMapper = new DefaultVariableMapper();
varMapper.setVariable(mappingName, component.getValueExpression(mappedAttributeName));
return new ValueExpressionImpl(expression, null, null, varMapper, expectedType);