How to call ad hoc SSJS from a Java Bean - xpages

I need to call ssjs from a java bean similar to this this issue. The issue is that the code I need to execute comes from a configuration document, and may look like:
getComponent("xxx").getValue();
I have built a version that does :
String compute = doc.getItemValueString("SSJSStuff");
String valueExpr = "#{javascript:" + compute + "}";
FacesContext fc = FacesContext.getCurrentInstance();
Application app = fc.getApplication();
ValueBinding vb = app.createValueBinding(valueExpr);
String vreslt = vb.getValue(fc).toString();
but I get "Exception in xxx: com.ibm.xsp.exception.EvaluationExceptionEx: Error while executing JavaScript computed expression"
I think I am close, but I do not see over the hill.. Any thoughts?

There are several possibilities for this:
The variable compute is empty
compute contains illegal chars
The code inside compute is malformed / has no correct syntax
No object is returned in your SSJS code:
If your SSJS code does not return something, vb.getValue(fc) returns null. A toString() will fail. To prevent this, you should cast your returning object explicitly:
vreslt = (String) vb.getValue(fc);
Hope this helps
Sven
EDIT:
After re-reading your post, I saw that you want to do a getComponent in your dynamic SSJS Code. This won't work with a value binding added to the javax.faces.application.Application. For this, you have to use the com.ibm.xsp.page.compiled.ExpressionEvaluatorImpl object instead:
String valueExpr = "#{javascript:" + compute + "}";
FacesContext fc = FacesContext.getCurrentInstance();
ExpressionEvaluatorImpl evaluator = new ExpressionEvaluatorImpl( fc );
ValueBinding vb = evaluator.createValueBinding( fc.getViewRoot(), valueExpr, null, null);
vreslt = (String) vb.getValue(fc);

Related

JSF: how to tell if a ValueExpression does not exist or actually its value is null?

FacesContext context = FacesContext.getCurrentInstance();
ELContext ctx = context.getELContext();
ValueExpression expression = context.getApplication().getExpressionFactory().createValueExpression(
ctx, "#{foo111.bar}", String.class);
String value = expression.getValue(ctx);
The return value is null. Obviously foo111.bar does not exist. Is there a way to tell if an expression does not exist or actually its value is null.
The best way to do that would be to evaluate the expression. If it's a property expression this should be side-effect free (And smart EL Implementations cache this operation, so it should be cheap if invoked several times).
If it's a method expression it'll get more complicated. Invoking the function could cause a state mutation if all you're wanting to do is 'check for existence'. You could in theory get the base object and see if it exists without invoking the function, which gets you a little closer, but isn't a complete solution:
final ValueReference valueReference = valueExpression.getValueReference(getFacesContext().getELContext());
final Object base = valueReference.getBase();
... valueReference.getProperty();

Sorting a Listbox in C++

first time asking questions here. I'm having trouble sorting a listbox in a c++ form. I would much rather do this in C# but it's a class requirement unfortunately. Here's the code in question:
void updateCourseDisplay()
{
courseListBox->Items->Clear();
set<Course*> courseSet = courseControl->getCourseSet();
std::set<Course *>::iterator it;
for (it = courseSet.begin(); it != courseSet.end(); ++it)
{
Course * c = (*it);
String ^courseId = gcnew String((c->getID().c_str()));
String ^courseName = gcnew String((c->getName().c_str()));
courseListBox->Items->Add(courseId + " - " + courseName);
}
courseListBox->System::Windows::Forms::ListBox::Sort();
populateCopyStudentsComboBox();
}
I know this is pretty messy but I didn't want to mess around with creating managed objects to add to the form. The error I'm getting when I try and run this says that System::Windows::Forms::ListBox::Sort() would have been called but it is inaccessible. All I want is simple ordering of the list by the string value. Any thoughts?
Sort is a protected method that can not be accessed from the "outside". You should set the public Sorted property to true instead.

p:autoComplete binding not showing label for searched value

I am trying to generate autocomplete box through binding. But I am not sure why label for the searched value is not rendered on UI. Code snippet is added below. Please help.
FacesContext facesContext = FacesContext.getCurrentInstance();
AutoComplete autoComplete = new AutoComplete();
ExpressionFactory factory = ExpressionFactory.newInstance();
#SuppressWarnings("rawtypes")
Class[] classes = new Class[1];
classes[0] = User.class;
autoComplete.setCompleteMethod(factory.createMethodExpression(facesContext.getELContext(), "#{userBean.values}", List.class , classes));
autoComplete.setVar("user");
autoComplete.setDropdown(false);
autoComplete.setItemValue(facesContext.getApplication().getExpressionFactory().createValueExpression("#{user}", User.class));
autoComplete.setItemLabel(facesContext.getApplication().evaluateExpressionGet(facesContext, "#{user.name}", String.class));
autoComplete.setConverter(new CommonConvertor());
I end up writing custom renderer in which wherever ItemLabel is referred I overridden the method & instead of using ItemLabel directly I put the EL expression evaluation whenever I find ItemLabel is starting with "#{". Which resulted in proper working of an autocomplete. The solution works.
I have overridden below methods
encodeInput
encodeMultipleMarkup
encodeSuggestionsAsTable
encodeSuggestionsAsList
Please let me know if you can find easier solution.

