Searching XPages event parameters - java

I assembled this piece of code from parts all over the XPages community, you might recognise a few:
var submitId= param.get( '$$xspsubmitid');
var component:com.ibm.xsp.component.xp.XspEventHandler= PageData.getComponentByClientId(submitId, view);
dprint("id= " + component.getClass().toString())
var params= component.getParameters();
for(var x:com.ibm.xsp.complex.Parameter in params) {
dprint(x);
dprint(x.getName());
dprint(x.getValue());
}
PageData is a managed bean, and getComponentByClientId does exactly what it says; its code, for completeness' sake:
public UIComponent getComponentByClientId(String id, UIComponent root) {
UIComponent component= new XspQuery().byClientId(id, root);
return component;
}
And as for XspQuery:
package org.openntf.xsp.extlib.query;
I want to find the name of the current field that triggered the partial update, and the form it is in. Both elements, fields and forms, are internal to my application. Their names are put in two Event Parameters, like this:
<xp:this.parameters>
<xp:parameter name="formName" value="#{javascript:compositeData.formName}"></xp:parameter>
<xp:parameter name="fieldName" value="#{javascript:compositeData.fieldName}"></xp:parameter>
</xp:this.parameters>
The issue is: when I put this code in one of the page events afterRestoreView, beforeRenderResponse or afterRenderResponse, the name of the parameter is correctly printed, but the call to getValue() never returns anything! More accurately: execution of the code stops, I don't know the exact error yet (which isn't exactly accurate, I admit).
How can I fetch these parameters?
TIA!

Looking at code in Mastering XPages, the way to access the value of an eventHandler parameter within the eventHandler's SSJS code is just to reference the name property as a variable. e.g. print(formName + ": " + fieldName)

Related

Unable to get a variable value in drools and use it to set in another field

