Apigility-powered API's on IBM i

Preview:

Citation preview

Apigility-powered API’s on IBM iChuk Shirley

Sabel Steel Service Sure Consulting

Senior Software Engineer

Subject Matter Expert

Founder and Owner

2015 Innovation Award Winner

@ChukShirley chukShirley@gmail.com

TODAY’S TOPICS• API concepts

• Apigility installation / Server configuration

• Creating RESTful web services

• Sanitizing input

• Using the toolkit

• Error handling

• Tips

WHAT IS AN API?

API TERMINOLOGY

• Examples:

• IBM i OS commands (CRTLIB, DSPJOBLOG)

• jQuery methods (jQuery.ajax(), jQuery.on())

• RPG built-in functions (%DEC, %XLATE)

“An API is a way for two computer applications to talk to each other over a network using a common

language that they both understand.”

Jacobson, Daniel and Greg Brail. Sebastopol, APIs: A Strategy Guide Sebastopol, CA: O’Reilly Media, Inc., 2012

• API = “Application Programming Interface”

API TERMINOLOGY• API vs Web API

• A Web API is an API accessed over HTTP

• Web service vs Web API

• A web service refers to one or many related API functions

• A web API is a collection of web services

APPLICATION LAYERS

Presentation Application & Domain Persistence

Web (HTML, CSS, JS) PHP Db2

Mobile (Objective C, Cordova) CL, RPG, COBOL, Java Sessions

Toaster app SQL Cache

Web API

LAYER COMMUNICATION

Presentation layer

HTTP Request

HTTP Response

Application/Domain

layers

Persistence layer

DB Interactions

Web API

APIGILITY INSTALLATION

REQUIREMENTS

• Code Editor (Zend Studio, RDi, Notepad, etc.)

• Zend Server 6 or above running PHP 5.4.8 or above

• PHP Toolkit and XMLSERVICE Library

• REST Client (optional)

• Postman, cURL, etc.

DEVELOPMENT METHODS

• Apigility admin UI runs locally

• Edit your code locally • Push changes to server

Local Remote

• Apigility admin UI runs on server

• Edit your code locally (pull files from server first)

• Push changes to server

LOCAL: RUN PHP LOCALLY

• Download PHP to your local computer

• Manual install

• Homebrew, Vagrant, Macports

• All in one (MAMP, XAMPP, WAMP, etc.)

LOCAL: RUN INSTALLATION SCRIPT

php -r “readfile(‘https://apigility.org/install');” | php

*See Apigility docs for alternative installation methods

Install Apigility Installation complete. Running PHP internal web server. Open your browser to http://localhost:8888, Ctrl-C to stop it.

cd /path/to/project/parent/directory

REMOTE INSTALLATION

DOWNLOAD SKELETON APP

• Add Zend Server’s binaries folder to PATH environment variable

• Start PASE shell

VERIFY OPENSSL VERSION• Only recent versions of OpenSSL can properly

use this CA bundle.

• Make sure you’re running at least 0.9.8

Too old!

PHP 5.6 AND OPENSSL

• PHP 5.6 now verifies peer certificates by default

• Download “good known” CA bundle

• Change php.ini setting

RUN APIGILITY INSTALLER

• Rename the directory to AcmeAPI

• Return to PASE and change directories to /www

• Run the Apigility installer scriptphp-cli -r “readfile(‘https://www.apigility.org/install');” | php-cli

SERVER CONFIGURATION

DISABLE OPCACHE• Enable opcache blacklist in php.ini

• Create file opcache_blacklist.txt and add two entries

DISABLE APC CACHE

• Change PHP setting in datacache.ini

• Set zend_datacache.apc_compatibility to “0”

CONFIGURE DIRECTORY PERMISSIONS

• Make /config and /module directories writable by web server

ADD APACHE VIRTUAL HOST • In /www/zendsvr6/conf/httpd.conf

• Template is on next slide

• You’ll need to supply three values:

• Server IP address/DNS (10.x.x.x, 192.x.x.x, subdomain.domain.com)

• Port number **Choose one that isn’t in use**

• Path to the project

• Restart Zend Server

Listen *:[port] NameVirtualHost *:[port] <VirtualHost *:[port]> ServerName [server ip]:[port] DocumentRoot "/www/AcmeAPI/public" ! SetEnv APPLICATION_ENV "development" AllowEncodedSlashes On ! RewriteEngine on <Location /> RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] ! RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$ RewriteRule ^(.*) - [E=BASE:%1] RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L] </Location> </VirtualHost>

http://[server ip]:[port]/

CREATING RESTFUL WEB SERVICES

INITIALIZING THE DB2 TABLE

CREATE TABLE MY_LIB.CUSTOMERS ( ID BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1, NO ORDER, NO CYCLE, NO MINVALUE, NO MAXVALUE, CACHE 20), NAME VARCHAR (50), ADDRESS VARCHAR (75) );

DESIGNING THE URIS

HTTP Request Method

Example URI Task

GET /customer Lists all rowsPOST /customer Creates new row in dbGET /customer/{customer id} Fetch a particular row PUT /customer/{customer id} Update row in db

DELETE /customer/{customer id} Remove row from db

USING THE ADMIN INTERFACE

USING THE TOOLKIT

ZF2 SERVICES• The toolkit should be used as a service

• Services are configured in the Service Manager

• PHP array

• Assembled at runtime from many locations

• Global application services located at /config/autoload/application.config.php

ADDING DB2 SERVICE

ADDING DB2 SERVICE

ADDING TOOLKIT SERVICE

PROJECT STRUCTURE

USING THE TOOLKIT

USING THE TOOLKIT

USING THE TOOLKIT (PHP)

USING THE TOOLKIT (CL)

USING THE TOOLKIT (RPG)

USING THE TOOLKIT (RPG)

USING THE TOOLKIT (PHP)

ERROR HANDLING

ERROR HANDLING• Use HTTP response status codes for errors • Apigility supports API Problem format

• Uses application/problem+json mediatype

SENDING THE API PROBLEM• You can produce an API Problem with one of two

methods:

• return new \ZF\ApiProblem\ApiProblemResponse()

• throw new Exception()

THROWING AN EXCEPTION

THROWING AN EXCEPTION

CUSTOMERRESOURCE::FETCH()

ADDITIONAL RESOURCES• This presentation’s GitHub repo:

http://github.com/chukShirley/rpg-php-rest-services-apigility

• Apigility documentation:http://www.apigility.org/documentation

• HTTP status codes cheat sheet:http://httpstatus.es/

QUESTIONS?

BONUS!

TIPS

• Start with a small project

• Use Toolkit’s HTTP transport to run PHP locally and RPG remotely

• Abstract the Toolkit calls

“BEST PRACTICE”

• Create ZF2 module to encapsulate Toolkit

• Composer package or php require()

• Move Toolkit calls to domain (e.g., customer) module

• Use DTO instead of array

“BEST PRACTICE”

• Convert DTO to command/query object

• Build command bus/query bus

• Convert Service to command/query handler object

• Restructure and rename command to reflect user’s intent

REST AND USER INTENT• REST is great for describing database actions (CRUD)

but usually not for representing user intent

• Which HTTP method describes Customer::payInvoice()?

• The process of paying an invoice may include creating db records, updating others, sending emails, and interacting with another web API.

REST AND CQRS

• One solution: build your application as a set of commands and queries(in the CQRS sense).

• Treat each command/query as an endpoint and use POST/GET http methods.

• POST http://my.api.com/commands/CustomerPayInvoice

• GET http://my.api.com/queries/FetchActiveCustomers

THANKS!