Category Archives: Tech Tips

Ionic 2, AngularFire 2 and Firebase 3

  1. Create a new Ionic 2 project:
    ionic start example-ionic blank --v2
  2. Install Firebase 3 and AngularFire 2
    cd example-ionic
    npm install angularfire2 firebase —save
    typings install file:node_modules/angularfire2/firebase3.d.ts --save --global
  3. In app.ts
    import {Component} from '@angular/core';
    import {Platform, ionicBootstrap} from 'ionic-angular';
    import {StatusBar} from 'ionic-native';
    import {HomePage} from './pages/home/home';
    
    import {
     defaultFirebase,
     FIREBASE_PROVIDERS
    } from 'angularfire2';
    
    const COMMON_CONFIG = {
     apiKey: "YOUR_API_KEY",
     authDomain: "YOUR_FIREBASE.firebaseapp.com",
     databaseURL: "https://YOUR_FIREBASE.firebaseio.com",
     storageBucket: "YOUR_FIREBASE.appspot.com"
    };
    
    @Component({
     template: '<ion-nav [root]="rootPage"></ion-nav>',
     providers: [
     FIREBASE_PROVIDERS,
     defaultFirebase(COMMON_CONFIG)
     ]
    })
    export class MyApp {
     rootPage: any = HomePage;
    
     constructor(platform: Platform) {
     platform.ready().then(() => {
     // Okay, so the platform is ready and our plugins are available.
     // Here you can do any higher level native things you might need.
     StatusBar.styleDefault();
     });
     }
    }
    
    ionicBootstrap(MyApp);
  4. In home.ts
    import {Component} from '@angular/core';
    import {NavController} from 'ionic-angular';
    
    import {
     AngularFire,
     FirebaseObjectObservable
    } from 'angularfire2';
    
    @Component({
     templateUrl: 'build/pages/home/home.html'
    })
    export class HomePage {
     item: FirebaseObjectObservable<any>;
    
     constructor(private navCtrl: NavController, af: AngularFire) {
     this.item = af.database.object('/item');
     }
    }
  5. In home.html
    <ion-header>
     <ion-navbar>
     <ion-title>
     Ionic Blank
     </ion-title>
     </ion-navbar>
    </ion-header>
    
    <ion-content padding>
     The world is your oyster.
     <p>
     {{ (item | async)?.name }}
     </p>
    </ion-content>
  6. In your firebase console, make sure have an object under /item with a “name” property. This is what we load in our example code above.
  7. Test by running the app.
    ionic serve

Azure Service Bus Topic issue while using NodeJS SDK: Error: getaddrinfo ENOTFOUND

While using NodeJS SDK to send message to an Azure Service Bus Topic, the docs suggest to set a couple of environment variables: AZURE_SERVICEBUS_NAMESPACE and AZURE_SERVICEBUS_ACCESS_KEY. However this did not work for me with SDK 0.10.6 and sendTopicMessage method returned error message “Error: getaddrinfo ENOTFOUND”.

To solve this, instead of setting the environment variable, create the service bus service like below – replace <namespace> and <namespace_access_key> accordingly.

azure.createServiceBusService('Endpoint=sb://'+ <namespace> + '.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=' + <namespace_access_key>);

Google Polymer: gulp serve error

Being eager to tryout Polymer 1.0, I downloaded the Polymer Started Kit and ran gulp serve only to run into below error:

[14:42:29] 'elements' all files 0 B
[14:42:29] Finished 'elements' after 2.18 s
Unhandled rejection Error: spawn ENOENT
    at errnoException (child_process.js:1001:11)
    at Process.ChildProcess._handle.onexit (child_process.js:792:34)
[14:42:29] 'styles' all files 98 B
[14:42:29] Finished 'styles' after 3.1 s

This happens when gulp serve task throws and error and it’s not handled. From the error log I could see that the “sytles” and “elements” sub tasks have completed. The other sub task for “serve” task is “images”. In gulpfile.js, the images task was configured as:

// Optimize Images
gulp.task('images', function () {
 return gulp.src('app/images/**/*')
 .pipe($.cache($.imagemin({
 progressive: true,
 interlaced: true
 })))
 .pipe(gulp.dest('dist/images'))
 .pipe($.size({title: 'images'}));
});