drl file :
rule "pendingMsgSizeModified"
when
$tibcoEMSObj : TibcoEMSData(deliveredMsgCnt.contains("MB") && pendingMsgSize \> 100)
eval (!($tibcoEMSObj.typeOfAlert != null))
then
$tibcoEMSObj.setSendEmail(true);
$tibcoEMSObj.setTypeOfAlert($tibcoEMSobj.getTypeOfAlert()+"pendingMsgSize###");
update($tibcoEMSObj)
end
It gives error at this location : $tibcoEMSobj.getTypeOfAlert()
Error : \[Error: unable to resolve method using strict-mode: org.drools.core.spi.KnowledgeHelper.$tibcoEMSobj()\]
\[Near : {... SObj.setTypeOfAlert($tibcoEMSobj.getTypeOfAlert()+ ....}\]
I am expecting to use the getter method to get it and concatenate the string to set in another variable and save/update it
Your syntax is all over the place. And without actually seeing your model, it's hard to tell what you're even trying to do.
But based on what you said:
I am expecting to use the getter method to get it and concatenate the string to set in another variable and save/update it
And the code you did provide, I think this is what you're trying to do:
rule "pendingMsgSizeModified"
when
$tibcoEMSObj : TibcoEMSData(
deliveredMsgCnt.contains("MB"),
pendingMsgSize > 100,
$alertType: typeOfAlert != null
)
then
String newAlert = $alertType + "pendingMsgSize###";
modify($tibcoEMSObj) {
setSendEmail(true)
setTypeOfAlert(newAlert)
}
end
I presumed that your eval was either typo'd or just plain wrong since it was checking that the value was actually null. Don't use eval unless you have absolutely no other choice. (And I've never actually run into a situation where there was no other choice.)
I also presumed that the alert type will not change. I don't know what your sendEmail method does, or if it has side effects; if it does have side effects that change the typeOfAlert, then you'll of course need to call getTypeOfAlert() after calling setSendEmail.

How do I track variable dependencies in Nashorn?

I would like to use the Nashorn engine as a general computation engine. It is powerful, fast has plenty of built-in functions and new functions are very easy to add, using #FunctionalInterface or static methods. Even better, it also provides value-adds like cyclic dependency checking, syntax checking, etc.
However I need to automatically update "output" variables when a dependency changes.
The general idea is that in Java, I'll have something like:
class CalculationEngine {
Data addData(String name, Number value){
...
}
Data addData(String name, String formula){
...
}
String getScript(){
...
}
}
CalculationEngine engine = new CalculationEngine();
Data datum1 = engine.addData("datum1", 1); // Constant integer 1
Data datum2 = engine.addData("datum2", 2); // Constant integer 2
Data datum3 = engine.addData("datum3", "datum1*10");
Data datum4 = engine.addData("datum4", "datum3+datum2");
The CalculationEngine service class knows how to use Nashorn to create a script string out of the Data objects that looks like this:
final String script = engine.getScript(); // "var datum1=1; var datum2=2; var datum3=datum1*10; var datum4=datum3+datum2;"
I know I can parse the script with the Nashorn Parser:
final CompilationUnitTree tree = parser.parse("test", script, null);
But how do I extract the dependencies:
List<Data> whatDependsOn(Data input){
// Process the parsed tree
return list;
}
such that whatDependsOn(datum2) returns [datum4] and whatDependsOn(datum1) returns [datum3, datum4] ?
Or the inverse function getReferencedVariables such that getReferencedVariables(datum3) returns [datum1] and getReferencedVariables(datum4) returns [datum2, datum3] (and I can recursively query getReferencedVariables until all referenced variables have been found).
Basically, when the "value" of one of my Data objects change (due to an external event), how I determine which of my script formulae are affected and need to be recomputed?
I know that the Nashorn script can be parsed but I can not figure out how to use the SimpleTreeVisitorES6 to build up a variable dependency graph:
final CompilationUnitTree tree = parser.parse("test", script, null);
if (tree != null) {
tree.accept(new SimpleTreeVisitorES6<Void, Void>() {
#Override
public Void visitVariable(VariableTree tree, Void v) {
final Kind kind = tree.getKind();
System.out.println("Found a variable: " + kind);
System.out.println(" name: " + kind.toString());
IdentifierTree binding = (IdentifierTree) tree.getBinding();
System.out.println(" kind: " + binding.getKind().name());
System.out.println(" name: " + binding.getName());
System.out.println(" val: " + kind.name());
return null;
}
}, null);
}
one of Nashorn devs here. What you are trying to do is compute the so called def-use relations on source code (well, more likely their transitive closure, but I digress). That's a well-understood compiler theory concept. The good news is that CompilationUnitTree and friends should give you enough information to implement an algorithm for computing this information. The bad news is you'll have to roll up your sleeves and roll your own implementation, I'm afraid. You'll basically have to gather this information, produce merges at control flow join points (back edges and exits of loops, ends of if statements, but you'll also have to handle more exotic stuff like switch/case with their fallthrough semantics and also try/catch/finally, which is the least fun of these as basically control can transfer from anywhere in try block to a catch block.) Your algorithm will also have to repeatedly evaluate loop bodies until the static information you're gathering reaches a fixpoint.
FWIW, while writing Nashorn I had to implement these kinds of things few times using Nashorn's internal parser API (which is different but similar to the public one). If you want some inspiration, you can look into the source code for Nashorn static type analyzer for inferring types of local variables in a JavaScript function which is something I wrote some years ago. If nothing else, it'll give you an idea how to walk an AST tree and keep track of control flow edges and partially computed static analysis data at the edges.
I wish there were an easier way to do this… FWIW, a generalized static analyzer that helps you with bookeeping of flow control could be possible. Good luck.

Calling JavaScript function in Java

I'm trying to send an email using a javascript code in a Java project. Database connection works fine, I already tested it. I got the error:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EvaluatorException: missing ) after formal parameters (#1) in at line number 1
The only information of relevance is not readily reported: the final JavaScript string executed. Make sure to look at relevant data when debugging. After inspecting the final string it will be apparent why it is incorrect and trivial to "fix".
Hint: it will look something like function sendMail(userblah, foo#bar.qux) { .., which is indeed invalid JavaScript.
The problem and solution should be self-evident from that - use fixed parameters (variable names) in the function declaration and supply arguments (values) via the invokeFunction call.
Solution:
// The following parameter names are JAVASCRIPT variable names.
String script = "function sendMail(username, email, body) { ..";
// And pass correct arguments (values), in order. The variables used
// here are JAVA variables, and align by-position with the JS parameters.
inv.invokeFunction("sendMail", username, email, "EMAIL SENT!!!!");
In addition, the getElementById (invalid ID) is wrong, the body parameter is never used, and encodeURIComponent should be used (instead of escape).
Not sure if this is a typo or not:
result = request.executeQuery("SELECT user.login, user.email "
+ "FROM user " + );
It looks like you are missing the end of your statement.
Hmmmm, your function definition:
function sendMail("username","email") {...}
doesn't look like valid JavaScript to me, apart of that, you never call the function.
Pseudocode, how to do it:
function sendMail(username, email) {
var link = "jadajada" + email; // .... etc
}
sendMail("+username+","+email+");

evaluation of parameter value in Seam

In a f:attribute I use to calculate the value, but I see it is calculated only when it is called.
I need to specify the value using variable consumed during the visualization, so if it asks for the value not during the production of the component where the f:attribute refer, the value will be not correct.
I hope correctly specify my problem. How can I force the evaluation of attribute value?
Thanks if someone answer me!
The xhtml is:
<rich:scrollableDataTable
value="#{myBean.getScrollData(frm,sez)}"
var="eachRow"
rows="20"
>
<rich:columns value="#{sez.getElements()}" var="info"
index="index" sortable="false"
>
<h:inputText id="txtf#{info.getId()}" value="#{eachRow.data[info]}"
valueChangeListener="#{myBean.handle}"
>
<f:attribute name="xxx" value="#{eachRow.getId()}"/>
</h:inputText>
</rich:columns>
</rich:scrollableDataTable>
the myBean java is:
public void handle(ValueChangeEvent e){
Object value = e.getNewValue();
if ((value==null || value.equals("")) && e.getOldValue()==null) return;
String xxx = e.getComponent().getAttributes().get("xxx").toString();
System.out.println("handle("+xxx+","+value+")");
}
the ScrollData java is:
private String id="";
public String getId(){ return id;}
id is a property of ScrollData read from DB.
I see the xxx value is inspected only during post, so the eachRow is positioned on the last record of the table... and it's wrong.
This mechanism goes ok when not used in DataTable and I see the getId() method is called during the creation of the page (it's correct).
This is expected behaviour. The <f:attribute> is a taghandler which is tied to its single parent UIComponent and processed during view build time. Effectively, when the JSF UI components are to be parsed based on XHTML markup, all taghandlers are evaluated and applied. In your case, the JSF component tree contains only one <h:inputText> component which is reused during every row iteration during the view render time. The <f:attribute> is not re-evaluated during the view render time. So it holds still only the value which was available during the view build time, i.e. it contains null.
There are several ways to achieve the functional requirement anyway, one of them is to just evaluate #{eachRow} programmatically by Application#evaluateExpressionGet() in the value change listener method.
public void handle(ValueChangeEvent e) {
FacesContext context = FacesContext.getCurrentInstance();
EachRow eachRow = context.getApplication().evaluateExpressionGet(context, "#{eachRow}", EachRow.class);
// ...
}
See also:
JSTL in JSF2 Facelets... makes sense? (the same answer applies to <f:attribute>).
How can I pass selected row to commandLink inside dataTable?

Simple way to use parameterised UI messages in Wicket?

Wicket has a flexible internationalisation system that supports parameterising UI messages in many ways. There are examples e.g. in StringResourceModel javadocs, such as this:
WeatherStation ws = new WeatherStation();
add(new Label("weatherMessage", new StringResourceModel(
"weather.${currentStatus}", this, new Model<String>(ws)));
But I want something really simple, and couldn't find a good example of that.
Consider this kind of UI message in a .properties file:
msg=Value is {0}
Specifically, I wouldn't want to create a model object (with getters for the values to be replaced; like WeatherStation in the above example) only for this purpose. That's just overkill if I already have the values in local variables, and there is otherwise no need for such object.
Here's a stupid "brute force" way to replace the {0} with the right value:
String value = ... // contains the dynamic value to use
add(new Label("message", getString("msg").replaceAll("\\{0\\}", value)));
Is there a clean, more Wicket-y way to do this (that isn't awfully much longer than the above)?
Take a look at Example 4 in the StringResourceModel javadoc - you can pass a null model and explicit parameters:
add(new Label("message",
new StringResourceModel(
"msg", this, null, value)));
msg=Value is {0}
I think the most consistent WICKETY way could be accomplished by improving Jonik's answer with MessageFormat:
.properties:
msg=Saving record {0} with value {1}
.java:
add(new Label("label", MessageFormat.format(getString("msg"),obj1,obj2)));
//or
info(MessageFormat.format(getString("msg"),obj1,obj2));
Why I like it:
Clean, simple solution
Uses plain Java and nothing else
You can replace as many values as you want
Work with labels, info(), validation, etc.
It's not completely wickety but it is consistent with wicket so you may reuse these properties with StringResourceModel.
Notes:
if you want to use Models you simply need to create a simple model that override toString function of the model like this:
abstract class MyModel extends AbstractReadOnlyModel{
#Override
public String toString()
{
if(getObject()==null)return "";
return getObject().toString();
}
}
and pass it as MessageFormat argument.
I don't know why Wicket does not support Model in feedback message. but if it was supported there was no reason to use these solutions and you could use StringResourceModel everywhere.
There's a way, which although still involves creating a model, doesn't requires a bean with a getter.
given this message in a properties file:
msg=${} persons
Here's how to replace the placeholder with a value, be it a local variable, a field or a literal:
add(new Label("label", new StringResourceModel("msg", new Model<Serializable>(5))));
When faced with something like described in the question, I would now use:
.properties:
msg=Saving record %s with value %d
Java:
add(new Label("label", String.format(getString("msg"), record, value)));
Why I like it:
Clean, simple solution
Uses plain Java and nothing else
You can replace as many values as you want (unlike with the ${} trick). Edit: well, if you actually need to support many languages where the replaced values might be in different order, String.format() is no good. Instead, using MessageFormat is a similar approach that properly supports this.
Disclaimer: this is "too obvious", but it's simpler than the other solutions (and definitely nicer than my original replaceAll() hack). I originally sought for a "Wicket-y" way, while this kinda bypasses Wicket—then again, who cares? :-)
In case you have a Model in your Component which holds an object with values you want to access from your placeholders as substitutions, you can write:
new StringResourceModel("salutation.text", getModel());
Let's imagine getModel()'s return type is IModel<User> and User contains fields like firstName and lastName. In this case you can easily access firstName and lastName fields inside your property string:
salutation.text=Hej ${firstName} ${lastName}, have a nice day!
Further information you can find here: https://ci.apache.org/projects/wicket/apidocs/8.x/org/apache/wicket/model/StringResourceModel.html#StringResourceModel-java.lang.String-org.apache.wicket.model.IModel-
Creating a Model for your Label really is The Wicket Way. That said, you can make it easy on yourself with the occasional utility function. Here's one I use:
/**
* Creates a resource-based label with fixed arguments that will never change. Arguments are wrapped inside of a
* ConvertingModel to provide for automatic conversion and translation, if applicable.
*
* #param The component id
* #param resourceKey The StringResourceModel resource key to use
* #param component The component from which the resourceKey should be resolved
* #param args The values to use for StringResourceModel property substitutions ({0}, {1}, ...).
* #return the new static label
*/
public static Label staticResourceLabel(String id, String resourceKey, Component component, Serializable... args) {
#SuppressWarnings("unchecked")
ConvertingModel<Serializable>[] models = new ConvertingModel[args.length];
for ( int i = 0; i < args.length; i++ ) {
models[i] = new ConvertingModel<Serializable>( new Model<Serializable>( args[i] ), component );
}
return new CustomLabel( id, new StringResourceModel( resourceKey, component, null, models ) );
}
Details I'm glossing over here are:
I've created my own ConvertingModel which will automatically convert objects to their String representation based on the IConverters available to the given component
I've created my own CustomLabel that applies custom label text post-processing (as detailed in this answer)
With a custom IConverter for, say, a Temperature object, you could have something like:
Properties key:
temperature=The current temperature is ${0}.
Page.java code:
// Simpler version of method where wicket:id and resourceKey are the same
add( staticResourceLabel( "temperature", new Temperature(5, CELSIUS) ) );
Page.html:
<span wicket:id='temperature'>The current temperature is 5 degrees Celsius.</span>
The downside to this approach is that you no longer have direct access to the Label class, you can't subclass it to override isVisible() or things like that. But for my purposes it works 99% of the time.

Categories

Resources