Download - Apigility-powered API's on IBM i
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 [email protected]
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!