Worklight Direct Update and run offline - ibm-mobilefirst

I want to achieve such a functionality.
That is:
1) in case of connecting to worklight server successfully, Direct Update is available.
2) in case of failing to connect to worklight server, the app can run offline.
Below is my configuration in "initOptions.js".
// # Should application automatically attempt to connect to Worklight Server on application start up
// # The default value is true, we are overriding it to false here.
connectOnStartup : true,
// # The callback function to invoke in case application fails to connect to Worklight Server
onConnectionFailure: function (){
alert("onConnectionFailure");
doDojoReady();
},
// # Worklight server connection timeout
timeout: 10 * 1000,
// # How often heartbeat request will be sent to Worklight Server
heartBeatIntervalInSecs: 20 * 60,
// # Should application produce logs
// # Default value is true
//enableLogger: false,
// # The options of busy indicator used during application start up
busyOptions: {text: "Loading..."
But it doesn't work.
Any idea?

Direct Update happens only when a connection to the server is available. From the way you phrased your question, your problem is that when the app cannot connect to the server it doesn't work "offline". So your question has got nothing to do with Direct Update (if it does, re-phrase your question appropriately).
What you should do, is read the training material for working offline in Worklight.
You are not specifying what "doesn't work". Do you get the alert you've placed in onConnectionFailure? How does your doDojoReady function look like?

I too am using Dojo in Worklight.
My practice is have worklight configured not to connect on startup
var wlInitOptions = {
connectOnStartup : false
in my wl init I then initialise my dojo app,
function wlCommonInit(){
loadDojoLayers();
};
requiring whatever layers I'm using, and then do the actual dojo parsing
require([ "dojo/parser",
"myApp/appController",
"dojo/domReady!"
],
function(parser, appController) {
parser.parse().then (function(){
appController.init();
});
});
Finally, now WL, Dojo, and myApp are all ready I attempt the WL connection, calling this method from my appController.init()
connectWLServer: function() {
// possibly WL.Client.login(realm) here
var options = {
onSuccess: lang.hitch(this, "connectedWLServer"),
onFailure: lang.hitch(this, "connectWLServerFailed"),
};
WL.Client.connect(options);
}
Any Direct Update activities happen at this point. Note that the app as whole keeps going whether or not the connection works, but clearly we can run appropriate code in success and fail cases. Depending upon exactly what authentication is needed an explicit login call may be needed - adapter-based authentication can't happen automatically from inside the connect().

Related

Why is the Azure App Configuration feature flag not found?

Azure Functions app, runtime v3.
The application has a FunctionsStartup class that first enables Azure App Configuration in its ConfigureAppConfiguration method:
builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
{
options
.Connect(appConfigurationConnectionString)
.UseFeatureFlags();
});
And in its Configure method it enables feature management, and it adds the Azure App Configuration services (so we can refresh settings at runtime):
builder.Services
.AddAzureAppConfiguration()
.AddFeatureManagement()
.AddFeatureFilter<ContextualTargetingFilter>();
On the Azure Portal there is a feature flag, which is enabled, called CardExpirationNotice. The code uses IFeatureManagerSnapshot to check if the feature is enabled:
feature = nameof(Features.CardExpirationNotice);
var isEnabled = await _featureManagerSnapshot.IsEnabledAsync(feature);
isEnabled is false, and this log message is output:
The feature declaration for the feature 'CardExpirationNotice' was not found.
I tried configuring a flag locally in local.settings.json:
"FeatureManagement__CardExpirationNotice": true
Then isEnabled is true, so I can narrow the problem to Azure App Configuration, and exclude the feature management implementation.
As it turns out, when you add a feature flag in Azure App Configuration, you can set a label. But if you do that, then you need to specify that label in your code as well:
builder.ConfigurationBuilder.AddAzureAppConfiguration(options =>
{
options
.Connect(appConfigurationConnectionString)
.UseFeatureFlags(options => options.Label = "payments");
});

Paho Rabitmqq connection getting failed

Here is my paho client code
// Create a client instance
client = new Paho.MQTT.Client('127.0.0.1', 1883, "clientId");
// set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
// connect the client
client.connect({onSuccess:onConnect});
// called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect");
client.subscribe("/World");
message = new Paho.MQTT.Message("Hello");
message.destinationName = "/World";
client.send(message);
}
// called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage);
}
}
// called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString);
}
On Rabbitmq server everything is default seetings. When i run this code i get WebSocket connection to 'ws://127.0.0.1:1883/mqtt' failed: Connection closed before receiving a handshake response
What i am missing ?
From my personal experience with Paho MQTT JavaScript library and RabbitMQ broker on windows, here is a list of things that you need to do to be able to use MQTT from JS from within a browser:
Install rabbitmq_web_mqtt plugin (you may find latest binary here, copy it to "c:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.2\plugins\", and enable from command line using "rabbitmq-plugins enable rabbitmq_web_mqtt".
Of course, MQTT plugin also needs to be enabled on broker
For me, client was not working with version 3.6.1 of RabbitMQ, while it works fine with version 3.6.2 (Windows)
Port to be used for connections is 15675, NOT 1883!
Make sure to specify all 4 parameters when making instance of Paho.MQTT.Client. In case when you omit one, you get websocket connection error which may be quite misleading.
Finally, here is a code snippet which I tested and works perfectly (just makes connection):
client = new Paho.MQTT.Client("localhost", 15675, "/ws", "client-1");
//set callback handlers
client.onConnectionLost = onConnectionLost;
client.onMessageArrived = onMessageArrived;
//connect the client
client.connect({
onSuccess : onConnect
});
//called when the client connects
function onConnect() {
console.log("Connected");
}
//called when the client loses its connection
function onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:" + responseObject.errorMessage);
}
}
//called when a message arrives
function onMessageArrived(message) {
console.log("onMessageArrived:" + message.payloadString);
}
It's not clear in the question but I assume you are running the code above in a web browser.
This will be making a MQTT connection over Websockets (as shown in the error). This is different from a native MQTT over TCP connection.
The default pure MQTT port if 1883, Websocket support is likely to be on a different port.
You will need to configure RabbitMQ to accept MQTT over Websockets as well as pure MQTT, this pull request for RabbitMQ seams to talk about adding this capability. It mentions that this capability was only added in version 3.6.x and that the documentaion is still outstanding (as of 9th Feb 2016)