I changed this to:

// Optimize Images
gulp.task('images', function () {
 return gulp.src('app/images/**/*')
 .pipe($.cache($.imagemin({
 progressive: true,
 interlaced: true
 }))).on('error', errorHandler)
 .pipe(gulp.dest('dist/images'))
 .pipe($.size({title: 'images'}));
});

And added below error handler function to the bottom of gulpfile.js:

// Handle the error
function errorHandler (error) {
 console.log(error.toString());
 this.emit('end');
}

#microtip – Center a div horizontally and vertically

A small tip that can be handy say when you are creating a landing HTML page. The goal is to position or align a div in the centre of the browser. There are many misleading and non working example when you google this, so pasting a simple solution that works.

HTML

<div class="outer-container">
 <div class="inner-container">
 <center>
 <h3>Hello Center!</h3>
 </center>
 </div>
</div>

CSS

.outer-container {
 position: fixed;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
}

.inner-container {
 position: relative;
 top: 40%;
}

JsFiddle: http://jsfiddle.net/31L9jdsz/

CORS for play framework 2.3.x java app

CORS is Cross Origin Resource Sharing and allows a browser to access APIs from a different domain. CORS is better than JSONP as it can be applied to Http POST, PUT, DELETE etc. Also using CORS is simpler as there is no special set up required in jQuery UI layer.

Configuring CORS for Play 2.3 java app is different from older versions. The following needs to be done:

1. All API responses from the server should contain a header: “Access-Control-Allow-Origin”, “*”. We need to write a wrapper for all action responses.

2. Server requests like POST, PUT make a preflight request to the server before the main request. The response for these preflight requests should contain below headers:

“Access-Control-Allow-Origin”, “*”
“Allow”, “*”
“Access-Control-Allow-Methods”, “POST, GET, PUT, DELETE, OPTIONS”
“Access-Control-Allow-Headers”, “Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent”

For achieving #1, do the following in Play: If you don’t already have a Global.java, create one in your default package.

play.*;
import play.libs.F.Promise;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;

public class Global extends GlobalSettings {

 // For CORS
 private class ActionWrapper extends Action.Simple {
 public ActionWrapper(Action<?> action) {
 this.delegate = action;
 }

 @Override
 public Promise<Result> call(Http.Context ctx) throws java.lang.Throwable {
 Promise<Result> result = this.delegate.call(ctx);
 Http.Response response = ctx.response();
 response.setHeader("Access-Control-Allow-Origin", "*");
 return result;
 }
 }

 @Override
 public Action<?> onRequest(Http.Request request,
 java.lang.reflect.Method actionMethod) {
 return new ActionWrapper(super.onRequest(request, actionMethod));
 }

}

For #2, First make an entry in routes. A preflight request is of Http type OPTIONS. So make an entry like below.

OPTIONS /*all controllers.Application.preflight(all)

Next, define the preflight method in your Application controller. And CORS is all setup!

package controllers;

import play.mvc.*;

public class Application extends Controller {

 public static Result preflight(String all) {
 response().setHeader("Access-Control-Allow-Origin", "*");
 response().setHeader("Allow", "*");
 response().setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
 response().setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Referer, User-Agent");
 return ok();
 }

}

Adding dependency from local maven repository to a Play project

I wanted to add a REST API layer to my java project and decided to use Play framework for the REST APIs. This way, in future I can also use Play to serve static web content.

Play framework uses SBT & Ivy whereas I had used Maven for my Java project. To be able to add the jar as dependency and get it working I had to do the below.

PS: I am using Play 2.3.x

1. Add the dependency in build.sbt and also a resolver pointing to my local Maven repository.

libraryDependencies ++= Seq(
 "my.group" % "my-project" % "1.0-SNAPSHOT",
 javaJdbc,
 javaEbean,
 cache,
 javaWs
)

resolvers += Resolver.mavenLocal

2. Do an “activator update”

3. Do an “activator eclipse”

4. Refreshed the project in eclipse.

The main trick was step#2 to update.
You could also use resolver like below:

resolvers += (
 "Local Maven Repository" at "file:///"+Path.userHome.absolutePath+"/.m2/repository"
)