Using Grunt to deploy to individual OpenShift Applications

I ran across this problem using the MEAN stack seed project generated through the angular fullstack generator (https://github.com/angular-fullstack/generator-angular-fullstack). The seed project’s developers made it easy to deploy an application to OpenShift, however they set it up so you can only deploy to a single OpenShift application instance.

One of the requirements for my current MEAN project is to deploy it to two environments: a staging environment and a full blown production environment. However with this seed project and respective Grunt buildcontrol directives, that wouldn’t be possible.

So I took it upon myself to edit the Grunt file and the yeoman javascript to deploy to OpenShift, to allow it to create multiple environments.

The first step is to edit generator-angular-fullstack\openshift\index.js file that ships with the yeoman generator for angular fullstack. (Note: this file is outside of your actual MEAN project seeded by the generator, typically in your home directory, so you’ll need to search for it on your filesystem). As writing of this blog post, openshift\index.js has hardcoded the application name to be ‘openshift’. Find all occurences of ‘openshift’ (single quotes included) and replace it with this.deployedName (no single quotes). This will allow the application name to be the actual name you’ll input when running this openshift deployment yeoman script.

Secondly, you’ll need to edit the Gruntfile.js in your project. Skip down to the buildcontrol. Under openshift, change the remote field from ‘openshift’ to grunt.option(‘openshift_target’). grunt.option() allows you to take an argument from the command line, so this way you can specify the application name you want to deploy to.

And voilà, that’s it. Now you have the capability to deploy (and update) your MEAN application to multiple OpenShift application environments.

As per the angular fullstack generator documentation, to deploy to OpenShift, you would run the following command:

yo angular-fullstack:openshift

In the yeoman script run in the command above, you’ll be asked for the application name. I named mine “staging” and “production” (two separate environments created by running the command twice). And then to deploy to your application initially, or deploying all code updates, you’d run the commands.

grunt build
grunt buildcontrol:openshift --openshift_target=staging
grunt buildcontrol:openshift --openshift_target=production

Vaadin: Executing custom JavaScript from a thread, or loading custom JavaScript functions into global scope

As you may know already, in Vaadin you can use com.vaadin.ui.JavaScript.getCurrent().execute(…) function to execute some custom JavaScript on the client browser.

  1. Executing custom JavaScript from a thread:
    The above works well as long as the JavaScript execute() method is being called on the main UI thread. However, if JavaScript.getCurrent().execute() is called from a background thread, the JavaScript won’t get executed until there is a periodic refresh of the UI, or there’s a UI event (triggered by the user, such as a mouse click somewhere). This can seem to cause erratic behavior, with the JavaScript executing at unpredictable times. (Side note: any Vaadin UI access/manipulation from a background thread needs to be done inside com.vaadin.UI.getCurrent().access(new Runnable() { … });, and also note that you want to do your time-consuming heavy lifting first (such as retrieving data from the back end) and then go into UI.getCurrent().access(…) to manipulate the UI).To get around this problem, simply use Vaadin Push. You’ll need to enable push if not already (see Vaadin documentation on how). Then depending on the push mode you’ve used (manual or automatic) you’ll either need to call com.vaadin.ui.UI.getCurrent().push() or not (for manual mode you’ll need to call the push() method, for automatic mode it will be called after the runnable you send to the UI.access(…) method finishes executing). So call get JavaScript.execute(…), and then UI.push() last. Example:

    new Thread() {
        public void run() {
            //some long running background work
                 UI.getCurrent.access(new Runnable() {
                public void run() {
                    JavaScript.getCurrent().execute("alert('Background Task Complete!');");
                                UI.getCurent().push();
                }
            });
        }
    }.start();
  2. Loading custom JavaScript functions into global scope:
    This is extremely useful so you can define a JavaScript function which you can use later from JavaScript.getCurrent().execute(…), such as inside an event (a button click, for example). However, the JavaScript function will need to be in the global scope by injecting it into thetag for the HTML page served by Vaadin. To do this, use the following code while your Vaadin view is being created, or is being enter()’ed.

    StringBuilder script = new StringBuilder(); script .append("var head = document.getElementsByTagName('head')[0];") .append("var script = document.createElement('script');") .append("script.content='function sayHello() { alert(\"Hello!\");}';") .append("head.appendChild(script);"); JavaScript.getCurrent().execute(script.toString());

    Note: as I mentioned, a JavaScript function can only be loaded this way when the view is being created, or in the view’s enter() method. To create a function this way AFTER the page is already loaded (such as through some event), you’ll need to use Vaadin Push, and call UI.getCurrent().push() after the JavaScript.getCurrent().execute() even though you’re not on a background thread.

  3. You can define a function in the script tag being created above, which can then be called later on through JavaScript.getCurrent().execute(“sayHello();”); perhaps inside a Vaadin button click listener.

Enjoy!

AngularJS creating multiple $resource endpoints in a service

So this had me baffled for a bit. For using Angular’s $resource in your Angular service, you map it to a particular URL with (optional) parameters defined for that URL. Then how can you have multiple resources with their own unique URLs mapped in the same service?

For example, here’s a service called User which maps to the URL “/api/users/…”:

angular.module('myApp')
  .factory('User', function($resource) {
    return $resource('/api/users/:id/:controller', {
      id: '@_id'
    }, {
      changePassword: {
        method: 'PUT',
        params: {
          controller: 'password'
        }
      },
      get: {
        method: 'GET',
        params: {
          id: 'me'
        }
      }
    });
  });

As you can see, there’s one resource in this service that maps to the one URL, so then how can I add another URL for the $resource?

The answer turned out to be pretty simple, actually. What you have to do is create an object (JSON) of $resources that are returned for the service. You can have individual elements inside the object that each map to a different $resource. So, for example:

'use strict';

angular.module('myApp')
  .factory('User', function ($resource) {
    return {
      WithId: $resource(
        '/api/users/:id/:controller',
        {
          id: '@_id'
        },
        {
          changePassword: {
            method: 'PUT',
            params: {
              controller: 'password'
            }
          },
        }
      ),
      Misc: $resource(
        '/api/users/misc/:controller',
        null,
        {
          generateResetPasswordToken: {
            method: 'POST',
            params: {
              controller: 'generateResetPasswordToken'
            }
          },
        }
      ),
    };
  });

In the above example, in the “User” service, we have two resources that can be accessed. To access “changePassword”, we can use User.WithId.changePassword (which maps to a particular URL), and to access “generateResetPasswordToken” we use User.Misc.generateResetPasswordToken (which maps to another URL).

Voila!

Correctly doing post-login processing in the DaftMonk AngularJS full-stack seed

So I’ve been working on a personal project using the MEAN stack (MongoDB, ExpressJS, AngularJS and NodeJS)! The nerd in me has been pretty excited to learn something completely new and different. I’ve never done full-stack development strictly in JavaScript, and so far I’m finding it to be pretty neat. I’ll be making posts about things I struggle with, or find useful, as I progress.

Anyway, I used the DaftMonk AngularJS full-stack yeoman generator (https://github.com/DaftMonk/generator-angular-fullstack) for my project seed. I definitely recommend it if you’re starting out fresh with MEAN (or even if you’re not), since it speeds up the initial setup and development immensely.

My problem arose as I was wiring up some post-processing to be done after a user logged in. In the login controller (login.controller.js), after the login function is called from the Auth service, there is a function in “.then()” that is called upon success.

Auth.login({
  email: $scope.user.email,
  password: $scope.user.password
})
.then( function() {
    //login was successful
    //...
  }

However, even though the user has logged in, the user data is not available yet! So, you cannot access the current user’s data properties (such as their role) through Auth.getCurrentUser() (for example the Auth.getCurrentUser().role field will be undefined). This is due to the fact that the data is loaded asynchronously (I’m still trying to get the hang of how that works).

The way around this is to use the Auth.isLoggedInAsync(…callback…) function. The callback sent to isLoggedInAsync is called after the user has finally been loaded, which will guarantee your post-login-processing code being executed after the data for the user is available.

This is how you’d make use of Auth.isLoggedInAsync(…):

Auth.login({
  email: $scope.user.email,
  password: $scope.user.password
})
.then( function() {
    Auth.isLoggedInAsync(function(success) {
      //Auth.getCurrentUser() will now return the user with all the properties fully loaded
    }

Enjoy!