Enable/Disable logging in Worklight application

We are developing a WL application using WL enterprise 6.2.0.1. We have four environments (Dev/QA/UAT and PROD).
Our application is logging the user credentials on the Server (file:SystemOut.log) which is ok for Dev environment. However, when we need to move the build to QA and UAT we need to disable the logging since it is a security point of view and we can't proceed to PROD.
What we did is we added the following code to the initOptions.js:
var bEnableConsoleLog = false; // Enable Disable the logging
var wlInitOptions = {
...
...
...
logger : {
enabled : bEnableConsoleLog},};
var disableLogging = function() {
WL.Logger.info("##### LOG ENABLED ?? => " + bEnableConsoleLog);
if (bEnableConsoleLog == false)
{
WL.Logger.config({
enabled : false,
level : 'info'
});
console.log = function() {
}.bind(console.log);
console.error = function() {
}.bind(console.error);
}
};
if (window.addEventListener) {
window.addEventListener('load', function() {
WL.Client.init(wlInitOptions);
disableLogging();
}, false);
} else if (window.attachEvent) {
window.attachEvent('onload', function() {
WL.Client.init(wlInitOptions);
disableLogging();
});
}
disableLogging();
WL.Logger
.info("######################## WL.Logger.info ENABLED ############################");
console
.log("######################## console.log ENABLED ############################");
console
.error("######################## console.error ENABLED ############################");
By Setting the value var bEnableConsoleLog = (true/false); we thought we can enable or disable the logging, but it seems still logging the credentials.
Is there a way to resolve this?
I don't think there is an 'enabled' option on WL.Logger.config based on the WL.Logger API reference. There is a 'capture' option which you can set to false, which will disable saving the client logs and sending them to the server.
If your client is logging the user credentials in a log statement then that information should only be sent based on 'capture' being true (the default) and the log statement you use being at the 'level' value or above. Given your WL.Logger.config() above, that means WL.Logger.info() would be sent to the server and WL.Logger.debug() would not. For more information see Configuring the Worklight Logger.
Note that all of this pertains only to WL.Logger calls made by the client. If you are logging the user credentials in your server-side code (for example using Java logger) then what is logged will be based on the log levels configured on the server; the client log configuration will have no effect.

IBM Worklight 5.0.6.1 - onFailure and onSuccess execution at Client.connect() and invokeProcedure() NOT exclusive when timeout?

We are seeing a surprising scenario when we are on a slow network connection and our calls to the WL Server time out.
This happens at WL.Client.connect as well as on invokeProcedure:
we execute the call with a timeout of 10 seconds
the network connection is slow so the call times out
the defined onFailure procedure associated to that call is executed
the WL Server responds with a valid response after the timeout
the onSuccess procedure associated to that call is executed
Is this the designed and intended behavior of the WL Client Framework? Is this specified in the InfoCenter documentation or somewhere?
All developers in our team expected these two procedures to be exclusive and our code was implemented based on this assumption. We are now investigating options on how to match a timed-out/failed response to a success response to make sure we achieve an exclusive execution of onFailure or onSuccess code/logic in our app.
Note: we did not test that with connectOnStartup=true and since the initOptions does not provide an onSuccess procedure (since WL handles that internally) it might be even harder to implement an exclusive execution in this case.
That seems like expected behavior, but don't quote me on that.
You can get the behavior you want (only call the failure callback when it fails, and only call the success callback when it succeeds) using jQuery.Deferreds. There are ways of creating these deferred objects with dojo and other libraries. But, I just tested with jQuery's implementation, which is shipped with every version of IBM Worklight.
$(function () {
var WL = {};
WL.Client = {};
WL.Client.invokeProcedureMock = function (options) {
options.onFailure('failure');
options.onSuccess('success');
};
var dfd = $.Deferred();
var options = {
onSuccess: dfd.resolve,
onFailure: dfd.reject
};
WL.Client.invokeProcedureMock(options);
dfd
.done(function (msg) {
// handle invokeProcedure success
console.log(msg);
})
.fail(function (msg) {
//handle invokeProcedure failure
console.log(msg);
});
});
I put the code above in a JSFiddle, notice that even if I call the onSuccess callback, it won't have any effect because I already called the failure callback (which rejected the deferred). You would add your application logic inside the .done or .fail blocks.
This is just a suggestion, there are likely many ways to approach your issue.