How do I extract the value of a UIInput in XPages

I have an Xpages application that manipulates Contracts. One procedure uses the Contract Type value in field "conService" to determine what must happen next. The code below does NOT produce any errors but third line does not seem to process any result and in fact does not even seem to process any line in the procedure after it. How do I extract the value of the conService? Thanks
UIInput uifield = (UIInput) JSFUtil.findComponent("conService");
String serviceName ="";
serviceName = uifield.getValue().toString();
You are almost there....
Once you have the UIInput object you can do either .getSubmittedValue() or .getValue() - depending on where in the JSF lifecycle you are. And then you just need to cast it to a String - instead of using toString().
So something like should do the trick:
UIInput uifield = (UIInput) JSFUtil.findComponent("conService");
String serviceName = (String)uifield.getValue();
To avoid having to thinkg about using getSubmittedValue or getValue I use a small utility method in my code:
ublic static Object getSubmittedValue(UIComponent c) {
// value submitted from the browser
Object o = null;
if (null != c) {
o = ((UIInput) c).getSubmittedValue();
if (null == o) {
// else not yet submitted
o = ((UIInput) c).getValue();
}
}
return o;
}
That just makes life a little less complicated ;-)
/John
Where possible, it's worth going directly to the datasource you're storing the value in. It's more efficient and easier to manage.
If you do need the value during Process Validation phase, for a converter or validator, you can use component binding to easily access the relevant component, at which point you can use getSubmittedValue() - because the value will not have been set yet. Here's a NotesIn9 from Tim Tripcony covering it http://notesin9.com/index.php/2014/05/22/notesin9-143-component-vs-value-binding-in-xpages/.

Get Values from a valueExpression JSF1.2

I am trying to get the value contained in a value expression. I need to use it for some validation. When I set the value expression in an HTMLOutput it is displayed on the screen. Please suggest what am I doing wrong?
HtmlOutputText output = new HtmlOutputText();
ve = ef.createValueExpression(elCtx, "#{dynamicRow["+ i + "]}", String.class);
//I have tried all options here that I came across.
//Either test1 , test2 , test3 should have the value ve has, but all of them have value "".
String test1 = (String)ve.getValue(elCtx);
String test2 = (String)output.getValue();
Application app = fCtx.getApplication( );
String test3 = (String) app.evaluateExpressionGet(fCtx, "#{dynamicRow["+ i + "]}", String.class);
output.setValueExpression("value", ve);
//the ve gets displayed in the column with correct string values and not ""
column.getChildren().add(output);
// I also tried ValueReference as given in ValueExpression: how to get base Object?
ValueReference valueReference = ve.getValueReference(elCtx);
//an exception is thrown here javax.el.PropertyNotFoundException: Target Unreachable, identifier 'dynamicRow' resolved to null
Object base = valueReference.getBase();
Object property = valueReference.getProperty();
where my table has the following code:
FacesContext fCtx = FacesContext.getCurrentInstance();
ELContext elCtx = fCtx.getELContext();
ExpressionFactory ef = fCtx.getApplication().getExpressionFactory();
HtmlExtendedDataTable dynamicDataTable = new HtmlExtendedDataTable();
HtmlDatascroller datascroller = new HtmlDatascroller();
ValueExpression ve = ef.createValueExpression(elCtx,"#{myController.dynamicList}", List.class);
dynamicDataTable.setValueExpression("value", ve);
dynamicDataTable.setVar("dynamicRow");
The var value dynamicRow is only in scope when the table places it into scope during processing. This is done by the various process* methods on component.
See setRowIndex(int) documentation:
Save current state information for all descendant components (as described below).
Store the new row index, and pass it on to the DataModel associated with this UIData instance.
If the new rowIndex value is -1:
If the var property is not null, remove the corresponding request scope attribute (if any).
Reset the state information for all descendant components (as described below).
If the new rowIndex value is not -1:
If the var property is not null, call getRowData() and expose the resulting data object as a request scope attribute whose key is
the var property value.
Reset the state information for all descendant components (as described below).

Resources