I've tried to use setTimeout in Worklight adapter procedure. It doesn't work.
WLSE0099E: An error occurred while invoking procedure [project BusinessBank]PushAdapter/submitNotificationFWLSE0100E: parameters: [project BusinessBank]
ReferenceError: "setTimeout" is not defined. (PushAdapter-impl.js#37)
I need to hold sending the push notification after invoking adapter procedure. It's need for the demo. My code example:
WL.Server.createEventSource({
name: 'PushEventSource',
onDeviceSubscribe: 'deviceSubscribeFunc',
onDeviceUnsubscribe: 'deviceUnsubscribeFunc',
securityTest:'AngularStarter-strong-mobile-securityTest'
});
function deviceSubscribeFunc(userSubscription, deviceSubscription){}
function deviceUnsubscribeFunc(userSubscription, deviceSubscription){}
function submitNotification(userId, notificationText) {
var userSubscription = WL.Server.getUserNotificationSubscription('PushAdapter.PushEventSource', userId);
if (userSubscription == null) {
return { result: "No subscription found for user :: " + userId };
}
var badgeDigit = 1,
notification = WL.Server.createDefaultNotification(notificationText, badgeDigit, {custom: "data"});
setTimeout(function() {
WL.Logger.debug("submitNotification >> userId :: " + userId + ", text :: " + notificationText);
WL.Server.notifyAllDevices(userSubscription, notification);
},5000);
return {
result: "Notification sent to user :: " + userId
};
}
If you're actually about about JavaScript method setTimeout, it will help if you'll add some code example of what exactly you're trying to do, given this is a programming Q&A website and all.
If you're demoing your app using Worklight Studio, there is no need to implement a timeout.
Open the app, login, subscribe to notifications, close the app. Then, right-click on the adapter and select Run As > Invoke Worklight procedure and add a username in text (for example: "myuser","mytext"). And that's it... the notification will be sent. Whenever you want it to be sent.
Otherwise,
There is no such thing as setTimeout for an adapter procedure...
See here: How to increase the adapter procedure timeout value in Worklight?
To set a timeout to a procedure, in the adapter XML file:
<procedure name="nameHere" requestTimeoutInSeconds="valueHere"/>
Please review the IBM Worklight Knowledge Center and training modules.
setTimeout API belongs to a global window object. basically using it the way you do is a shortcut to window.setTimeout().
Since adapter is not a browser but a server runnable code it doesn't have a global window object, therefore you have no setTimeout API.
Related
I have two Worklight apps an one SQL-adapter in one project. the first app is the client app and works perfectly well. the second one is the the managment app which is using the same SQL-Adapter. they also call the same procedure, which makes a SQL-statement and returns the results. But when initializing the procedure from the controller app I am getting an error:
TypeError: invalid 'in' operand profile worklight.js:4039
Adapter-Procedure:
var selectStatement = WL.Server.createSQLStatement("select TITLE, BODY, DATE from MESSAGES where DATE>?");
function getMessages(param1) {
return WL.Server.invokeSQLStatement({
preparedStatement : selectStatement,
parameters : [param1]
});
}
Call from the Controller:
function getMessages(){
console.log("lala");
var invocationData = {
adapter : 'ClientAdapter',
procedure : 'getMessages',
parameters: ['2014-07-21 00:00:00.000000']
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : success,
onFailure : failure
});
function success(result){
console.log("Successfully gathered Messages");
}
function failure(ErrorObject){
console.log("ERROR: could not get Messages/n" + ErrorObject);
}
}
I don't get how there can be an error there because i never touch that file (to be honest: I don't even know where it's located in my Project) and in the web inspector it looks the same in both apps.
The only difference is that I'm using Bootstrap in the contorller app instead of jquery mobile.
Any ideas how to fix it or work around?
Sincerely
Max
EDIT: Added code
I am able to create a worklight adapter, deploy it and invoke it by passing the parameter manually, but i need to create a login page where when the user enters the credentials, the application should get the his/her data from the tables by passing his username in the where clause of the query SELECT * FROM USER_ACC_TABLE WHERE USER = ?
How do I programmatically pass the parameters for a query in worklight adapters?
If you look at the docs, you will see that the invocation process includes a parameters key. In your case, I would use a JSON object as shown.
http://www-01.ibm.com/support/knowledgecenter/SSZH4A_6.2.0/com.ibm.worklight.apiref.doc/html/refjavascript-client/html/WL.Client.html%23invokeProcedure
function invokeAdapter(USERNAME) {
var USERINFO = {username: USERNAME};
var invocationData = {
adapter: "USER_ACCT_TABLE",
procedure: "getUserData",
parameters:[USERINFO]
};
// DEFINE THE CALL BACK FUNCTIONS
var options = {
onSuccess: onSuccess,
onFailure: onFailure
};
WL.Client.invokeProcedure(invocationData, options);
}
In your adapter code, you would have something like the following:
var selectStatement = WL.Server.createSQLStatement("SELECT * FROM USER_ACC_TABLE WHERE USER = ?");
function getUserData(data) {
var USERNAME = data.username;
return WL.Server.invokeSQLStatement({
preparedStatement : selectStatement,
parameters : [USERNAME]
});
}
If I understand you correctly, you'd like to get the values that the user will input in the login form's text fields and use them in your adapter request?
Maybe the answer the following question will help: Passing parameters through HTTP Adapter?
While it explains it for HTTP adapter, the JavaScript part of getting the values should be the same.
Basically, you use the following the get the value from the input field. You could save it in a variable just as well:
parameters : [$('#element-name').val()]
Full example is available in the linked question.
For passing the value to your SQL query in a SQL adapter, the following answer by jnortey should help: IBM Worklight - Error while using variable in a SQL Adapter query, which is basically the same.
That's it. Now the '?' in the SQL query should get the parameter's value.
pls. is there any idea or suggestion wy call from an SQL adapter to another SQL adapter doesnt work ?
i use WL.Server.invokeProcedure.({adapter : "SQL_Adapter",procedure : "procedure name in the another adapter"}). it seems that function doesnt check the existence of the adapter and procedure parameters and work with any arbitrary string even for non-existing adapter/procedure. Result is always undefined object returned from the call
i am using Worklight 6.1.0.01.20140311-2356 on Windows server
both adapters works fine and are used regularly from client devices
the "server" adapter (MS SQL) is used for push notification and defines event source
the "client" adapter (DB2) is normal one.
there is piece of code:
var result = getAllUsersFromSQLPushNotificationAdapter();
if (result){
WL.Logger.info("test1" + result.isSuccessful); //i got false
WL.Logger.info("test2" + result.errorMessages); //i got undefined
WL.Logger.info("test3 " + result.resultSet); //i got undefined
//result = result["invocationResult"]["resultSet"];
for (var i = 0; i < result.resultSet.length; i++) {
//result[i].Category ";
}
WL.Logger.info("Number of users: " + result.resultSet.length);
}
function getAllUsersFromSQLPushNotificationAdapter(){
return WL.Server.invokeProcedure({
adapter : "CZU_SQL",
procedure : "getAllUsers"});
}
thank you
Try something like below.In getDataSuccess() get the results and use it.
var invocationData = {
adapter : 'ADAPTER_NAME',
procedure : 'PROCEDURE_NAME'
};
WL.Server.invokeProcedure(invocationData,{
onSuccess : getDataSuccess,
onFailure : getDataFailure,
});
For debugging purpose check the Success and failure function results. if you are not able to call another adapter procedure please post the error from failure function.
my procdure in sql adapter is given below
var procedure1Statement = WL.Server.createSQLStatement("select * from userreg ");
function procedure1() {
var resp= WL.Server.invokeSQLStatement({
preparedStatement : procedure1Statement,
parameters : []
});
var a=resp.resultSet;
var name=new Array();
for(var i=0;i<a.length;i++){
name[i]=a[i].name;
}
//return (name);
//alert (name);
console.log( name.toString());
}
if i call this procedure can i display name values in browser console,
or if i use WL.logger.log() instead of console.log
You cannot use console.log in server-side code... you must have code in the client-side that will receive the response from this server-side code (that is - you must return it), and then you could use console.log (and other options) - in the client-side - to print the values to the console in your browser or LogCat or other tools...
What you can do in the case of adapter logging or debugging, is to use WL.Logger.warn or WL.Logger.error to print out to the Eclipse console.
See this question for more information on the above: IBM Worklight 6.0 - How to enable/view WL.Logger.debug in adapters?
When javascript is run in the browser there is no need to try and hide function code because it is downloaded and viewable in source.
When run on the server the situation changes. There are use cases such as api where you want to provide users with functions to call without allowing them to view the code that which is run.
On our specific case we want to execute user submitted javascript inside node. We are able to sandbox node.js api however we would like to add our own api to this sandbox without users being able to toString the function to view the code which is run.
Does anyone have a pattern or know of a way of preventing users from outputting a functions code?
Update:
Here is a full solution (i believe) based on the accepted answer below. Please note that although this is demonstrated using client side code. You would not use this client side as someone can see the contents of your hidden function by simply reading the downloaded code (although it may provide some basic slow down to inspect the code if you have used a minify).
This is meant for server side use where you want to allow users to run api code within a sandbox env but not allow them to view what the api's do. The sandbox in this code is only to demonstrate the point. It is not an actual sandbox implementation.
// function which hides another function by returning an anonymous
// function which calls the hidden function (ie. places the hidden
// function in a closure to enable access when the wraped function is passed to the sandbox)
function wrapFunc(funcToHide) {
var shownFunc = function() {
funcToHide();
};
return shownFunc;
}
// function whose contents you want to hide
function secretFunc() {
alert('hello');
}
// api object (will be passed to the sandbox to enable access to
// the hidden function)
var apiFunc = wrapFunc(secretFunc);
var api = {};
api.apiFunc = apiFunc;
// sandbox (not an actual sandbox implementation - just for demo)
(function(api) {
console.log(api);
alert(api.apiFunc.toString());
api.apiFunc();
})(api);
If you wrap a callback in a function, you can use another function in that scope which is actually hidden from the callback scope, thus:
function hideCall(funcToHide) {
var hiddenFunc = funcToHide;
var shownFunc = function() {
hiddenFunc();
};
return shownFunc;
}
Then run thusly
var shtumCallBack = hideCall(secretSquirrelFunc);
userCode.tryUnwindingThis(shtumCallBack);
The userCode scope will not be able to access secretSquirrelFunc except to call it, because the scope it would need is that of the hideCall function which is not available.