Thursday, August 13, 2015

Make Mac Minecraft work on Oracle Java

My son likes to play Minecraft.  I like to use Oracle Java 8 instead of the decrepit Apple Java (6) that Apple insists on.  Can't Minecraft use Oracle Java 8?

It can but it took me 6 months to figure out how to do it right.  You can modify the Minecraft Mac application so it will work on whatever is installed, either Oracle Java 8 or Apple Java 6.  You can even do it without starting a Terminal (but I'll tell you how to do it in Terminal, too).

On MacOS X Yosemite:

1.  Make a copy of your Minecraft application for backup.

2.  Start Safari and go to this page:

https://raw.githubusercontent.com/tofi86/universalJavaApplicationStub/master/src/universalJavaApplicationStub

This is a bash script from https://github.com/tofi86/universalJavaApplicationStub GitHub project.

3.  Choose the "File" menu, then select the "Save As..." menu item.  Select the "Page Source" item in the "Format" dropdown list.  Now, save it using the default name (i.e. universalJavaApplicationStub) on your Desktop.

4.  Go to the Applications folder, right click on the Minecraft application and select "Show Package Contents".  A Finder window will open.  Double-click on the Contents folder to open it.  Start Finder and choose the "Go" menu, then select the "Go to Folder..." menu item.  Type "/Applications/Minecraft.app/Contents" and press the "Go" button.  A Finder window will open.

5.  Double-click on the MacOS folder.  If it is a Java application, you will probably see a single file named JavaApplicationStub in the MacOS folder.

6.  Drag the universalJavaApplicationStub into the MacOS folder.  Now, there are two files in there.

7.  Right click on universalJavaApplicationStub and select the "Get Info" menu item.  Open the "Name & Extensions" item.

8.  If the "Hide extension" checkbox is enabled and checked, uncheck it.

9.  In the text box, delete the extension (probably ".txt") and close the "Get Info" box.

10.  If you get "Are you sure you want to remove the extension ".txt"?" prompt, press the "Remove" button.  (The icon for universalJavaApplicationStub will change to a green CRT terminal icon with the text, "exec", on it.)  Leave the "MacOS" Finder window open.

11.  Oh, I lied.  You do have to use Terminal.  Open the Applications folder, open the Utilities and run Terminal application.

12.  Paste the following into Terminal and press the "Return" key to execute it:

chmod ugo+x /Applications/Minecraft.app/Contents/MacOS/universalJavaApplicationStub

This command adds eXecute permissions to the file for User, Group and Other.

If you don't get an error, it probably worked.  If you get an error, you can give up on this process and, don't worry, the Minecraft application is undamaged.  In either case, close the Terminal.

13.  Press the back button on the original Finder window to return to the Contents folder.

14.  Right click on the Info.plist file.  Select the "Open With" menu, then choose the "Other..." menu item.  Scroll down and select the "TextEdit" application.  The TextEdit application should start.

15.  Edit and save the file:

A.  Insert "universal" in front of "JavaApplicationStub" so it reads <string>universal JavaApplicationStub</string>.

B.  Insert an "X" at <key>Java</key> to make <key>JavaX</key>.

16.  Go to the Applications folder and run Minecraft.  It should work.  You're done.

If you want to perform this same process entirely in Terminal, start a Terminal and do this:

$ cp -r /Applications/Minecraft.app /Applications/Minecraft\ copy.app
$ cd /Applications/Minecraft.app/Contents
$ curl "https://raw.githubusercontent.com/tofi86/universalJavaApplicationStub/master/src/universalJavaApplicationStub" -o "MacOS/universalJavaApplicationStub"
$ chmod ugo+x MacOS/universalJavaApplicationStub
$ vi Info.plist
Press i to insert text
- <string>JavaApplicationStub</string>
+ <string>universalJavaApplicationStub</string>
- <key>Java</key>
+ <key>JavaX</key>
Press Esc, then type ZZ which will save

This technique should work for any Mac Java application, as long as you go to the correct .app folder.

Don't forget that you have to a backslash (\) before any spaces in the name when using Terminal so Minecraft copy.app becomes Minecraft\ copy.app.

If you need to troubleshoot, try running universalJavaApplicationStub from the Terminal and see if it launches Minecraft or gives you error messages.  If that works, try running the open command so open /Applications/Minecraft.app and see if that launches Minecraft or gives you error messages.  The error messages can be somewhat cryptic but, with Google, perhaps you can figure out what the issue is.

References:
http://apple.stackexchange.com/questions/88110/make-minecraft-or-java-preferences-app-run-on-java-7
http://gaming.stackexchange.com/questions/178178/making-minecraft-run-with-java-8-on-os-x-10-10
http://www.cgwerks.com/make-minecraft-work-mac-osx-yosemite-latest-java-8/
https://gist.github.com/pudquick/7518753
http://www.minecraftforum.net/forums/support/unmodified-minecraft-client/1858141-minecraft-x64-for-mac-with-java-7
https://bugs.mojang.com/browse/MCL-1049
http://mosx.tumblr.com/post/64402950499/os-x-tip-execute-java-apps-like-minecraft-or
http://stackoverflow.com/questions/14806709/application-is-using-java-6-from-apple-instead-of-java-7-from-oracle-on-mac-os-x
http://superuser.com/questions/490425/how-do-i-switch-between-java-7-and-java-6-on-os-x-10-8-2

Thursday, July 30, 2015

What does _.bind() do?

The name, "bind", conjures fear.  It's scary.  Binding sounds mysterious and strange.

Underscore.js has the _.bind() function.  What does it do?

Let's say that you using the JavaScript setTimeout() function to set the focus on a jQuery DOM element.

var el = $('#myinput');
setTimeout(function() { el.focus(); }, 50);

The setTimeout() function takes a standalone function as its first argument.

Now, consider this code:

var el = $('#myinput');
setTimeout(el.focus, 50);

This code doesn't work.  Why?  Well, the focus() call is an object method, not a standalone function.  The setTimeout() function expects a standalone function, not an object method.

A standalone function and an object method aren't the same thing.  If you pass an object method as an argument that expects a standalone function, it's not the same thing, it's wrong and it doesn't work.

It's as if you passed a string as an argument to a function that expects a number.  You passed the wrong kind of thing, even if the string contains a number.  If you want it to work, you have to convert the string to the proper type before calling the function.

So, how can you convert an object method call into a standalone function?

One way is to create a standalone function that calls the object method as you did in the original code.

A second way is to call the _.bind() function.

The _.bind() function says, "Create a standalone function that invokes the method in the first argument, using the second argument as the this object."

So, instead of creating your own standalone function, the _.bind() function will create one for you.

var el = $('#myinput');
setTimeout(_.bind(el.focus, el), 50);

The _.bind(el.focus, el) code creates a standalone function that calls the el.focus() method.  You can think of it as converting a method (call) into a standalone function.

The _.bind() implementation is more complex but you can understand it by imagining that it is implemented like this:

function bind(method, self) {
  return function() {
    self.method(); // this doesn't work; it's just for clarity
  };
}

That's what _bind.() does.  It takes a method call and "converts" it into a standalone function.

Once you grasp this, you will discover that _.bind() has additional uses, such as converting a standalone function call with multiple arguments into a standalone function with no arguments.

With this explanation, I hope that _.bind() and binding is no longer mysterious and strange.  And not scary.


AngularJS dependency resolution and child controller creation

Suppose that you have an AngularJS template (HTML with AngularJS tags, same thing) and an AngularJS controller and you want to execute them together:

var elem = angular.element(angularTemplateHtml);
var compileFunc = $compile(elem);
$controller(controllerName, locals);
elem = compileFunc($scope);

This is how ngRoute bootstraps a route.

Suppose that the controller has dependencies.  How are they resolved?

Deep inside angular.js, there is an invoke() function that looks like this:

function invoke(fn, self, locals, serviceName) {
  if (typeof locals === 'string') {
    serviceName = locals;
    locals = null;
  }
  var args = [],
    $inject = createInjector.$$annotate(fn, strictDi, serviceName),
    length, i,
    key;

  for (i = 0, length = $inject.length; i < length; i++) {
    key = $inject[i];
    if (typeof key !== 'string') {
      throw $injectorMinErr('itkn',
        'Incorrect injection token! Expected service name as string, got {0}', key);
    }
    args.push(
      locals && locals.hasOwnProperty(key)
      ? locals[key]
      : getService(key, serviceName)
    );
  }
  if (isArray(fn)) {
    fn = fn[length];
  }
  // http://jsperf.com/angularjs-invoke-apply-vs-switch
  // #5388
  return fn.apply(self, args);
}

AngularJS looks for dependencies in the locals object and getService().  If it doesn't find the dependency in either place, the dependency fails and you get an error.

It's interesting that you can bolt dependencies onto the locals object.  The locals object is passed directly into the $controller() function so, if you are calling $controller() function directly, you can provide dependencies to the controller, even if those dependencies aren't AngularJS services.

The $controller() function itself looks like this:

/**
 * @ngdoc service
 * @name $controller
 * @requires $injector
 *
 * @param {Function|string} constructor If called with a function
 * then it's considered to be the controller constructor function.
 * Otherwise it's considered to be a string which is used to
 * retrieve the controller constructor using the following steps:
 *
 *  * check if a controller with given name is registered via 
 *    `$controllerProvider`
 *  * check if evaluating the string on the current scope returns
 *    a constructor
 *  * if $controllerProvider#allowGlobals, check
 *    `window[constructor]` on the global `window` object (not
 *    recommended)
 *
 * The string can use the `controller as property` syntax, where
 * the controller instance is published as the specified property
 * on the `scope`; the `scope` must be injected into `locals` param
 * for this to work correctly.
 *
 * @param {Object} locals Injection locals for Controller.
 * @return {Object} Instance of given controller.
 *
 * @description
 * `$controller` service is responsible for instantiating
 * controllers.
 *
 * It's just a simple call to {@link auto.$injector $injector}, but
 * extracted into a service, so that one can override this service
 * with [BC version](https://gist.github.com/1649788).
 */
return function(expression, locals, later, ident) {
  // PRIVATE API:
  //   param `later` --- indicates that the controller's constructor
  //     is invoked at a later time. If true, $controller will
  //     allocate the object with the correct prototype chain, but
  //     will not invoke the controller until a returned callback is
  //     invoked.
  //   param `ident` --- An optional label which overrides the label
  //     parsed from the controller expression, if any.
  var instance, match, constructor, identifier;
  later = later === true;
  if (ident && isString(ident)) {
    identifier = ident;
  }

  if (isString(expression)) {
    match = expression.match(CNTRL_REG);
    if (!match) {
      throw $controllerMinErr('ctrlfmt',
        "Badly formed controller string '{0}'. " +
        "Must match `__name__ as __id__` or `__name__`.",
        expression);
    }
    constructor = match[1],
    identifier = identifier || match[3];
    expression = controllers.hasOwnProperty(constructor)
      ? controllers[constructor]
      : getter(locals.$scope, constructor, true) ||
        (globals ? getter($window, constructor, true) : undefined);
        assertArgFn(expression, constructor, true);
  }

  if (later) {
    // Instantiate controller later:
    // This machinery is used to create an instance of the object
    // before calling the controller's constructor itself.
    //
    // This allows properties to be added to the controller before
    // the constructor isinvoked. Primarily, this is used for
    // isolate scope bindings in $compile.
    //
    // This feature is not intended for use by applications, and is
    // thus not documented publicly.
    // Object creation: http://jsperf.com/create-constructor/2
    var controllerPrototype = (isArray(expression) ?
      expression[expression.length - 1] : expression).prototype;
    instance = Object.create(controllerPrototype || null);

    if (identifier) {
      addIdentifier(locals, identifier, instance, constructor
        || expression.name);
    }

    var instantiate;
    return instantiate = extend(function() {
      var result = $injector.invoke(expression, instance, locals,
        constructor); // resolve dependencies
      if (result !== instance && (isObject(result)
        || isFunction(result))) {
        instance = result;
        if (identifier) {
          // If result changed, re-assign controllerAs value to
          // scope.
          addIdentifier(locals, identifier, instance, constructor
            || expression.name);
        }
      }
      return instance;
    }, {
      instance: instance,
      identifier: identifier
    });
  }
  instance = $injector.instantiate(expression, locals, constructor);

The $controller() function's first argument is expression.   This is either a controller object or its a string with the controller's name.  If it's a string with the controller's name, the $controller() function immediately looks up the controller object and sets expression equal to the object.

Then, the $controller() function chooses whether to create the object instance and return the constructor function to be called later (in green text) or to create the object instance and call the constructor immediately.

In our example, the constructor is called immediately.

But what happens if angularTemplateHtml contains additional controllers that are created by using the ng-controller attribute?

When $compile() function is invoked, it crawls through the angularTemplateHtml DOM tree using functions named nodeLinkFn()childLinkFn() and compositeLinkFn() to find and instantiate AngularJS constructs, like controllers.

The compileFunc() function is created and returned by the $compile() call.

Inside AngularJS, the compileFunc() function looks like this:

return function publicLinkFn(scope, cloneConnectFn, options) {
  assertArg(scope, 'scope');

  options = options || {};
  var parentBoundTranscludeFn = options.parentBoundTranscludeFn,
    transcludeControllers = options.transcludeControllers,
    futureParentElement = options.futureParentElement;

AngularJS crawls the angularTemplateHtml DOM tree during the $compile() function and, when it finds a ng-controller attribute, it invokes the setupControllers() function.

function setupControllers($element, attrs, transcludeFn,
    controllerDirectives, isolateScope, scope) {
  var elementControllers = createMap();
  for (var controllerKey in controllerDirectives) {
    var directive = controllerDirectives[controllerKey];
    var locals = {
      $scope: directive === newIsolateScopeDirective
        || directive.$$isolateScope ? isolateScope : scope,
      $element: $element,
      $attrs: attrs,
      $transclude: transcludeFn
    };
    var controller = directive.controller;
    if (controller == '@') {
      controller = attrs[directive.name];
    }

    var controllerInstance = $controller(controller, locals, true,
      directive.controllerAs);

Notice the bold purple text where the locals object is created by AngularJS when it finds an ng-controller attribute.  While a child controller can access its parent's $scope for various purposes, a child controller's locals object is hardcoded, unavailable and unlinked to the parent controller's locals object!  So, a parent controller cannot resolve dependencies for a child controller created by AngularJS.  Wouldn't it be nice if a parent controller could use its locals object to provide dependency resolution and control over instantiation of its child controllers?  But, it doesn't.  Maybe next version.

Notice the orange highlighted true argument inside the setupControllers() function.  The true argument allocates the controller instance but does not invoke the constructor immediately.  It returns the constructor to be invoked later.

AngularJS allocates controller instances during the $compile() call (in our example) but waits and invokes constructors later during the compileFunc() call (in our example).

During the compileFunc() call, the child controller constructor functions are invoked in this code:

if (elementControllers) {
  // Initialize bindToController bindings for new/isolate scopes
  var scopeDirective = newIsolateScopeDirective
    || newScopeDirective;
  var bindings;
  var controllerForBindings;
  if (scopeDirective && elementControllers[scopeDirective.name]) {
    bindings = scopeDirective.$$bindings.bindToController;
    controller = elementControllers[scopeDirective.name];

    if (controller && controller.identifier && bindings) {
      controllerForBindings = controller;
      thisLinkFn.$$destroyBindings = 
        initializeDirectiveBindings(scope, attrs,
        controller.instance, bindings, scopeDirective);
    }
  }
  for (i in elementControllers) {
    controller = elementControllers[i];
    var controllerResult = controller();

    if (controllerResult !== controller.instance) {
      // If the controller constructor has a return value,
      // overwrite the instance from setupControllers and update
      //the element data
      controller.instance = controllerResult;
      $element.data('$' + i + 'Controller', controllerResult);
      if (controller === controllerForBindings) {
        // Remove and re-install bindToController bindings
        thisLinkFn.$$destroyBindings();
        thisLinkFn.$$destroyBindings =
          initializeDirectiveBindings(scope, attrs,
            controllerResult, bindings, scopeDirective);
      }
    }
  }
}

Notice the bold red text shows where the child controller construction functions are invoked during the compileFunc() call.

This shows the lifecycle of controller objects, both directly created controllers and controllers created by AngularJS itself.

Monday, July 27, 2015

AngularJS $formatters

Suppose you have a new directive that declares a tag like:

<input type="array">

In AngularJS v1.4.1, when you add an "input" directive, AngularJS decides how its going to store your data.  Will your data be stored as a string (in a text node), in a JavaScript object (hanging off a DOM node) or what?

In the case above, is the data stored as a string like "[1, 2, 3, 4]" in a text node or is it stored as a JavaScript array like ctrl.array = [1, 2, 3, 4]?

It decides by running through a whole list of known (to AngularJS) input types and, if it does not know about a new, unexpected input type, it decides that it must be stored as a string.

The known types are:
  • text
  • date ('yyyy-MM-dd')
  • datetime-local ('yyyy-MM-ddTHH:mm:ss.sss')
  • time ('HH:mm:ss.sss')
  • week ('yyyy-Www')
  • month ('yyyy-MM')
  • number
  • url
  • email
  • radio
  • checkbox
  • hidden
  • button
  • submit
  • reset
  • file
If you default to being stored as a string, it adds this function to the $formatters object on the caller's instantiated directive.

function stringBasedInputType(ctrl) {
  ctrl.$formatters.push(function(value) {
    return ctrl.$isEmpty(value) ? value : value.toString();
  });
}

As you can see, if the object doesn't have a toString() method, it will call the default toString() method for all JavaScript objects.  If that happens, the user's data may be "stored" as "[object Object]".  Oh, no!

To avoid this, make sure that you empty or change the $formatters array so it is appropriate:

angular
  .directive('input', function(...) {
    return {
      restrict: 'E',
      require: '?ngModel',
      link: function($scope, $element, $attributes, ngModel) {
        ngModel.$formatters = [];
        ...

That way, you can get the unformatted object and handle it appropriately.

Friday, August 22, 2014

QUnit tests on AngularJS directives

Recently, I had an little homework assignment to create a "signup" web application using Angular.js. You can see the app here.

As part of that assignment, I created an Angular directive to validate the data in the "password" and "verification" text inputs.  Here's what the Angular directive looked like:

// match password and verification
app.directive('match', [function () {
  return {
    require: 'ngModel',
    link: function(scope, elem, attrs, ctrl) {
      scope.$watch('['+attrs.ngModel+', '+attrs.match+']',
          function(value){
        ctrl.$setValidity('match', value[0] === value[1]);
      }, true);
    }
  };
}]);

But I wanted to use QUnit to test this directive.  I spent a ton of time, trying a zillion things, which didn't work because I was a newbie to both Angular and QUnit (and using them together).  But, finally, I found the correct combination.

// create test bed
var injector = angular.injector(['ng', 'ngMock', 'signupApp']);

var init = {
  setup: function() {
    this.$scope = injector.get('$rootScope').$new();
  }
};

module('tests', init);

// test the 'match' directive
QUnit.test('match', function() {
  var html = '<form id="myform" name="signupController" ng-controller="signupController"><input id="password" ng-model="password" match="verification"></input><input id="verification" ng-model="verification" match="password"></input></form>';
  var $compile = injector.get('$compile');
  var element = $compile(html)(this.$scope);
  this.$scope.password = 'passw0rd';
  this.$scope.verification = 'passw0rd';
  this.$scope.$apply();
  ok(element.scope().signupController.$valid, '$valid is false');
  this.$scope.password = 'passw0rd';
  this.$scope.verification = 'passw0rd2';
  this.$scope.$apply();
  ok(!element.scope().signupController.$valid, '$valid is true when it should be false');
});

My first mistake was that it took me a long time to figure out that I needed angular-mocks.js to create a fully functional test bed.  The ngMock module is needed to add lots of support to the Angular test harness.  While I could get a simple test harness running without angular-mocks.js, testing that required the controller (and probably ngModel) required angular-mocks.js.

My second mistake was that it took me a long time to realize that the Angular scope and the Angular controller are different.  (Well, duh.)  Finally, I discovered that, if I added a "name" attribute to the controller element, a property giving access to the controller would be available in the scope.

This may be obvious to Angular experts but I spent a ton of time traveling around on Google and I never found any posts that were on point.

Thursday, July 3, 2014

Events Are More Flexible Than HTTP

When you first use $.ajax() in jQuery, it is easy and tempting to set up a HTTP request/response style communication mechanism between your client and your server.  Your client sends a HTTP request, it provides a handler to receive the HTTP response and the handler does something with the result.  That seems fine ...

... except it breaks down pretty easily.  If the server takes too long, the HTTP connection times out and the response is lost.  And, when it breaks down, you hack on it, adding polling and/or subscription mechanisms.  Then it breaks down some more and you hack on it some more.

Events are always better.

With events, the client sends and receives events (e.g. a JSON object).

Events are self-contained.  They do not require any external information.  For example, the event should not have a different meaning if it is called on one URI (e.g. /users) versus another URI (e.g. /groups).  If it does, the event should be updated with that new information to keep the event self-contained.  So, in our example, maybe an "domain" key is added to the event which is assigned a value of "users" or "groups".  After modifying the event, the event would again be self-contained and the URI that it was sent to can be forgotten.

An event should also be disconnected from the communications mechanism: it should not matter if an event was received via a HTTP request (or HTTP response), short-polling, long-polling, JSONP, Socket.IO or even some strange new datagram mechanism (which would be session-less and not allow responses).  Different communication transports should be easy to substitute.

Events work in "fire and forget" mode.  Once an event is fired, it is gone.  The sender does not concern itself whether the event is received or not; it lets the event delivery mechanism do its work and deliver the event with no further interaction.

But what if your code expects a response?

The event handler should receive the event, process it and then send a response event back to the original sender.  A response event is new event that is created by the receiver and sent to the original sender with a reference to the original event.  Usually, the events contain a unique event number which the response event can reference.  The response is still a new event; it just references another event.

With HTTP, an assumption is made that every request has its own response.  This assumption may not be valid when you are using long-polling instead of HTTP.  With events, however, the assumption is removed; events can be sent and response events can be sent back using some other mechanism or at a much later date.  HTTP relies on the response being sent back in the same HTTP connection as the HTTP request was sent.  Events do not.

Events can be built on top of HTTP requests/responses.  Events are sent as part of the GET query string or the POST data and any pending events can be returned in the HTTP response body.  The difference is that the events returned do not need to correspond to the events sent.  Arbitrary events can be sent and arbitrary events can be received in the same HTTP connection with no relationship implied between them.

Inevitably, it seems that most systems move towards an event system (or suffer through an ever growing number of hacks to add flexibility to HTTP request/response designs).

If you want my advice, consider starting any new code with events, rather than muddling through with an HTTP request/response system and converting it later.

Friday, January 3, 2014

Super simple JSON and MySQL

I invented jsonhib (available for Node.js and PHP at http://github.com/ajaximrpg/jsonhib ) to provide a "good enough" solution to reading and writing JSON data to a MySQL database.

Most developers say this is impossible.

But, to read JSON from a MySQL database, jsonhib has a readRows() method that takes two arguments: a table name and a WHERE clause.  It returns a JSON array of JSON objects where each object represents a MySQL row.  The columns of each MySQL row become JSON property names; the values of each MySQL row become property values.  The WHERE clause only serves to narrow the number of JSON objects returned.

In Node.js, it looks like this:

// assume 'mytable' is a MySQL table with these columns: id, name
jh.readRows('mytable', 'WHERE id > 0', function(s) {
  var str = s;
});
// str='[{"id": 1, "name": "bob"}, {"id": 2, "name": "fred"}]'

Most developers will object that the objects are out of order.  "There's no sorting or ordering," they say, "the objects come out in random order."

They sure do.  Sometimes, the client doesn't care so it doesn't matter.  But, if it does matter and an additional integer column can be added to the table (a sort_column column), jsonhib can be directed to use this hidden column to maintain the order of rows.  And, if the table can't be modified, jsonhib relies on the caller to reorder the JSON array if he wishes.

Another objection is that MySQL databases require a schema and JSON objects can have arbitrary properties.  "The only choice is to put all your JSON objects in one table and serialize the JSON to a single MySQL text column," they say.

Uh, is that how you do it in client?  Just have all your JSON objects crammed into a single humongous array?  Mix your customer JSON objects with your sales order JSON objects and your permissions JSON objects?  Of course not!  You assign arrays of similar JSON objects to different variables.  In this case, similar JSON objects are assigned to specific MySQL tables.  Your client doesn't add customer JSON objects to the permissions variable; don't add customer data to the MySQL permissions table.

Also, don't all customers have a name?  Isn't their name always a string, not a floating point value?  Yes, JSON objects can have arbitrary properties but they always have a lot of properties that are expected and required and are of a specific type.  jsonhib relies on the caller to know that, by default, JSON properties that do not fit into the MySQL schema will be discarded.  Avoid extra properties or store them somewhere else.  If that is not desirable and an additional string column can be added to the table (a json_column column), jsonhib can be directed to use this hidden column to keep track of JSON data that doesn't fit into the MySQL schema.  This column doesn't keep all the JSON data; it just keeps the JSON properties that don't have a corresponding dedicated MySQL column or have a MySQL column of the wrong type.

jsonhib really is just an object-relational mapping (ORM) layer for JSON and MySQL.  When reading, jsonhib queries MySQL rows and sensibly maps MySQL columns to JSON properties and, if available, uses the sort_column and json_column columns to fix up the mismatches between how MySQL works and how JSON works.

Besides reading, jsonhib can also insert, delete and update JSON objects.  JSON arrays (i.e. MySQL tables) can also be reordered using the moveRow() method.

// insert a row
jh.insertRow('mytable', '', -1, '{"id": 1, "name": "bob"}',
  function() {});
// delete a row
jh.deleteRow('mytable', '', 0,
  function() {});
// update a row
jh.updateRow('mytable', 'WHERE id=1', 0, '{"id": 1, "name": "eric"}',
  function() {});
// move a row (huh?)
jh.moveRow('mytable', 'WHERE id=1', 0, 1,
  function() {});

jsonhib has a lot of nice attributes.  Other solutions require new SQL syntax provided by specially modified MySQL database software, plugins or new versions but jsonhib works with any MySQL version and any MySQL data.  Existing applications and processes that use the MySQL database work without modification and can work with data that is inserted, updated and deleted using jsonhib.

Impossible?  No, not impossible.  JSON can be stored in MySQL.