0
votes

In my QA environment, the hybrid Android app does not connect to the MFP server.
On my local machine, using the MFP CLI tooling, the app connects without issue.
In my QA environment, the hybrid iPhone app connects to the MFP server.

The callback on the failed WL.Client.connect() gets this error object:

{
  "status": 403
}

Here is the stack trace from the error handler:

08-25 14:31:56.016: D/CordovaLog(27971): file:///android_asset/www/default/assets/js/dependencies.js: Line 23 : trace: Error
08-25 14:31:56.016: D/CordovaLog(27971):     at Object.connectionFailure [as onFailure] (file:///android_asset/www/default/assets/js/dependencies.js:23:190)
08-25 14:31:56.016: D/CordovaLog(27971):     at onFailureResetSettings (file:///android_asset/www/default/worklight/worklight.js:8251:12)
08-25 14:31:56.016: D/CordovaLog(27971):     at onInitFailure (file:///android_asset/www/default/worklight/worklight.js:8245:4)
08-25 14:31:56.016: D/CordovaLog(27971):     at Object.onFailure (file:///android_asset/www/default/worklight/worklight.js:951:20)
08-25 14:31:56.016: D/CordovaLog(27971):     at klass.window.WLJSX.Ajax.WLRequest.WLJSX.Class.create.onFailure (file:///android_asset/www/default/worklight/worklight.js:3650:26)
08-25 14:31:56.016: D/CordovaLog(27971):     at klass.window.WLJSX.Ajax.WLRequest.WLJSX.Class.create.onWlFailure (file:///android_asset/www/default/worklight/worklight.js:3599:12)
08-25 14:31:56.016: D/CordovaLog(27971):     at Object.<anonymous> (file:///android_asset/www/default/worklight/worklight.js:3437:27)
08-25 14:31:56.016: D/CordovaLog(27971):     at Object.<anonymous> (file:///android_asset/www/default/worklight/wljq.js:1202:33)
08-25 14:31:56.016: D/CordovaLog(27971):     at fire (file:///android_asset/www/default/worklight/wljq.js:1047:30)
08-25 14:31:56.016: D/CordovaLog(27971):     at Object.self.fireWith [as rejectWith] (file:///android_asset/www/default/worklight/wljq.js:1158:7)

I don't see anything in the server logs about a rejected connection request.

I'm calling WL.Client.connect() from the success handler of my WL.Client.init() call, which is itself called on the window load event.

(NOTE: based on comments below I've changed to calling connect() from wlCommonInit() but there's no change ... the stack trace above is from that scenario)

Here is the code doing the connect:

(function () {
  'use strict';

  angular
    .module('myng-worklight', [])
    .run(WorklightRun)

  WorklightRun.$inject = ['$rootScope', '$q'];

  /**
  * Load worklight
  */
  function WorklightRun($rootScope, $q) {

    // Worklight statuss
    var worklightDeferred = $q.defer();
    $rootScope.worklightPromise = worklightDeferred.promise;
    $rootScope.worklightLoaded = false;
    $rootScope.worklightConnected = false;

    var worklightLoadEvent = null;
    worklightLoadEvent = document.createEvent('CustomEvent');

    // Worklight connect options
    var wlConnectOptions = {
      timeout: 30000,

      onFailure: connectionFailure,

      onSuccess: function () {
        console.log('MFP: Connected');
        $rootScope.worklightConnected = true;
        worklightDeferred.resolve();
      }
    };

    // Worklight init options
    var wlInitOptions = {
      timeout: 10000,

      onConnectionFailure: connectionFailure,

      onFailure: connectionFailure,

      onSuccess: function () {
        console.log('MFP: Loaded');
        $rootScope.worklightLoaded = true;
        if (window.addEventListener) {
          window.addEventListener(WL.Events.WORKLIGHT_IS_CONNECTED, wlConnectedHandler, true);
          window.addEventListener(WL.Events.WORKLIGHT_IS_DISCONNECTED, wlDisconnectedHandler, true);
        } else if (window.attachEvent) {
          window.attachEvent(WL.Events.WORKLIGHT_IS_CONNECTED, wlConnectedHandler);
          window.attachEvent(WL.Events.WORKLIGHT_IS_DISCONNECTED, wlDisconnectedHandler);
        }
        console.log('MFP: About to connect with: ' + JSON.stringify(wlConnectOptions, null, 2));
        WL.Client.connect(wlConnectOptions);
      }
    };
    // we should connect on the cb from init -- output!

    // Listen for load / onload and start worklight init
    if (window.addEventListener) {
      window.addEventListener('load', loadHandler, false);
    } else if (window.attachEvent) {
      window.attachEvent('onload', loadHandler);
    }


    function connectionFailure(err) {
      console.log('MFP: No Connection - ' + JSON.stringify(err, null, 2));
      worklightDeferred.reject(err);
    }

    function loadHandler() {
      try {
        console.log('MFP: Load event detected, about to init with: ' + JSON.stringify(wlInitOptions, null, 2));
        WL.Client.init(wlInitOptions);
      } catch (err) {
        console.error('MFP: "WL" not defined - ' + err);
        connectionFailure();
        worklightLoadEvent.initCustomEvent('worklightLoadFailure', true, false, {});
        window.dispatchEvent(worklightLoadEvent);
      }
    }

    function wlConnectedHandler() {
      $rootScope.worklightConnected = true;
      WL.App.hideSplashScreen();
    }

    function wlDisconnectedHandler() {
      $rootScope.worklightFailureAcknowledged = true;
      $rootScope.worklightConnected = false;
      WL.App.hideSplashScreen();
    }
  }
})();

Possibly this is related to the Android app authenticity settings? (e.g. publicSigningKey in application-descriptor.xml or the customTests in authenticationConfig.xml)

Here is the relevant bit from application-descriptor.xml:

<android securityTest="customTests" version="1.0">
    <worklightSettings include="false"/>
    <pushSender key="XYZ" senderId="123"/>
    <security>
        <encryptWebResources enabled="false"/>
        <testWebResourcesChecksum enabled="false" ignoreFileExtensions="png, jpg, jpeg, gif, mp4, mp3"/>
        <publicSigningKey>MIIBI...</publicSigningKey>
        <packageName>com.MyPackage</packageName>
    </security>
</android>

And from authenticationConfig.xml:

<customSecurityTest name="customTests">
  <test realm="wl_antiXSRFRealm" step="1" />
  <test realm="wl_authenticityRealm" step="1" />
  <test realm="wl_remoteDisableRealm" step="1" />
  <test realm="wl_directUpdateRealm" mode="perSession" step="1" />
  <test realm="wl_anonymousUserRealm" isInternalUserID="true" step="1" />
  <test realm="wl_deviceNoProvisioningRealm" isInternalDeviceID="true" step="2" />
</customSecurityTest>
1
Calling connect from the success handler of init?! Who told you to do it that way? Please add your implementation. - Idan Adar
@IdanAdar - it looked like we were having race conditions between the init() completing and the call to connect(). How should we do a manual call to connect() ? - N2O
This is not the implementation code I asked for. Add the code where you do the connect. - Idan Adar
I'll add that too ... given that I'm seeing a 403 now, I thought it might have to do with the app authenticity config. Still, I'll add the other code. - N2O
MFP code should run once wlCommonInit is called, which is where the WL.Client.connect method should be, and not be used directly via WL.Client.init. Please, next time do mention all of details at once, like the fact you're using authenticity and implement your app the way you did, we can't read your mind and know this... - Idan Adar

1 Answers

0
votes

IMO this is wrong.

You should not call WL.Client.connect in this manner.
Worklight API should be called inside the wlCommonInit() function, located in the common\main.js file, and not from the common\initOptions.js file.

Look at the various sample applications provided at the Developer Center. None of them are implemented in this manner... (it doesn't matter the samples are for 7.1 and you're using 6.2, as the concept is the same).

All of the onSuccess should not be done that way;