Apache + Symfony2 + HTTPS + Node.js + Socket.io: socket.emit not firing

I've been spending hours upon hours on this problem, but to no avail.
EDIT: solution found (see my answer)
Project background
I'm building a project in Symfony2, which requires a module for uploading large files. I've opted for Node.js and Socket.IO (I had to learn it from scratch, so I might be missing something basic).
I'm combining these with the HTML5 File and FileReader API's to send the file in slices from the client to the server.
Preliminary tests showed this approach working great as a standalone app, where everything was handled and served by Node.js, but integration with Apache and Symfony2 seems problematic.
The application has an unsecured and secured section. My goal is to use Apache on ports 80 and 443 for serving the bulk of the app built in Symfony2, and Node.js with Socket.io on port 8080 for file uploads. The client-side page connecting to the socket will be served by Apache, but the socket will run via Node.js. The upload module has to run over HTTPS, as the page resides in a secured environment with an authenticated user.
The problem is events using socket.emit or socket.send don't seem to work. Client to server, or server to client, it makes no difference. Nothing happens and there are no errors.
The code
The code shown is a simplified version of my code, without the clutter and sensitive data.
Server
var httpsModule = require('https'),
fs = require('fs'),
io = require('socket.io');
var httpsOptions =
{
key: fs.readFileSync('path/to/key'),
cert: fs.readFileSync('/path/to/cert'),
passphrase: "1234lol"
}
var httpsServer = httpsModule.createServer(httpsOptions);
var ioServer = io.listen(httpsServer);
httpsServer.listen(8080);
ioServer.sockets.on('connection', function(socket)
{
// This event gets bound, but never fires
socket.on('NewFile', function(data)
{
// To make sure something is happening
console.log(data);
// Process the new file...
});
// Oddly, this one does fire
socket.on('disconnect', function()
{
console.log("Disconnected");
});
});
Client
// This is a Twig template, so I'll give an excerpt
{% block javascripts %}
{{ parent() }}
<script type="text/javascript" src="https://my.server:8080/socket.io/socket.io.js"></script>
<script type="text/javascript">
var socket = io.connect("my.server:8080",
{
secure: true,
port: 8080
});
// Imagine this is the function initiating the file upload
// File is an object containing metadata about the file like, filename, size, etc.
function uploadNewFile(file)
{
socket.emit("NewFile", item);
}
</script>
{% endblock %}
So the problem is...
Of course there's much more to the application than this, but this is where I'm stuck. The page loads perfectly without errors, but the emit events never fire or reach the server (except for the disconnect event). I've tried with the message event on both client and server to check if it was a problem with only custom events, but that didn't work either. I'm guessing something is blocking client-server communication (it isn't the firewall, I've checked).
I'm completely at a loss here, so please help.
EDIT: solution found (see my answer)
After some painstaking debugging, I've found what was wrong with my setup. Might as well share my findings, although they are (I think) unrelated to Node.js, Socket.IO or Apache.
As I mentioned, my question had simplified code to show you my setup without clutter. I was, however, setting up the client through an object, using the properties to configure the socket connection. Like so:
var MyProject = {};
MyProject.Uploader =
{
location: 'my.server:8080',
socket: io.connect(location,
{
secure: true,
port: 8080,
query: "token=blabla"
}),
// ...lots of extra properties and methods
}
The problem lay in the use of location as a property name. It is a reserved word in Javascript and makes for some strange behaviour in this case. I found it strange that an object's property name can't be a reserved word, so I decided to test. I had also noticed I was referencing the property incorrectly, I forgot to use this.location when connection to the socket. So I changed it to this, just as a test.
var MyProject = {};
MyProject.Uploader =
{
location: 'my.server:8080',
socket: io.connect(this.location,
{
secure: true,
port: 8080,
query: "token=blabla"
}),
// ...lots of extra properties and methods
}
But to no avail. I was still not getting data over the socket. So the next step seemed logical in my frustration-driven debugging rage. Changing up the property name fixed everything!
var MyProject = {};
MyProject.Uploader =
{
socketLocation: 'my.server:8080',
socket: io.connect(this.socketLocation,
{
secure: true,
port: 8080,
query: "token=blabla"
}),
// ...lots of extra properties and methods
}
This approach worked perfectly, I was getting loads of debug messages. SUCCESS!!
Whether it is expected behaviour in Javascript to override (or whatever is happening here, "to misuse" feels like a better way of putting it to me right now) object properties if you happen to use a reserved word, I don't know. I only know I'm steering clear of them from now on!
Hope it helps anyone out there!