.gitignore for Worklight

29 Sep

I have recently started maintaining a .gitignore template file for IBM Worklight Foundation on github, in a similar spirit to the standard gitignore repository. Please feel free to take a look; just copy the Worklight.gitignore file into the root of your Worklight project, and rename it to .gitignore – then you’re ready to go.

It’s unofficial, and possibly not complete/accurate, so caveat emptor – any pull requests for fixes or enhancements will be gladly received.

Transforming worklight.properties values in JNDI properties suitable for insertion into a Liberty server.xml

16 Sep

If you’re working with a Worklight application, you might like to exploit the fact that Worklight allows you to programmatically retrieve custom values from the worklight.properties file defined in your Worklight project. For example, you can write code like this:

function myAdapterProcedure(opt1, opt2) {
  var path = WL.Server.configuration["myadapter.path"];

  var input = {
    method: 'get',
    path: path
  }

  WL.Server.invokeHttp(input);
}

Your worklight.properties might look like:

myadapter.path=/myserver/somepath/service

This is quite useful, but becomes even more useful when combined with the fact that Worklight allows you to override the worklight.properties values with JNDI properties defined on the server. This enables you to easily automate having different values for these properties on different development environments – for example, to connect to different backend servers.

Assuming you are using WebSphere Liberty, here’s a Perl one-liner that you can use to transform a worklight.properties file into the equivalent JNDI properties definitions, suitable for inserting into the server.xml for Liberty:

cat worklight.properties.$ENVIRONMENT | grep  "^\w" | perl -p -i -e 's/((?:\w+\.)*(?:\w+.))=(.*)/<property name="$1" value="$2"\/>/g' > $TEMPFILE

$TEMPFILE will now contain your transformed properties, which will look like these:

<property name="myadapter.path" value="/myserver/somepath/service"/>

This is suitable for directly inserting into your Liberty server’s server.xml.

Custom expiry times for Mongoose documents in Node.js

10 Sep

If you’re using MongoDB and Mongoose in your Node.js application, perhaps on IBM Bluemix, you may need to expire (delete) documents documents at a set time.

The Mongoose documentation includes instructions for creation of a schema-level expiry time, with all documents expiring a set number of seconds after their creation.

However, it doesn’t explain how to specify a specific expiry time for an individual document.

Here’s a snippet of how to do this:

var mongoose = require('mongoose');

// Define our token schema
var ThingSchema = new mongoose.Schema({
	value: {
		type: String, 
		required: true
	},
	expireAt: {
		type: Date,
		required: true
	}
});

// Expire at the time indicated by the expireAt field
ThingSchema.index({ expireAt: 1 }, { expireAfterSeconds : 0 });

var model = mongoose.Model('Thing', ThingSchema);

You can set validation and defaults on the expireAt field, too:

	expireAt: {
		type: Date,
		validate: [ function(v) {
			return (v - new Date()) <= 60000;
		}, 'Cannot expire more than 60 seconds in the future.' ],
		default: function() {
			// 60 seconds from now
			return new Date(new Date().valueOf() + 60000);
		}
	}

One gotcha – the MongoDB expiry reaper only runs once a minute. This means a document could remain in the DB up to 60 seconds after it has expired. You should write your code to allow for this.

Where do I specify the hostname of my Worklight server?

26 May

When developing a Worklight application, there are various places the hostname of your Worklight server might need to be specified, and might end up:

  • In the mobile app itself (the .ipa, .apk etc.) – this value (prior to Worklight V6) was taken from the application-descriptor.xml file during the build of the application and determines where the app attempts to connect back to for adapter calls and so on. In versions of Worklight subsequent to V6, it is now specified instead in the <app-builder> ANT task (used for automated builds of the application) inside the worklightServerHost property.
  • In the publicWorkLightHostname, publicWorkLightProtocol, and publicWorkLightPort values inside the worklight.properties file. These values determine:
    • Where the Mobile web and desktop browser apps should connect back to.
    • How the Worklight Application Center (if used) will form RESTful URLs for its own internal use.

In all cases, these hostnames should point to the externally-resolvable address of the Worklight server (in front of any load-balancers, firewalls, proxies, etc.).

Thanks to Itay Hindy and Thomas Kw Poon for help with this tip.

Enabling WebView remote debugging in KitKat

26 Feb

My current application is targeting multiple versions of Android, but I’d also like to enable the remote debugging features of KitKat’s new WebView. This creates a problem when trying to maintain API compatibility, as the methods to enable debugging don’t exist on older versions of Android.

Here’s the snippet of code I’m now using to get around this problem – it leverages Java’s reflection API to allow us to enable debugging, but only if it’s available on the platform. Make sure you augment your Android application’s main Java file correctly.

public class CustomerView extends WLDroidGap {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);		
        
        // Enable remote debugging, if available! - KitKat or more
        if (Build.VERSION.SDK_INT >= 19) {
            if (0 != (getApplicationInfo().flags = ApplicationInfo.FLAG_DEBUGGABLE)) {
                try {
                    Method m = WebView.class.getMethod("setWebContentsDebuggingEnabled", boolean.class);
                    m.invoke(null, true);
                } catch (Exception e) {
                    // Oh well
                }
            }
        }
    }
    
}

How to make your generated widget’s DOM IDs reflect their AMD module

14 Nov

In the new AMD world, it’s suggested that we omit the specification of a “declaredClass” in our custom widget’s declare() call, like so:

define(["dijit/_WidgetBase"], function(_WidgetBase) {
    return declare([_WidgetBase], { 

    })
});

However, in this case, _WidgetBase doesn’t have a specified value for declaredClass, and uses the declaredClass from an appropriate parent class to automatically generate a DOM ID.

I’ve worked around this so far by using a pattern like this:

define(["module", "dijit/_WidgetBase"], function(module, _WidgetBase) {
    return declare(module.id, [_WidgetBase], { 

    })
});

Hopefully we’ll see some fixes from Dojo here to make this easier in future.

Destroy all widgets/dijits in a DOM node

31 Oct

Following up on Tom’s post from 2011, and taking into account the comments posted, here is the latest “known good” technique.

Often we need to empty a DOM node of all widgets. Here’s the magic incantation.

require(["dijit/registry", "dojo/dom-construct", 
        "dojo/_base/array"], 
        function(registry, domConstruct, array) {

    // Your DOM node reference goes here
    var node = null; 

    // Destroy the widgets, including their
    // children and DOM fragments
    array.forEach(registry.findWidgets(node), 
        "item.destroyRecursive()");

    // OPTIONAL: Explicitly empty the node.
    // This will take care of DOM nodes that 
    // weren't managed by widgets
    domConstruct.empty(node);

});
Follow

Get every new post delivered to your Inbox.

Join 83 other followers