Monthly Archives: September 2016

Your API’s and HAL

HAL – Hypertext Application Language

HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API. Adopting HAL will make your API explorable, and its documentation easily discoverable from within the API itself. In short, it will make your API easier to work with and therefore more attractive to client developers.

APIs that adopt HAL can be easily served and consumed using open source libraries available for most major programming languages. It’s also simple enough that you can just deal with it as you would any other JSON. HAL provides a set of conventions for expressing hyperlinks in either JSON or XML. The rest of a HAL document is just plain old JSON or XML. Instead of using ad-hoc structures, or spending valuable time designing your own format; you can adopt HAL’s conventions and focus on building and documenting the data and transitions that make up your API. Its conventions make the documentation for an API discoverable from the API messages themselves. This makes it possible for developers to jump straight into a HAL-based API and explore its capabilities, without the cognitive overhead of having to map some out-of-band documentation onto their journey.

The HAL conventions revolve around representing two simple concepts: Resources and Links.

Resources have: Links (to URIs), Embedded Resources (i.e. other resources contained within them), State (your standard JSON or XML data).

Links have: A target (a URI), A relation aka. ‘rel’ (the name of the link), a few other optional properties to help with deprecation, content negotiation, etc.

HAL is designed for building APIs in which clients navigate around the resources by following links. Links are identified by link relations. Link relations are the lifeblood of a hypermedia API: they are how you tell client developers about what resources are available and how they can be interacted with, and they are how the code they write will select which link to traverse.

@Injectables + Angular 2.0 + @Inject

@Injectable() is the decorator in Angular 2.0

Typically in Angular 2.0 services are simple classes and if these services require dependencies to be injected then you need this decorator.

DI (Dependency Injection) in Angular 2.0 is hierarchical in nature, for dependency injection to be able to create instances for you, you need to register providers for these classes (or other values) somewhere. and you can configure providers for DI at different levels

  • For the whole application when bootstrapping it. In this cases, all sub injectors (the component ones) will see this provider and share the instance associated with. When interacting, it will be the same instance
  • For a specific component and its sub components. Same as before but for à specific component. Other components won’t see this provider. If you redefine something defined above (when bootstrapping for example), this provider will be used instead. So you can override things. If a provider is registered in one of the child components a new (different) instance is provided for descendants of this component.
  • If a component requests an instance (by a constructor parameter), DI looks “upwards” the component tree (starting from leaf towards the root) and takes the first provider it finds. If an instance for this provider was already created previously, this instance is used, otherwise a new instance is created.

Angular 2.0 docs recommend adding @Injectable() to all services classes , even those that don’t have dependencies and, therefore, do not technically require it. Here’s why:

  • Future proofing: No need to remember @Injectable() when we add a dependency later.
  • Consistency: All services follow the same rules, and we don’t have to wonder why a decorator is missing.

Here is sample service (CategoryService) for my mobile app

import { Injectable } from '@angular/core';
import { Http, Response} from '@angular/http';

import {Category} from './category';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class CategoryService {
    constructor(private http: Http){
        
    }
    
    private categoryServiceUrl = "http://app.cloudapp.net/api/Category";
    
    getCategories (): Observable<Category[]>{
        return this.http.get(this.categoryServiceUrl)
                        .map(this.extractCategoryData)
                        .catch(this.handleError);
                        
    } 
    
    private extractCategoryData(res: Response){
        let body = res.json();
        return body || { };
    }
    
    private handleError (error: any) {
        let errMsg = (error.message) ? error.message : 
        error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg); 
        return Observable.throw(errMsg);
  }
}

 

Here is how you register with provider this is at component level

import { Component, OnInit } from '@angular/core';
import { Category } from './category';
import { CategoryService } from './categoryService';
// Add the RxJS Observable operators we need in this app.
import './rxjs-operators';
@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  providers:[CategoryService]
})
export class AppComponent implements OnInit{
  title = 'app works!';
  firstName= "Aamol Gote";
  errorMessage: string;
  categories: Category[];
  
  constructor(private categoryService: CategoryService){
    
  }
  
  ngOnInit() {
    this.getCategories();
  }
  
  getCategories(){
    this.categoryService.getCategories()
                        .subscribe(
                          categories => this.categories = categories,
                          error => this.errorMessage = <any>error
                        );
  }
}

 

@Inject – This is manual way of letting angular know that this parameter must be injected. typically DI is implicit in nature for Angular 2.0 but for certain edge cases if there is need to specify dependency explicitly with its type then @Inject is used. One very good candidate for @Inject is for injecting non class dependencies. Suppose if you have an application configuration which includes API end point, then these configurations need not necessarily be instances of the classes these can be just object literals, for e.g. as shown below

export interface ApplicationConfiguration{
    apiEndPoint : string,
    timeOut: number
}

export const INTERVIEW_APP_CONFIG: ApplicationConfiguration = {
  apiEndPoint: 'http://app.cloudapp.net/api/Category',
  timeOut: 20
};

 

Now we need to inject INTERVIEW_APP_CONFIG in CategoryService, way we do it first need to register the Provider for INTERVIEW_APP_CONFIG,

[{ provide: InterviewAppConfig, useValue: INTERVIEW_APP_CONFIG  })]

constructor(private config:InterviewAppConfig){ }

 

But the above code snippet fails as INTERVIEW_APP_CONFIG constant has an interface, InterviewAppConfig. We cannot use a TypeScript interface as a token, to solve this we have to use Opaque tokens, here is the updated category service class with config value injected through @Inject()

import { Injectable, Inject } from '@angular/core';
import { Http, Response} from '@angular/http';
import { OpaqueToken } from '@angular/core';

import {Category} from './category';
import {Observable} from 'rxjs/Observable';

export let INTERVIEW_APP_CONFIG = new OpaqueToken('app.config');
export interface ApplicationConfiguration{
    apiEndPoint : string,
    timeOut: number
}

export const INTERVIEW_APP_DI_CONFIG: ApplicationConfiguration = {
  apiEndPoint: 'http://app.cloudapp.net/api/Category',
  timeOut: 20
};


@Injectable()
export class CategoryService {
    categoryServiceUrl :string;
    constructor(private http: Http, @Inject(INTERVIEW_APP_CONFIG) 
        config: ApplicationConfiguration){
        this.categoryServiceUrl = config.apiEndPoint;
    }
    
    
    
    getCategories (): Observable<Category[]>{
        console.log("Get Categories");
        return this.http.get(this.categoryServiceUrl)
                        .map(this.extractCategoryData)
                        .catch(this.handleError);
                        
    } 
    
    private extractCategoryData(res: Response){
        let body = res.json();
        return body || { };
    }
    
    private handleError (error: any) {
        let errMsg = (error.message) ? error.message : 
        error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg); // log to console instead
        return Observable.throw(errMsg);
  }
}

 

We need register the provider in the component like shown below

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  providers:[CategoryService, { provide: INTERVIEW_APP_CONFIG, 
                                useValue: INTERVIEW_APP_DI_CONFIG }]
})