OTN TechBlog

Subscribe to OTN TechBlog feed
Oracle Blogs
Updated: 4 hours 44 min ago

Microservices From Dev To Deploy, Part 2: Node/Express and Fn Serverless

Fri, 2018-10-05 08:08
.syntaxhighlighter table td.gutter div.line { padding: 0 .5em 0 1em!important; }

In our last post, we were introduced to a fictional company called TechCorp run by an entrepreneur named Lydia whose goal it is to bring back the world back to the glory days of the internet homepage. Lydia’s global team of remarkable developers are implementing her vision with a microservice architecture and we learned about Chris and Michiko who have teams in London and Tokyo.  These teams built out a weather and quote service using Helidon, a microservice framework by Oracle.  Chris’ team used Helidon SE with Groovy and Michiko’s team chose Java with Helidon MP.  In this post, we’ll look at Murielle and her Bangalore crew who are building a stock service using NodeJS with Express and Dominic and the Melbourne squad who have the envious task of building out a random cat image service with Java Oracle Fn (a serverless technology).

It’s clear Helidon makes both functional and Microprofile style services straight-forward to implement.  But, despite what I personally may have thought 5 years ago it is getting impossible to ignore that NodeJS has exploded in popularity.  Stack Overflow’s most recent survey shows over 69% of respondents selecting JavaScript as the “Most Popular Technology” among Programming, Scripting and Markup Languages and Node comes in atop the “Framework” category with greater than 49% of the respondents preferring it.  It’s a given that people are using JavaScript on the frontend and it’s more and more likely that they are taking advantage of it on the backend, so it’s no surprise that Murielle’s team decided to use Node with Express to build out the stock service.  
 
We won’t dive too deep into the Express plumbing for this service, but let’s have a quick look at the method to retrieve the stock quote:
var express = require('express'); var router = express.Router(); var config = require('config'); var fetch = require("node-fetch"); /* GET stock quote */ /* jshint ignore:start */ router.get('/quote/:symbol', async (req, res, next) => { const symbol = req.param('symbol'); const url = `${config.get("api.baseUrl")}/?function=GLOBAL_QUOTE&symbol=${symbol}&apikey=${config.get("api.apiKey")}`; try { const response = await fetch(url); const json = await response.json(); res.send(json); } catch (error) { res.send(JSON.stringify(error)); } }); /* jshint ignore:end */ module.exports = router;
Using fetch (in an async manner), this method calls the stock quote API and passes along the symbol that it received via the URL parameters and returns the stock quote as a JSON string to the consumer.  Here’s how that might look when we hit the service locally:
stock-service-response
Murielle’s team can expand the service in the future to provide historical data, cryptocurrency lookups, or whatever the business needs demand, but for now it provides a current quote based on the symbol it receives.  The team creates a Dockerfile and Kubernetes config file for deployment which we’ll take a look at in the future.
 
Dominic’s team down in Melbourne has been doing a lot of work with serverless technologies.  Since they’ve been tasked with a priority feature – random cat images – they feel that serverless is the way to go do deliver this feature and set about using Fn to build the service.  It might seem out of place to consider serverless in a microservice architecture, but it undoubtedly has a place and fulfills the stated goals of the microservice approach:  flexible, scalable, focused and rapidly deployable.  Dominic’s team has done all the research on serverless and Fn and is ready to get to work, so the developers installed a local Fn server and followed the quickstart for Java to scaffold out a function.
 
Once the project was ready to go Dominic’s team modified the func.yaml file to set up some configuration for the project, notably the apiBaseUrl and apiKey:
schema_version: 20180708 name: cat-svc version: 0.0.47 runtime: java build_image: fnproject/fn-java-fdk-build:jdk9-1.0.70 run_image: fnproject/fn-java-fdk:jdk9-1.0.70 cmd: codes.recursive.cat.CatFunction::handleRequest format: http config: apiBaseUrl: https://api.thecatapi.com/v1 apiKey: [redacted] triggers: - name: cat type: http source: /random
The CatFunction class is basic.  A setUp() method, annotated with @FnConfiguration gives access to the function context which contains the config info from the YAML file and initializes the variables for the function.  Then the handleRequest() method makes the HTTP call, again using a client library called Unirest, and returns the JSON containing the link to the crucial cat image.  
public class CatFunction { private String apiBaseUrl; private String apiKey; @FnConfiguration public void setUp(RuntimeContext ctx) { apiBaseUrl = ctx.getConfigurationByKey("apiBaseUrl").orElse(""); apiKey = ctx.getConfigurationByKey("apiKey").orElse(""); } public OutputEvent handleRequest(String input) throws UnirestException { String url = apiBaseUrl + "/images/search?format=json"; HttpResponse<JsonNode> response = Unirest .get(url) .header("Content-Type", "application/json") .header("x-api-key", apiKey) .asJson(); OutputEvent out = OutputEvent.fromBytes( response.getBody().toString().getBytes(), OutputEvent.Status.Success, "application/json" ); return out; } }
To test the function, the team deploys the function locally with:
fn deploy --app cat-svc –local
And tests that it is working:
curl -i \ -H "Content-Type: application/json" \ http://localhost:8080/t/cat-svc/random
Which produces:
HTTP/1.1 200 OK Content-Length: 112 Content-Type: application/json Fn_call_id: 01CRGBAH56NG8G00RZJ0000001 Xxx-Fxlb-Wait: 502.0941ms Date: Fri, 28 Sep 2018 15:04:05 GMT [{"id":"ci","categories":[],"url":"https://24.media.tumblr.com/tumblr_lz8xmo6xYV1r0mbi6o1_500.jpg","breeds":[]}]
Success!  Dominic’s team created the cat service before lunch and spent the rest of the day looking at random cat pictures.
 
Now that all 4 teams have implemented their respective services using various technologies, you might be asking yourself why it was necessary to implement such trivial services on the backend instead of calling the third-party APIs directly from the front end.  There are several reasons but let's take a look at just a few of them:
 
One reason to implement this functionality via a server-based backend is that third-party APIs can be unreliable and/or rate limited.  By proxying the API through their own backend, the teams are able to take advantage of caching and rate limiting of their own design to prevent the demand on the third-party API and get around potential downtime or rate limiting for a service that they have limited or no control over.  
 
Secondly, the teams are given the luxury of controlling the data before it’s sent to the client.  If it is allowed within the API terms and the business needs require them to supplement the data with other third-party or user data they can reduce the client CPU, memory, and bandwidth demands by augmenting or modifying the data before it even gets to the client.
 
Finally, CORS restrictions in the browser can be circumvented by calling the API from the server (and if you've ever had CORS block your HTTP calls in the browser you can definitely appreciate this!).
 
TechCorp has now completed the initial microservice development sprint of their project.  In the next post, we’ll look at how these 4 services can be deployed to a local Kubernetes cluster and we'll also dig into the Angular front end of the application.
 

Microservices From Dev To Deploy, Part 1: Getting Started With Helidon

Wed, 2018-10-03 11:27
.syntaxhighlighter table td.gutter div.line { padding: 0 .5em 0 1em!important; }

Microservices are undoubtedly popular.  There have been plenty of great posts on this blog that explain the advantages of using a microservice approach to building applications (or “why you should use them”).  And the reasons are plentiful:  flexibility to allow your teams to implement different services with their language/framework of choice, independent deployments, and scalability, and improved build and test times are among the many factors that make a microservice approach preferable to many dev teams nowadays.  It’s really not much of a discussion anymore as studies have shown that nearly 86% of respondents believe that a microservice approach will be their default architecture within the next 5 years.  As I mentioned, the question of “why microservices” has long been answered, so in this short blog series, I’d like to answer the question of “how” to implement microservices in your organization. Specifically, how Oracle technologies can help your dev team implement a maintainable, scalable and easy to test, develop, and deploy solution for your microservice applications.

To keep things interesting I thought I’d come up with a fictional scenario that we can follow as we take this journey.  Let’s imagine that a completely fabricated startup called TechCorp has just secured $150M in seed funding for their brilliant new project.  TechCorp’s founder Lydia is very nostalgic and she longs for the “good old days” when 56k modems screeched and buzzed their way down the on-ramp to the “interwebs” and she’s convinced BigCity Venture Capital that personalized homepages are about to make a comeback in a major way.  You remember those, right?  Weather, financials, news – even inspiring quotes and funny cat pictures to brighten your day.  With funding secured Lydia set about creating a multinational corporation with several teams of “rock star” developers across the globe.  Lydia and her CTO Raj know all about microservices and plan on having their teams split up and tackle individual portions of the backend to take advantage of their strengths and ensure a flexible and reliable architecture.

Team #1:
Location:  London
Team Lead:  Chris
Focus:  Weather Service
Language:  Groovy
Framework:  Oracle Helidon SE with Gradle

Team #2:
Location:  Tokyo
Team Lead:  Michiko
Focus:  Quote Service
Language:  Java
Framework:  Oracle Helidon MP with Maven

Team #3:
Location:  Bangalore
Team Lead:  Murielle
Focus:  Stock Service
Language:  JavaScript/Node
Framework:  Express

Team #4:
Location:  Melbourne
Team Lead:  Dominic
Focus:  Cat Picture Service
Language:  Java
Framework Oracle Fn (Serverless)

Team #5
Location:  Atlanta
Team Lead:  Ava
Focus:  Frontend
Language:  JavaScript/TypeScript
Framework:  Angular 6

As you can see, Lydia has put together quite a globally diverse group of teams with a wide-ranging set of skills and experience.  You’ll also notice some non-Oracle technologies in their selections which you might find odd in a blog post focused on Oracle technology, but that’s indicative of many software companies these days.  Rarely do teams focus solely on a single company’s stack anymore.  While we’d love it if they did, the reality is that teams typically have strengths and preferences that come into play.  I’ll show you in this series how Oracle’s new open source Helidon framework and Fn Serverless project can be leveraged to build microservices and serverless functions, but also how a team can deploy their entire stack to Oracle’s cloud regardless of the language or framework used to build the services that comprise their application.  We'll dive slightly deeper into Helidon than an introductory post, so you might want to first read this introductory blog post and the tutorial before you read the rest of this post.

Let’s begin with Team #1 who has been tasked with building out the backend for retrieving a user’s local weather.  They’re a Groovy team, but they’ve heard good things about Oracle’s new microservice framework Helidon so they’ve chosen to use this new project as an opportunity to learn the new framework and see how well it works with Groovy and Gradle as a build tool.  Team lead Chris has read through the Helidon tutorial and created a new application using the quickstart examples so his first task is to transform the Java application that was created into a Groovy application.  The first step for Chris, in this case, is to create a Gradle build file and make sure that it includes all of the necessary Helidon dependencies as well as a Groovy dependency.  Chris also adds a ‘copyLibs’ task to make sure that all of the dependencies end up where they need to when the project is built.  The build.gradle file looks like this:

apply plugin: 'java' apply plugin: 'maven' apply plugin: 'groovy' apply plugin: 'application' mainClassName = 'codes.recursive.weather.Main' group = 'codes.recursive.weather' version = '1.0-SNAPSHOT' description = """A simple weather microservice""" sourceSets.main.resources.srcDirs = [ "src/main/groovy", "src/main/resources" ] sourceCompatibility = 1.8 targetCompatibility = 1.8 tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } ext { helidonversion = '0.10.0' } repositories { maven { url "http://repo.maven.apache.org/maven2" } mavenLocal() mavenCentral() } configurations { localGroovyConf } dependencies { localGroovyConf localGroovy() compile 'org.codehaus.groovy:groovy-all:3.0.0-alpha-3' compile "io.helidon:helidon-bom:${project.helidonversion}" compile "io.helidon.webserver:helidon-webserver-bundle:${project.helidonversion}" compile "io.helidon.config:helidon-config-yaml:${project.helidonversion}" compile "io.helidon.microprofile.metrics:helidon-metrics-se:${project.helidonversion}" compile "io.helidon.webserver:helidon-webserver-prometheus:${project.helidonversion}" compile group: 'com.mashape.unirest', name: 'unirest-java', version: '1.4.9' testCompile 'org.junit.jupiter:junit-jupiter-api:5.1.0' } // define a custom task to copy all dependencies in the runtime classpath // into build/libs/libs // uses built-in Copy task copyLibs(type: Copy) { from configurations.runtime into 'build/libs/libs' } // add it as a dependency of built-in task 'assemble' copyLibs.dependsOn jar copyDocker.dependsOn jar copyK8s.dependsOn jar assemble.dependsOn copyLibs assemble.dependsOn copyDocker assemble.dependsOn copyK8s // default jar configuration // set the main classpath jar { archiveName = "${project.name}.jar" manifest { attributes ('Main-Class': "${mainClassName}", 'Class-Path': configurations.runtime.files.collect { "libs/$it.name" }.join(' ') ) } }

With the build script set up Chris’ team goes about building the application.  Helidon SE makes it pretty easy to build out a simple service.  To get started you only really need a few classes:  A Main.groovy (notice that the Gradle script indentifies the mainClassName with a path to Main.groovy) which creates the server, sets up routing, configures error handling and optionally sets up metrics for the server.  Here’s the entire Main.groovy:

final class Main { private Main() { } private static Routing createRouting() { MetricsSupport metricsSupport = MetricsSupport.create() MetricRegistry registry = RegistryFactory .getRegistryFactory() .get() .getRegistry(MetricRegistry.Type.APPLICATION) return Routing.builder() .register("/weather", new WeatherService()) .register(metricsSupport) .error( NotFoundException.class, {req, res, ex -> res.headers().contentType(MediaType.APPLICATION_JSON) res.status(404).send(new JsonGenerator.Options().build().toJson(ex)) }) .error( Exception.class, {req, res, ex -> ex.printStackTrace() res.headers().contentType(MediaType.APPLICATION_JSON) res.status(500).send(new JsonGenerator.Options().build().toJson(ex)) }) .build() } static void main(final String[] args) throws IOException { startServer() } protected static WebServer startServer() throws IOException { // load logging configuration LogManager.getLogManager().readConfiguration( Main.class.getResourceAsStream("/logging.properties")) // By default this will pick up application.yaml from the classpath Config config = Config.create() // Get webserver config from the "server" section of application.yaml ServerConfiguration serverConfig = ServerConfiguration.fromConfig(config.get("server")) WebServer server = WebServer.create(serverConfig, createRouting()) // Start the server and print some info. server.start().thenAccept( { NettyWebServer ws -> println "Web server is running at http://${config.get("server").get("host").asString()}:${config.get("server").get("port").asString()}" }) // Server threads are not demon. NO need to block. Just react. server.whenShutdown().thenRun({ it -> Unirest.shutdown() println "Web server has been shut down. Goodbye!" }) return server } }

Heldion SE uses a YAML file located in src/main/resources (named application.yaml) for configuration.  You can store server related config, as well as any application variables in this file.  Chris’ team puts a few variables related to the API in this file:

app: apiBaseUrl: "https://api.openweathermap.org/data/2.5" apiKey: "[redacted]" server: port: 8080 host: 0.0.0.0

Looking back at the Main class, notice on line 13 where the endpoint “/weather” is registered and pointed at the WeatherService. That’s the class that’ll do all the heavy lifting when it comes to getting weather data.  Helidon SE services implement the Service interface.  This class has an update() method that is used to establish sub-routes for the given service and point those sub-routes at private methods of the service class.  Here’s what Chris’ team came up with for the update() method:

void update(Routing.Rules rules) { rules .any(this::countAccess as Handler) .get("/current/city/{city}", this::getByLocation as Handler) .get("/current/id/{id}", this::getById as Handler) .get("/current/lat/{lat}/lon/{lon}", this::getByLatLon as Handler) .get("/current/zip/{zip}", this::getByZip as Handler) }

Chris’ team creates 4 different routes under “/weather” giving the consumer the ability to get the current weather in 4 separate ways (by city, id, lat/lon or zip code).  Note that since we’re using Groovy we have to cast the method references as io.helidon.webserver.Handler or we’ll get an exception.  We’ll take a quick look at just one of those methods, getByZip():

private void getByZip(ServerRequest request, ServerResponse response) { def zip = request.path().param("zip") def weather = getWeather([ (ZIP): zip ]) response.headers().contentType(MediaType.APPLICATION_JSON) response.send(weather.getBody().getObject().toString()) }

The getByZip() method grabs the zip parameter from the request and calls getWeather(), which uses a client library called Unirest to make an HTTP call to the chosen weather API and returns the current weather to getByZip() which sends the response to the browser as JSON:

private HttpResponse<JsonNode> getWeather(Map params) { return Unirest .get("${baseUrl}/weather?${params.collect { it }.join('&')}&appid=${apiKey}") .asJson() }

As you can see, each service method gets passed two arguments when called by the router – the request and response (as you might have guessed if you’ve worked with a microservice framework before).  These arguments allow the developer to grab URL parameters, form data or headers from the request and set the status, body or headers into the response as necessary.  Once the team builds out the entire weather service they are ready to execute the Gradle run task to see everything working in the browser.

weather-service-response

Cloudy in London?  A shocking weather development!

There’s obviously more to Helidon SE, but as you can see it doesn’t take a lot of code to get a basic microservice up and running. We’ll take a look at deploying the services in a later post, but Helidon makes that step trivial with baked in support for generating Dockerfiles and Kubernetes config files. 

Let’s switch gears now and look at Michiko’s team who was tasked with building out a backend to return random quotes since no personalized homepage would be complete without such a feature.  The Tokyo team prefers to code in Java and they use Maven to manage compilation and dependencies.  They are quite familiar with the Microprofile family of APIs.  Michiko and team also decided to use Helidon, but with their Microprofile expertise, they decided to go with Helidon MP over the more reactive functional style of SE because it provides recognizable APIs like JAX-RS and CDI that they have been using for years.  Like Chris’ team, they rapidly scaffold out a skeleton application with the MP quickstart archetype and set out configuring their Main.java class.  The main method of that class calls startServer() which is slightly different from the SE method, but accomplishes the same task – starting up the application server using a config file (this one named microprofile-config.properties and located in /src/main/resources/META-INF):

protected static Server startServer() throws IOException { // load logging configuration LogManager.getLogManager().readConfiguration( Main.class.getResourceAsStream("/logging.properties")); // Server will automatically pick up configuration from // microprofile-config.properties Server server = Server.create(); server.start(); return server; }

Next, they create a beans.xml file in /src/main/resources/META-INF so the CDI implementation can pick up their classes:

<!--?xml version="1.0" encoding="UTF-8"?--> <beans> </beans>

Create the JAX-RS application, adding the resource class(es) as needed:

@ApplicationScoped @ApplicationPath("/") public class QuoteApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> set = new HashSet<>(); set.add(QuoteResource.class); return Collections.unmodifiableSet(set); } }

And create the QuoteResource class:

@Path("/quote") @RequestScoped public class QuoteResource { private static String apiBaseUrl = null; @Inject public QuoteResource(@ConfigProperty(name = "app.api.baseUrl") final String apiBaseUrl) { if (this.apiBaseUrl == null) { this.apiBaseUrl = apiBaseUrl; } } @SuppressWarnings("checkstyle:designforextension") @Path("/random") @GET @Produces(MediaType.APPLICATION_JSON) public String getRandomQuote() throws UnirestException { String url = apiBaseUrl + "/posts?filter[orderby]=rand&filter[posts_per_page]=1"; HttpResponse<JsonNode> quote = Unirest.get(url).asJson(); return quote.getBody().toString(); } }

Notice the use of constructor injection to get a configuration property and the simple annotations for the path, HTTP method and content type of the response. The getRandomQuote() method again uses Unirest to make a call to the quote API and return the result as a JSON string.  Running the mvn package task and executing the resulting JAR starts the application running and results in the following:

quote-service-responseMichiko’s team has successfully built the initial implementation of their quote microservice on a flexible foundation that will allow the service to grow with time as the user base expands and additional funding rolls in from the excited investors!  As with the SE version, Helidon MP generates a Dockerfile and Kubernetes app.yaml file to assist the team with deployment.  We’ll look at deployment in a later post in this series.

In this post, we talked about a fictitious startup getting into microservices for their heavily funded internet homepage application.  We looked at the Helidon microservice framework which provides a reactive, functional style version as well as a Microprofile version more suited to Java EE developers who are comfortable with JAX-RS and CDI.  Lydia’s teams are moving rapidly to get their backend architecture built out and are well on their way to implementing her vision for TechCorp.  In the next post, we’ll look at how Murielle and Dominic’s teams build out their services and in future posts we’ll see how all of the teams ultimately test and deploy the services into production.

Oracle Offline Persistence Toolkit — After Request Sync Listener

Thu, 2018-09-27 21:30
.oracle-singlepageview__featuredimage, .cb11v2-cover{display:none !important;}

Originally published at andrejusb.blogspot.com 

In my previous post, we learned how to handle replay conflict — Oracle Offline Persistence Toolkit — Reacting to Replay Conflict. Additional important thing to know — how to handle response from request which was replayed during sync (we are talking here about PATCH). It is not as obvious as handling response from direct REST call in callback (there is no callback for response which is synchronised later). You may think, why you would need to handle response, after successful sync. Well there could be multiple reasons — for instance you may read returned value and update value stored on the client.

Listener is registered in Persistence Manager configuration, by adding event listener of type syncRequest for given endpoint:


This is listener code. We are getting response, reading change indicator value (it was updated on the backend and new value is returned in response) and storing it locally on the client. Additionally we maintain array with mapping of change indicator value to updated row ID (in my next post I will explain why this is needed). After request listener must return promise:


On runtime — when request sync is executed, you should see in the log message printed, which shows new change indicator value:


Double check in payload, to make sure request was submitted with previous value:


Check response, you will see new value for change indicator (same as in after request listener):


Sample code can be downloaded from GitHub repository

Which Way to Go: Code One Presenters Help You Select Which Sessions to Attend

Thu, 2018-09-27 19:54

According to the Oracle Code One session catalog, there are 625 HOLs, BOFs, and other sessions for you to choose from when planning your itinerary over the 3 1/2 days of that event. Math was never my strong suit, but by my calculation that's roughly 15 sessions for every hour the doors are open. Unless you have developed the Dr. Manhattan-like ability to be in several places at once, you're going to have to make some tough decisions about which sessions to attend.

In the interest of helping you to make that choice we've put together a series of interviews with 30 of the most recognized and influential thought-leaders who are presenting at Code One. Each video provides you with deep technical background on the sessions these pros will present, and you'll even learn about the sessions they plan to attend.

The videos below are just a sample to get you started.

Chris Richardson

Eventuate founder and Java Champion Chris Richardson is the go-to pro for expertise on microservice architecture. In this interview he previews his session Developing Message-Driven Asynchronous Microservices, and talks about his upcoming book, Microservices Patterns (2018, Manning Publications).

Sebastian Daschner

No stranger to developer conferences, Java Champion/Developer Champion Sebastian Daschner will present four Code One technical sessions, and serve as a keynote panelist. What can you expect from these appearances? Who better to explain than Sebastian himself?

Trisha Gee

The ever-busy Trisha Gee, developer advocate at JetBrains and a Java Champion, will travel from her home in Spain all the way to San Francisco to present five sessions at Code One. Trisha takes you into the nuts and bolts of each session in this preview.

Josh Long

Java Champion Josh Long, Spring Developer Advocate at Pivotal, teams up with Trisha Gee at Code One to present Fully Reactive: Spring, Kotlin, JavaFX, and MongoDB Playing Together. Why should you add this session to your schedule? We'll let Josh explain.

 

While this is just a small sampling of the full schedule of Code One sessions, we hope these videos will provide some help in building out your itinerary. Of course, with the stellar roster of Code One presenters, any way you go will be OK. There are no bad choices.

  Additional Resources

Complete Code One Preview Playlist

Code One Featured Speakers

Code One Session Catalog

Code One Home Page

 

Generic Docker Container Image for running and live reloading a Node application based on a ...

Fri, 2018-09-21 21:30

Originally published at technology.amis.nl

My desire: find a way to run a Node application from a Git(Hub) repository using a generic Docker container and be able to refresh the running container on the fly whenever the sources in the repo are updated. The process of producing containers for each application and upon each change of the application is too cumbersome and time consuming for certain situations — including rapid development/test cycles and live demonstrations. I am looking for a convenient way to run a Node application anywhere I can run a Docker container — without having to build and push a container image — and to continuously update the running application in mere seconds rather than minutes. This article describes what I created to address that requirement.

Key ingredient in the story: nodemon — a tool that monitors a file system for any changes in a node.js application and automatically restarts the server when there are such changes. What I had to put together:

a generic Docker container based on the official Node image — with npm and a git client inside

  • adding nodemon (to monitor the application sources)
  • adding a background Node application that can refresh from the Git repository — upon an explicit request, based on a job schedule and triggered by a Git webhook
  • defining an environment variable GITHUB_URL for the url of the source Git repository for the Node application
  • adding a startup script that runs when the container is ran first (clone from Git repo specified through GITHUB_URL and run application with nodemon) or restarted (just run application with nodemon)

I have been struggling a little bit with the Docker syntax and operations (CMD vs RUN vs ENTRYPOINT) and the Linux bash shell scripts — and I am sure my result can be improved upon.

The Dockerfile that builds the Docker container with all generic elements looks like this:

FROM node:8 #copy the Node Reload server - exposed at port 4500 COPY package.json /tmp COPY server.js /tmp RUN cd tmp && npm install EXPOSE 4500 RUN npm install -g nodemon COPY startUpScript.sh /tmp COPY gitRefresh.sh /tmp CMD ["chmod", "+x", "/tmp/startUpScript.sh"] CMD ["chmod", "+x", "/tmp/gitRefresh.sh"] ENTRYPOINT ["sh", "/tmp/startUpScript.sh"]

Feel free to pick any other node base image — from https://hub.docker.com/_/node/. For example: node:10.

The startUpScript that is executed whenever the container is started up — that takes care of the initial cloning of the Node application from the Git(Hub) URL to directory /tmp/app and the running of that application using nodemon is shown below. Note the trick (inspired by StackOverflow) to run a script only when the container is ran for the very first time.

#!/bin/sh CONTAINER_ALREADY_STARTED="CONTAINER_ALREADY_STARTED_PLACEHOLDER" if [ ! -e $CONTAINER_ALREADY_STARTED ]; then touch $CONTAINER_ALREADY_STARTED echo "-- First container startup --" # YOUR_JUST_ONCE_LOGIC_HERE cd /tmp # prepare the actual Node app from GitHub mkdir app git clone $GITHUB_URL app cd app #install dependencies for the Node app npm install #start both the reload app and (using nodemon) the actual Node app cd .. (echo "starting reload app") & (echo "start reload";npm start; echo "reload app finished") & cd app; echo "starting nodemon for app cloned from $GITHUB_URL"; nodemon else echo "-- Not first container startup --" cd /tmp (echo "starting reload app and nodemon") & (echo "start reload";npm start; echo "reload app finished") & cd app; echo "starting nodemon for app cloned from $GITHUB_URL"; nodemon fi The startup script runs the live reloader application in the background — using (echo “start reload”;npm start)&. That final ampersand (&) takes care of running the command in the background. This npm start command runs the server.js file in /tmp. This server listens at port 4500 for requests. When a request is received at /reload, the application will execute the gitRefresh.sh shell script that performs a git pull in the /tmp/app directory where the git clone of the repository was targeted.

 

const RELOAD_PATH = '/reload' const GITHUB_WEBHOOK_PATH = '/github/push' var http = require('http'); var server = http.createServer(function (request, response) { console.log(`method ${request.method} and url ${request.url}`) if (request.method === 'GET' && request.url === RELOAD_PATH) { console.log(`reload request starting at ${new Date().toISOString()}...`); refreshAppFromGit(); response.write(`RELOADED!!${new Date().toISOString()}`); response.end(); console.log('reload request handled...'); } else if (request.method === 'POST' && request.url === GITHUB_WEBHOOK_PATH) { let body = []; request.on('data', (chunk) => { body.push(chunk);}) .on('end', () => { body = Buffer.concat(body).toString(); // at this point, `body` has the entire request body stored in it as a string console.log(`GitHub WebHook event handling starting ${new Date().toISOString()}...`); ... (see code in GitHub Repo https://github.com/lucasjellema/docker-node-run-live-reload/blob/master/server.js console.log("This commit involves changes to the Node application, so let's perform a git pull ") refreshAppFromGit(); response.write('handled'); response.end(); console.log(`GitHub WebHook event handling complete at ${new Date().toISOString()}`); }); } else { // respond response.write('Reload is live at path '+RELOAD_PATH); response.end(); } }); server.listen(4500); console.log('Server running and listening at Port 4500'); var shell = require('shelljs'); var pwd = shell.pwd() console.info(`current dir ${pwd}`) function refreshAppFromGit() { if (shell.exec('./gitRefresh.sh').code !== 0) { shell.echo('Error: Git Pull failed'); shell.exit(1); } else { } }

Using the node-run-live-reload image
Now that you know a little about the inner workings of the image, let me show you how to use it (also see instructions here: https://github.com/lucasjellema/docker-node-run-live-reload).

To build the image yourself, clone the GitHub repo and run

docker build -t "node-run-live-reload:0.1" .

using of course your own image tag if you like. I have pushed the image to Docker Hub as lucasjellema/node-run-live-reload:0.1. You can use this image like this:

docker run --name express -p 3011:3000 -p 4505:4500 -e GITHUB_URL=https://github.com/shapeshed/express_example -d lucasjellema/node-run-live-reload:0.1

In the terminal window — we can get the logging from within the container using

docker logs express --follow

After the application has been cloned from GitHub, npm has installed the dependencies and nodemon has started the application, we can access it at <host>:3011 (because of the port mapping in the docker run command):


When the application sources are updated in the GitHub repository, we can use a GET request (from CURL or the browser) to <host>:4505 to refresh the container with the latest application definition:


The logging from the container indicates that a git pull was performed — and returned no new sources:


Because there are no changed files, nodemon will not restart the application in this case.

One requirement at this moment for this generic container to work is that the Node application has a package.json with a scripts.start entry in its root directory; nodemon expects that entry as instruction on how to run the application. This same package.json is used with npm install to install the required libraries for the Node application.

Summary

The next figure gives an overview of what this article has introduced. If you want to run a Node application whose sources are available in a GitHub repository, then all you need is a Docker host and these are your steps:

  1. Pull the Docker image: docker pull lucasjellema/node-run-live-reload:0.1 (this image currently contains the Node 8 runtime, npm, nodemon, a git client and the reloader application) 
    Alternatively: build and tag the container yourself.
  2. Run the container image, passing the GitHub URL of the repo containing the Node application; specify required port mappings for the Node application and the reloader (port 4500): docker run –name express -p 3011:3000 -p 4500:4500 -e GITHUB_URL=<GIT HUB REPO URL> -d lucasjellema/node-run-live-reload:0.1
  3. When the container is started, it will clone the Node application from GitHub
  4. Using npm install, the dependencies for the application are installed
  5. Using nodemon the application is started (and the sources are monitored so to restart the application upon changes)
  6. Now the application can be accessed at the host running the Docker container on the port as mapped per the docker run command
  7. With an HTTP request to the /reload endpoint, the reloader application in the container is instructed to
  8. git pull the sources from the GitHub repository and run npm install to fetch any changed or added dependencies
  9. if any sources were changed, nodemon will now automatically restart the Node application
  10. the upgraded Node application can be accessed

Note: alternatively, a WebHook trigger can be configured. This makes it possible to automatically trigger the application reload facility upon commits to the GitHub repo. Just like a regular CD pipeline this means running Node applications can be automatically upgraded.


Next Steps

Some next steps I am contemplating with this generic container image — and I welcome your pull requests — include:

  • allow an automated periodic application refresh to be configured through an environment variable on the container (and/or through a call to an endpoint on the reload application) instructing the reloader to do a git pull every X seconds.
  • use https://www.npmjs.com/package/simple-git instead of shelljs plus local Git client (this could allow usage of a lighter base image — e.g. node-slim instead of node)
  • force a restart of the Node application — even it is not changed at all
  • allow for alternative application startup scenarios besides running the scripts.start entry in the package.json in the root of the application
Resources

GitHub Repository with the resources for this article — including the Dockerfile to build the container: https://github.com/lucasjellema/docker-node-run-live-reload

My article on my previous attempt at creating a generic Docker container for running a Node application from GitHub: https://technology.amis.nl/2017/05/21/running-node-js-applications-from-github-in-generic-docker-container/

Article and Documentation on nodemon: https://medium.com/lucjuggery/docker-in-development-with-nodemon-d500366e74df and https://github.com/remy/nodemon#nodemon

NPM module shelljs that allows shell commands to be executed from Node applications: https://www.npmjs.com/package/shelljs

Podcast: DevOps to NoOps: State of Play

Tue, 2018-09-18 23:00

What is the current state of play in DevOps? What forces are having the greatest impact on the evolution and adoption of DevOps? Is NoOps a valid prospect for the future? Those questions notwithstanding, one thing is certain: while everybody is talking about DevOps, getting from talk to action is proving to be a substantial hurdle for many organizations.

"What I see so far is lack of knowledge," says podcast panelist Davide Fiorentino. "People don't know the tools. Most of the time they don't know what they are talking about." In some cases the problem can be a lot like trying to turn a battleship.

As panelist Bert Jan Schrijver explains, "it's typically easier for smaller organizations to move to a definite way of working, and a bit harder for larger organizations," where the stakes can be high. "I typically try to find organization projects to work on where the IT department has no more than 50 to 60 people. Then there's a good opportunity to get the organization in the right mindset and to get everybody on deck."

But in Bert's experience, smaller doesn't always mean easier. "It can be easier to convince 1500 people who have the same mindset than 50 people who are basically against all that you're saying."

In that situation management support can be invaluable. "It's always been about having unconditional support in all levels of the organization, especially in management," Bert says. "Because when you're changing an organization you're always going to hit resistance. And if you're going to get resistance from somebody who's higher up in the tree than you, then you better have support from that person's manager."

"The key to working as a DevOps team is not being blocked by people or departments outside your team that you don't have influence on," Bert adds. "A true DevOps team is a cross-functional team which is a team that can do anything necessary to go from idea to working software in production."

"That's a very important point!" agrees Michael. "I really appreciate the ops guys having strong experiences and skills about non-functional parts of the solution, and running and scaling out infrastructure."

Of course, there is a lot more to getting from DevOps talk to real transformation, and what you're reading here is only a fraction of the insight Davide, Bert, and Michael offer in this podcast. So strap on your headphones and dig in.

BTW: Each of these panelists have sessions on the schedule for Oracle Code One, Oct 22-25, 2018 in San Francisco, CA. If you haven't already done so, there's plenty of time to register for that event. You'll find information on those sesssion below.

Special thanks to my Developer Community colleague Javed Mohammed for his help in organizing this program, and for co-hosting the discussion.

The Panelists Davide Fiorentino
Principal DevOps Engineer, Cambridge Broadband Networks Limited (CBNL)
Consultant, Food and Agriculture Organization, United Nations

Twitter LinkedIn

Code One Session:

  • DevOps in Action [BOF5289]
    Monday, Oct 22, 7:30 p.m. - 8:15 p.m. | Moscone West - Room 2009
Michael Hutterman
Java Champion
Oracle Developer Champion
Independent DevOps Consultant

Twitter LinkedIn

Code One Session:
  • Continuous Delivery/DevOps: Live Cooking Show [DEV4762]
    Monday, Oct 22, 2:30 p.m. - 3:15 p.m. | Moscone West - Room 2010
Bert Jan Schrijver
Java Champion
Oracle Developer Champion
CTO, OpenValue
Software Craftsman, JPoint

Twitter LinkedIn

Code One Sessions:
  • Better Software, Faster: Principles of Continuous Delivery and DevOps [DEV5118]
    Monday, Oct 22, 4:00 p.m. - 4:45 p.m. | Moscone West - Room 2010
  • Angular for Java Developers [DEV4345]
    Wednesday, Oct 24, 10:30 a.m. - 11:15 a.m. | Moscone West - Room 2003
  • Microservices in Action at the Dutch National Police [DEV4344]
    Monday, Oct 22, 2:30 p.m. - 3:15 p.m. | Moscone West - Room 2007
Javed Mohammed
Podcast Co-Host
Systems Community Manager, Oracle

Twitter LinkedIn 


Additional Resources Coming Soon

Talking about microservices is a useful thing. But at some point the talk has to stop and the real work has to begin. And that's when the real challenges appear. In this upcoming podcast a panel of experts discusses how to overcome the challenges inherent in designing microservices that will fulfill their potential.

Subscribe

Never miss an episode! The Oracle Developer Community Podcast is available via:

Connecting to Autonomous Transaction Processing Database from a Node. ...

Thu, 2018-09-13 18:53
Introduction

In this tutorial I demonstrate how to connect an app written in Python, Node.js or PHP running in Oracle Cloud Infrastructure(OCI) to an Autonomous Transaction Processing (ATP) Database running in Oracle Cloud. To complete these steps, it is assumed you have either a baremetal or VM shape running Oracle Linux with a public IP address in Oracle Cloud Infrastructure, and that you have access to Autonomous Transaction Processing Database Cloud Service. I used Oracle Linux 7.5

We've recently added Oracle Instant Client to the Oracle Linux yum mirrors in each OCI region, which has simplified the steps significantly. Previously, installing Oracle Instant Client required either registering a system with ULN or downloading from OTN, each with manual steps to accept license terms. Now you can simply use yum install directly from Oracle Linux running in OCI. For this example, I use a Node.js app, but the same principles apply to Python with cx_Oracle, PHP with php-oci8 or any other language that can connect to Oracle Database with an appropriate connector via Oracle Instant Client.



Overview Installing Node.js, node-oracledb and Oracle Instant Client Grab the Latest Oracle Linux Yum Mirror Repo File

This steps will ensure you have an updated repo file local to your OCI region with a repo definition for OCI-included software such as Oracle Instant Client. Note that I obtain the OCI region from the instance metadata service via an HTTP endpoint that every OCI instance has access to via the address 169.254.169.254. After connecting to your OCI compute instance via ssh, run the following commands:

cd /etc/yum.repos.d sudo mv public-yum-ol7.repo public-yum-ol7.repo.bak export REGION=`curl http://169.254.169.254/opc/v1/instance/ -s | jq -r '.region'| cut -d '-' -f 2` sudo -E wget http://yum-$REGION.oracle.com/yum-$REGION-ol7.repo

Enable yum repositories for Node.js and Oracle Instant Client

Next, enable the required repositories to install Node.js 10 and Oracle Instant Client

sudo yum install -y yum-utils sudo yum-config-manager --enable ol7_developer_nodejs10 ol7_oci_included

Install Node.js, node-oracledb and Oracle Instant Client

To install Node.js 10 from the newly enabled repo, we'll need to make sure the EPEL repo is disabled. Otherwise, Node.js from that repo may be installed and that's not the Node we are looking for. Also, note the name of the node-oracledb package for Node.js 10 is node-oracledb-12c-node10. Oracle Instant Client will be installed automatically as a dependency of node-oracledb.

sudo yum --disablerepo="ol7_developer_EPEL" -y install nodejs node-oracledb-12c-node10

Add Oracle Instant Client to the runtime link path. sudo sh -c "echo /usr/lib/oracle/12.2/client64/lib > /etc/ld.so.conf.d/oracle-instantclient.conf" sudo ldconfig

Using Oracle Instant Client Download Wallet and Configure Wallet Location

To connect to ATP via SQL*Net, you'll need Oracle client credentials. An ATP service administrator can download these via the service console. See this documentation for more details.

Figure 1. Downloading Client Credentials (Wallet) from Autonomous Transaction Processing Service Console

Once you've obtained the wallet archive for your ATP Database, copy it to your OCI instance, unzip it and set the permissions appropriately. First prepare a location to store the wallet.

sudo mkdir -pv /etc/ORACLE/WALLETS/ATP1 sudo chown -R opc /etc/ORACLE

Copy the wallet from the machine to which you've downloaded it to the OCI instance. Here I'm copying the file wallet_ATP1.zip from my development machine using scp. Note that I'm using an ssh key file that matches the ssh key I created the instance with.

Note: this next command is run on your development machine to copy the downloaded Wallet zip file to your OCI instance. In my case, wallet_ATP1.zip was downloaded to ~/Downloads on my MacBook. scp -i ~/.ssh/oci/oci ~/Downloads/wallet_ATP1.zip opc@<OCI INSTANCE PUBLIC IP>:/etc/ORACLE/WALLETS/ATP1

Returning to the OCI instance, unzip the wallet and set the permissions appropriately.

cd /etc/ORACLE/WALLETS/ATP1 unzip wallet_ATP1.zip sudo chmod -R 700 /etc/ORACLE

Edit sqlnet.ora to point to the Wallet location, replacing ?/network/admin. After editing sqlnet.ora should look something like this.

cat /etc/ORACLE/WALLETS/ATP1/sqlnet.ora WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="/etc/ORACLE/WALLETS/ATP1"))) SSL_SERVER_DN_MATCH=yes

Set the TNS_ADMIN environment variable to point Instant Client the Oracle configuration directory as well as NODE_PATH so that the node-oracledb module can be found by our Node.js program.

export TNS_ADMIN=/etc/ORACLE/WALLETS/ATP1 export NODE_PATH=`npm root -g`

Create and run a Node.js Program to Test Connection to ATP

Create a file, select.js based on the example below. Either assign values to the environment variables NODE_ORACLEDB_USER, NODE_ORACLEDB_PASSWORD, and NODE_ORACLEDB_CONNECTIONSTRING to suit your configuration or edit the placeholder values USERNAME, PASSWORD and CONNECTIONSTRING in the code below. The former being the username and password you've been given for ATP and the latter being one of the service descriptors in the $TNS_ADMIN/tnsnames.ora file.

'use strict'; const oracledb = require('oracledb'); async function run() { let connection; try { connection = await oracledb.getConnection({ user: process.env.NODE_ORACLEDB_USER || "USERNAME", password: process.env.NODE_ORACLEDB_PASSWORD || "PASSWORD", connectString: process.env.NODE_ORACLEDB_CONNECTIONSTRING || "CONNECTIONSTRING" }); let result = await connection.execute("select sysdate from dual"); console.log(result.rows[0]); } catch (err) { console.error(err); } finally { if (connection) { try { await connection.close(); } catch (err) { console.error(err); } } } } run();

Run It!

Let's run our Node.js program. You should see a date returned from the Database.

node select.js [ 2018-09-13T18:19:54.000Z ] Important Notes

As there currently isn't a service gateway to connect from Oracle Cloud Infrastructure to Autonomous Transaction Processing, any traffic between these two will count against your network quota.

Conclusion

In this blog post I've demonstrated how to run a Node.js app on an Oracle Linux instance in Oracle Cloud Infrastructure (OCI) and connect it to Autonomous Transaction Processing Database by installing all necessary software —including Oracle Instant Client— directly from yum servers within OCI itself. By offering direct access to essential Oracle software from within Oracle Cloud Infrastructure, without requiring manual steps to accept license terms, we've made it easier for developers to build Oracle-based applications on Oracle Cloud.



References

Revisiting the Performance & Scalability of Java Applications that use RDBMSes

Mon, 2018-09-03 13:30

Originally published at db360.blogspot.com.

A re-edition of my recent blog post.

There is an abundant literature on Java performance (books, articles, blogs, websites, and so on); a Google search returns more than 5 millions hits. To name a few, the Effective Java programming language guide, Java Performance the definitive guide, Java performance tuning newsletter and its associated website
This blog post revisits the known best practices for speeding up and scaling database operations for Java applications then discusses new mechanisms such as database proxies, and the Asynchronous Database Access (ADBA) proposal.

Speeding up RDBMS operations in Java apps

Optimizing database operations for Java applications includes: speeding up database connectivity, speeding up SQL statements processing, optimizing network traffic, and in-place processing.

Speeding up Database Connectivity

Connection establishment is the most expensive database operation; the obvious optimization that Java developers have been using for ages is connection pooling which avoid creating connections at runtime (unless you exhaust the pool capacity.

Client-side Connection Pools

Java connection pools such as the Apache Commons DBCP, C3P0, the Oracle Universal Connection Pool (UCP) and so on, are libraries to be used as part of your stand-alone Java applications or as part of the datasource of Java EE containers e.g.,Tomcat, Weblogic, WebSphere and others. Java EE containers embed their own connection pools but also allow 3rd party pools (e.g., using Using UCP with Tomcat, Using UCP with Weblogic). 
 
Most Java applications use client-side or mid-tier connection pools to support small and medium workloads however, these pools are confined to the JRE/JDK instance (i.e., can’t be shared beyond their boundaries) and unpractical when deploying tens of thousands of mid-tiers or Web servers. Even with a very small pool size on each web tier, the RDBMS server is overwhelmed by thens of thousands of pre-allocated connections that are idle more than 90% of the time.

Proxy Connection Pools 

Database proxies such as MySQL Router, the Oracle Database Connection Manager in Traffic Director Mode (CMAN-TDM), NGINX and others, are proxy servers that sit between the database clients (i.e., Java apps, Web tiers) and the RDBMS. These allow thousands of mid-tiers to share a common connection pool. See database proxy in the second part of this blog.

The Oracle database furnishes in addition, database-side connection pools such as the Shared Servers, and the Database Resident Connection Pool (DRCP); these will not be discussed in this post.

Misc. Connection Optimizations

Other connection optimization features include: deferring connection health check, and de-prioritization of failed nodes.

Deferring Connection Health Check 
The ability of a connection pool to defer the health checking of connections for a defined period of time, fastens connection check-out (i.e., getConnection() returns faster).
 
De-prioritization of Failed Nodes
In a multi-instances clustered database environment such as Oracle RAC, this feature assigns a low priority to a failed instance for a defined period of time (iow, avoids attempts to get connections from the failed instance) thereby speeding up connection check-out.

Speeding up SQL Statements Processing

Processing a SQL statement requires several steps including: parsing (at least once), binding variables, executing, fetching resultSets (if a query), and COMMITting or ROLLBACKing the transaction (if a DML i.e., Insert, Update, or Delete). 
JDBC furnishes several APIs/knobs for optimizing SQL statements processing including: Prepared Statements, Statements Caching, and ResultSets caching.

Disabling Default COMMIT

Auto-COMMITTING each DML is the default/implicit transaction mode in JDBC . Unless this mode corresponds to your desire, you should explicitly disable it on the connection object and demarcate your transactions (DML + Queries) with explicit COMMIT or ROLLBACK calls.

i.e., conn.setAutoCommit(false);

Prepared Statements

Ahead of its execution, a SQL statement must be parsed, if not already. Parsing (i.e., hard parsing) is the most expensive operation when processing a SQL statement. The best practice consists in using Prepared Statements which are parsed once then reused many times on subsequent invocations, after setting new values for the bind variables. A security byproduct of Prepared Statements is the prevention of SQL injection.

Statements Caching

The JDBC driver may be directed to automatically cache SQL statements (PreparedStatements and CallableStatements) on smt.close(). On subsequent invocation of the same statements, the driver directs the RDBMS to use an existing statement (i.e., “use statement #2) without sending the statement string, thereby avoiding soft parsing (lexical analysis, syntactic parsing) and potentially a network roundtrip.

Implicit statement caching is enabled either on the connection object or the datasource object (note: the statement cache is an array per physical connection).


ResultSets Caching with Change Notification — the Hard Way

Caching JDBC result sets avoids re-executing the corresponding SQL query, resulting in dramatic Java applications performance. RDBMSes allow caching ResultSet at the server side however, applications needs roundtrips to the database to retrieve it. This topic is discussed at length in chapter 15th of the Oracle database performance tuning guide.

Optimizing further, these result set can be pushed to the drivers (Java, C/C++, PHP, C#, and so on) and consumed by the applications without database roundtrips. What if the ResultSets become stale, out of sync with the actual data in the RDBMS table? RDBMSes furnish mechanisms for maintaining the ResultSets up to date thereby ensuring the consistency of the cached ResultSets. For example, the Oracle database’s Query Change Notifications allows registering a SQL query with the RDBMS and receiving notifications when committed DMLs from other threads render the ResultSets out of sync.

Java applications may explicitly implement ResultSet caching with change notification through the following steps:

0) Prerequisites: the server-side ResultSet caching must be enabled and database user schema must be granted the “CHANGE NOTIFICATION” privilege.
 e.g., grant change notification to HR; // might need your DBA’s help.

1) Create “a registration” on the connection object

// Creating a registration for Query Change Notiication // OracleConnection conn = ods.getConnection(); Properties prop = new Properties(); prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true"); prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION,"true"); // ... DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotifictaion(prop); // ...

 

2) Associate a query with the registration

Statement stmt = conn.createStatement(); // associating the query with the registration ((OracleStatement)stmt).setDatabaseChangeRegistration(dcr); /* * any query that will be executed with the 'stmt' object will be associated with * the registration 'dcr' until 'stmt' is closed or * '((OracleStatement)stmt).setDatabaseChangeRegistration(null);' is executed. */ ...


3) Listen to the notification

/* * Attach a listener to the registration. * Note: DCNListener is a custom listener and not a predefined or standard * listener */ DCNListener list = new DCNListener(); dcr.addListener(list); catch(SQLException ex) { /* * if an exception occurs, we need to close the registration in order * to interrupt the thread otherwise it will be hanging around. */ if(conn != null) conn.unregisterDatabaseChangeNotification(dcr); throw ex; }


See more details in chapter 26 of the Oracle JDBC Developers guide.

ResultSets Caching with Change Notification — the Easier Way

You may, preferably, enable client-side ResulSet caching with invalidation in a much easier way, using the following steps (available with the Oracle JDBC driver release 18.3 and up)

1) Set the following parameters in the database configuration file a.k.a. INIT.ORA.

CLIENT_RESULT_CACHE_SIZE=100M // example: maximum cache size, in bytes CLIENT_RESULT_CACHE_LAG=1000 // example: maximum delay for refreshing the cache (msec)

2) Set the JDBC connection property oracle.jdbc.enableQueryResultCache to true (the default).

3) add the following hint to the SQL query string “/*+ RESULT_CACHE */”

SELECT /*+ RESULT_CACHE */ product_name, unit_price FROM PRODUCTS WHERE unit_price > 100


If changing the Java/JDBC source code to add the SQL hint is not an option, you can instruct the RDBMS to cache the ResultSets of all queries related to a specific table, either at table creation (the default mode) or later (force mode); this is called “Table Annotation”.

/* Table Annotation at creation time */ CREATE TABLE products (...) RESULT_CACHE (MODE DEFAULT); /* Table annotation at runtime ALTER TABLE products RESULT_CACHE (MODE FORCE);


The Oracle RDBMS furnishes views such as the V$RESULT_CACHE_STATISTICS and a CLIENT_RESULT_CACHE_STATS$ table for monitoring the effectiveness of ResultSet caching. See section 15 in the performance tuning guide for more details on configuring the server-side result set cache

Array Fetch

Array fetching is a must when retrieving a large number of rows from a ResultSet. The fetch size can be specified on the Statement, or the PreparedStatement, or the CallableStatement, or the ResultSet objects.
Example: pstmt.setFetchSize(20);

When using the Oracle database, this array size is capped by the RDBMS’s internal buffer known as Session Data Unit (SDU). The SDU buffer is used for transferring data from the tables to the client, over the network. The size of this buffer, in bytes, can be specified in JDBC URL as illustrated hereafter.


or at the service level in Net Services configuration files sqlnet.ora and tnsnames.ora. There is a hard limit depending on the RDBMS release: 2MB with DB 12c and up, 64K with DB 11.2, and 32K with DB pre-11.2. 
In summary, even if you set the array fetch to a large number, it cannot retrieve more data than the SDU permits, for each roundtrip.

Array DML (Update Batch)

The JDBC specification allows sending a batch of the same DML operations (i.e., array INSERTs, array UPDATEs, array DELETE) for sequential execution at the server, thereby reducing network round-trips.

Update Batching consists in explicitly invoking the addBatch method which adds a statement to an array of operations then explicitly calling executeBatch method to send it as in the following example.

// Array INSERT PreparedStatement pstmt = conn.prepareStatement("INSERT INTO employees VALUES(?, ?)"); pstmt.setInt(1, 2000); pstmt.setString(2, "Milo Mumford"); pstmt.addBatch(); pstmt.setInt(1, 3000); pstmt.setString(2, "Sulu Simpson"); pstmt.addBatch(); int[] updateCounts = pstmt.executeBatch(); ...
Optimizing Network Traffic

Here are two mechanisms that will help optimize the network traffic between your Java code and the RDBMS: network compression and session multiplexing.

Network Data Compression

The ability to compress data transmitted between the Java applications and the RDBMS over LAN or WAN reduces the volume of data, the transfer time and the number of roundtrips.

// Enabling Network Compression in Java prop.setProperty("oracle.net.networkCompression","on"); // Optional configuration for setting the client compression threshold. prop.setProperty("oracle.net.networkCompressionThreshold","1024"); ds.setConnectionProperties(prop); ds.setURL(url); Connection conn = ds.getConnection(); // ...
Sessions Multiplexing 

The Oracle database Connection Manager a.k.a. CMAN, furnishes the ability to funnel multiple database connections over a single network connection thereby saving OS resources. See more details in the Net Services Admin guide.

In-Place Processing

As seen earlier, SQL statements processing involves a number of roundtrips between a database client i.e., Java mid-tier/web-server and the RDBMS. If you move the Java code close or into the RDBMS session/process, you cut the network traffic which constitutes a large part of the latency.
Okay, stored procedures are old-fashion, so seventies, but modern data processing such as Hadoop or Spark, collocate the processing and data for low latency.

If your goal is efficiency, you got to consider using Java stored procedures, here and there for data-bound modules. I discussed the pros and cons of stored procedures in chapter 1 of my book. I’d add that in a modern micro-services based architecture, REST-wrapped stored procedures are a good design choice for data-bound services.

All RDBMSes furnish stored procedures in various languages including proprietary procedural language, Java, JavaScript, PHP, Perl, Python, and TCL.The Oracle database furnishes Java and PL/SQL stored procedures. Java in the database is one of the best unsung Oracle database gems; see some code samples on GitHub.

Scaling Out Java Workloads

In the second part of this blog post, I will discuss the various mechanisms for scaling out Java workloads including Sharded and Multitenant databases, database proxy, and the asynchronous Java database access API proposal.

Horizontal Scaling of Java applications with Sharded Databases

Sharded databases — horizontal partitioning of tables across several databases — have been around for a while. Java applications that use sharded databases must:
(i) define which fields to use as sharding key (and super sharding key) 
(ii) set the values and build the key then request a connection to the datasource.
Java SE 9 furnishes the standard APIs for building the sharding and super-sharding keys.

DataSource ds = new MyDataSource(); // ShardingKey shardingKey = ds.createShardingKeyBuilder() .subkey("abc", JDBCType.VARCHAR) .subkey(94002, JDBCType.INTEGER) .build(); // ... Connection con = ds.createConnectionBuilder() .shardingKey(shardingKey) .build();>


Without further optimization, all shard-aware connection requests go to a central mechanism which maintains the map or topology of the shard keys thereby incurring one additional hop per request.

The Oracle Universal Connection Pool (UCP) has been enhanced to transparently collect all the keys that map to a specific shard. Once UCP gets the keys range it directs connection requests to the appropriate shard, based on the shard key.

Scaling Multi-Tenant Java Applications

Fully multi-tenant Java applications must use a multi-tenant RDBMS where a group of tenants or each tenant has its own database (it’s own pluggable database or PDB in Oracle’s parlance). With tens of thousands of tenants, using (tens of) thousands of databases (or PDBs), a naive approach would allocate a pool per database; we have witnessed naive architecture with a connection per tenant.
The Oracle UCP has been enhanced to use a single pool for all (tens of) thousands databases. Upon a connection request to a specific database, if there is no free/available connection attached to that database, UCP transparently repurposes an idle connection in the pool, which was attached to another database to be re-attached to this one, thereby allowing to use a small set of pooled connections to service all tenants.

See the UCP doc for more details on using one datasource per tenant or a single datasource for all tenants.

Database proxy

Proxies are man-in-the-middle software running between the database and its clients e.g., Java applications. There are several proxy offerings on the market; to name a few: MySQL Router, the Oracle Database Connection Manager in Traffic Director Mode (CMAN-TDM), ProxySQL, and so on.
The Oracle CMAN-TDM is new in Oracle database 18c; it is an extension of the existing Oracle Connection Manager a.k.a. CMAN and furnishes these new following capabilities

Fully transparent to applications
Routes database traffic to right instance (planned)
Hides database planned and unplanned outages to support zero application downtime
Optimizes database session usage and application performance
Enhances database security
CMAN-TDM is client agnostic, iow, it supports all database clients applications including: Java, C, C++, DotNET, Node.js, Python, Ruby, R.

Java applications would connect to CMAN-TDM which, in its turn, connects to the database using the latest driver and libraries then transparently furnish the Quality of Service that the application would get only if it was using the latest driver and APIs.

See more details in the CMAN landing page and the Net Services documentations linked from the landing page.

The Asynchronous Database Access API (ADBA)

The existing JDBC API leads to blocked threads, threads scheduling, and contention; it is not suitable for reactive applications or high throughput and large-scale deployments. There are 3rd party asynchronous Java database access libraries but the Java community needs a standard API where user threads submit database operations and return.

The new API proposal based on the java.util.concurrent.CompletionStage interface; it is available for download from the OpenJDK sandbox @ http://tinyurl.com/java-async-db. The API implementation takes care of executing the operations, completing the CompletableFutures.
You can sense the ADBA API through the latest presentation and examples.

ADBA over JDBC (AoJ)

In order to help the community get a feel of ADBA, a trial/functional version (no asynchronous behavior) of it that runs over JDBC — that we are calling AoJ for ADBA over JDBC — @ https://github.com/oracle/oracle-db-examples/tree/master/java/AoJ. I encourage the reader to play with the AoJ examples.

With the announce of the project Loom which will bring Fibers and Java continuations to the JVM, we will once again revisit the performance and scalability of Java applications that use RDBMSes.

Introducing GraphPipe

Wed, 2018-08-15 11:00
Dead Simple Machine Learning Model Serving

There has been rapid progress in machine learning over the past few years. Today, you can grab one of a handful of frameworks, follow some online tutorials, and have a working machine learning model in a matter of hours. Unfortunately, when you are ready to deploy that model into production you still face several unique challenges.

First, there is no standard for model serving APIs, so you are likely stuck with whatever your framework gives you. This might be protocol buffers or custom JSON. Your business application will generally need a bespoke client just to talk to your deployed model. And it's even worse if you are using multiple frameworks. If you want to create ensembles of models from multiple frameworks, you'll have to write custom code to combine them.

Second, building your model server can be incredibly complicated. Deployment gets much less attention than training, so out-of-the-box solutions are few and far between. Try building a GPU version of TensorFlow-serving, for example. You better be prepared to bang your head against it for a few days.

Finally, many of the existing solutions don't focus on performance, so for certain use cases they fall short. Serving a bunch of tensor data from a complex model via a python-JSON API not going to cut it for performance-critical applications.

We created GraphPipe to solve these three challenges. It provides a standard, high-performance protocol for transmitting tensor data over the network, along with simple implementations of clients and servers that make deploying and querying machine learning models from any framework a breeze. GraphPipe's efficient servers can serve models built in TensorFlow, PyTorch, mxnet, CNTK, or caffe2. We are pleased to announce that GraphPipe is available on Oracle's GitHub. Documentation, examples, and other relevant content can be found at https://oracle.github.io/graphpipe.

The Business Case

In the enterprise, machine-learning models are often trained individually and deployed using bespoke techniques. This impacts an organizations’ ability to derive value from its machine learning efforts. If marketing wants to use a model produced by the finance group, they will have to write custom clients to interact with the model. If the model becomes popular sales wants to use it as well, the custom deployment may crack under the load.

It only gets worse when the models start appearing in customer-facing mobile and IoT applications. Many devices are not powerful enough to run models locally and must make a request to a remote service. This service must be efficient and stable while running models from varied machined learning frameworks.

A standard allows researchers to build the best possible models, using whatever tools they desire, and be sure that users can access their models' predictions without bespoke code. Models can be deployed across multiple servers and easily aggregated into larger ensembles using a common protocol. GraphPipe provides the tools that the business needs to derive value from its machine learning investments.

Implementation Details

GraphPipe is an efficient network protocol designed to simplify and standardize transmission of machine learning data between remote processes. Presently, no dominant standard exists for how tensor-like data should be transmitted between components in a deep learning architecture. As such it is common for developers to use protocols like JSON, which is extremely inefficient, or TensorFlow-serving's protocol buffers, which carries with it the baggage of TensorFlow, a large and complex piece of software. GraphPipe is designed to bring the efficiency of a binary, memory-mapped format while remaining simple and light on dependencies.

GraphPipe includes:

  • A set of flatbuffer definitions
  • Guidelines for serving models consistently according to the flatbuffer definitions
  • Examples for serving models from TensorFlow, ONNX, and caffe2
  • Client libraries for querying models served via GraphPipe

In essence, a GraphPipe request behaves like a TensorFlow-serving predict request, but using flatbuffers as the message format. Flatbuffers are similar to google protocol buffers, with the added benefit of avoiding a memory copy during the deserialization step. The flatbuffer definitions provide a request message that includes input tensors, input names and output names. A GraphPipe remote model accepts the request message and returns one tensor per requested output name. The remote model also must provide metadata about the types and shapes of the inputs and outputs that it supports.

Performance

First, we compare serialization and deserialization speed of float tensor data in python using a custom ujson API, protocol buffers using a TensorFlow-serving predict request, and a GraphPipe remote request. The request consists of about 19 million floating-point values (consisting of 128 224x224x3 images) and the response is approximately 3.2 million floating point values (consisting of 128 7x7x512 convolutional outputs). The units on the left are in seconds.

Graphpipe is especially performant on the deserialize side, because flatbuffers provide access to underlying data without a memory copy.

Second, we compare end-to-end throughput using a Python-JSON TensorFlow model server, TensorFlow-serving, and the GraphPipe-go TensorFlow model server. In each case the backend model is the same. Large requests are made to the server using 1 thread and then again with 5 threads. The units on the left are rows calculated by the model per second.

Note that this test uses the recommended parameters for building Tensorflow-serving. Although the recommended build parameters for TensorFlow-serving do not perform well, we were ultimately able to discover compilation parameters that allow it to perform on par with our GraphPipe implementation. In other words, an optimized TensorFlow-serving performs similarly to GraphPipe, although building TensorFlow-serving to perform optimally is not documented nor easy.

Where Do I Get it?

You can find plenty of documentation and examples at https://oracle.github.io/graphpipe. The GraphPipe flatbuffer spec can be found on Oracle's GitHub along with servers that implement the spec for Python and Go. We also provide clients for Python, Go, and Java (coming soon), as well as a plugin for TensorFlow that allows the inclusion of a remote model inside a local TensorFlow graph.

Podcast: Developer Evolution: What's rockin’ roles in IT?

Tue, 2018-08-14 23:00

The good news is that the US Bureau of Labor Statistics predicts 24% growth in software developer jobs through 2026. That’s well above average. The outlook for Database administrators certainly isn’t bleak, but with projected job growth of 11% to 2026, that’s less than half the growth projected for developers. Job growth for System administrators, at 6% through 2016, is considered average by the BLS. So while the news is positive all around, developers certainly have an advantage. Each of these roles certainly has separate and distinct responsibilities. But why is the outlook so much better for developers, and what does this say about what’s happening in the IT ecosystem?

"More than ever," says Oracle Developer Champion Rolando Carrasco, "institutions, organizations, and governments are keen to generate a new crop of developers that can help them to to create something new." In today's business climate competition is tough, and high premium is placed on innovation. "But developers have a lot of tools,  a lot of abilities within reach, and the opportunity to make something that can make a competitive difference."

But the role of the developer is morphing into something new, according to Oracle ACE Director Martin Giffy D'Souza. "In the next couple years we're also going to see that  the typical developer is not going to be the traditional developer that went to school, or the script kitties that just got into the business. We're going see what is called the citizen developer. We're going to see a lot more people transition to that simply because it adds value to their job. Those people are starting to hit the limits of writing VBA macros in Excel and they want to write custom apps. I think that's what we're going to see more and more of, because we already know there's a developer job shortage."

But why is the job growth for developers outpacing that for DBAs and SysAdmins? "If you take it at very high level, devs produce things," Martin says. "They produce value. They produce products.  DBAs and IT people are maintainers. They’re both important, but the more products and solutions we can create," the more value to the business.

Oracle ACE Director Mark Rittman has spent the last couple of years working as a product manager in a start-up, building a tech platform. "I never saw a DBA there," he admits. "It was at the point that if I were to try to explain what a DBA was to people there, all of whom are uniformly half my age, they wouldn't know what I was talking about. That's because the platforms people use these days, within the Oracle ecosystem or Google or Amazon or whatever, it's all very much cloud, and it's all very much NoOPs, and it's very much the things that we used to spend ages worrying about,"

This frees developers to do what they do best. "There are far fewer people doing DBA work and SysAdmin work," Mark says. "That’s all now in the cloud. And that also means that developers can also develop now. I remember, as a BI developer working on projects, it was surprising how much of my time was spent just getting the system working in the first place, installing things, configuring things, and so on. Probably 75% of every project was just getting the thing to actually work."

Where some roles may vanish altogether, others will transform. DBAs have become data engineers or infrastructure engineers, according to Mark. "So there are engineers around and there are developers around," he observes, "but I think administrator is a role that, unless you work for one of the big cloud companies in one of those big data centers, is largely kind of managed away now."

Phil Wilkins, an Oracle ACE, has witnessed the changes. DBAs in particular, as well as network people focused on infrastructure, have been dramatically affected by cloud computing, and the ground is still shaking. "With the rise and growth in cloud adoption these days, you're going to see the low level, hard core technical skills that the DBAs used to bring being concentrated into the cloud providers, where you're taking a database as a service. They're optimizing the underlying infrastructure, making sure the database is running. But I'm just chucking data at it, so I don't care about whether the storage is running efficiently or not. The other thing is that although developers now get a get more freedom, and we've got NoSQL and things like that, we're getting more and more computing power, and it's accelerating at such a rate now that, where 10 years ago we used to have to really worry about the tuning and making sure the database was performant, we can now do a lot of that computing on an iPhone. So why are we worrying when we've got huge amounts of cloud and CPU to the bucketload?

These comments represent just a fraction of the conversation captured in this latest Oracle Developer Community Podcast, in which the panelists dive deep into the forces that are shaping and re-shaping roles, and discuss their own concerns about the trends and technologies that are driving that evolution. Listen!

The Panelists Rolando Carrasco

Rolando Carrasco
Oracle Developer Champion
Oracle ACE
Co-owner, Principal SOA Architect, S&P Solutions
Twitter LinkedIn

Martin Giffy D'Souza

Martin Giffy D'Souza
Oracle ACE Director
Director of Innovation, Insum Solutions
Twitter LinkedIn 

Mark Rittman

Mark Rittman
Oracle ACE Director
Chief Executive Officer, MJR Analytics
Twitter LinkedIn 

Phil Wilkins

Phil Wilkins
Oracle ACE
Senior Consultant, Capgemini
Twitter LinkedIn 5

Related Oracle Code One Sessions

The Future of Serverless is Now: Ci/CD for the Oracle Fn Project, by Rolando Carrasco and Leonardo Gonzalez Cruz [DEV5325]

Other Related Content

Podcast: Are Microservices and APIs Becoming SOA 2.0?

Vibrant and Growing: The Current State of API Management

Video: 2 Minute Integration with Oracle Integration Cloud Service

It's Always Time to Change

Coming Soon

The next program, coming on Sept 5, will feature a discussion of "DevOps to NoOps," featuring panelists Baruch Sadogursky, Davide Fiorentino, Bert Jan Schrijver, and others TBA. Stay tuned!

Subscribe

Never miss an episode! The Oracle Developer Community Podcast is available via:

What's New in Oracle Developer Cloud Service - August 2018

Mon, 2018-08-06 12:14

Over the weekend we updated Oracle Developer Cloud Service - your cloud based DevOps and Agile platform - with a new release (18.3.3) adding some key new features that will improve the way you develop and release software on the Oracle Cloud. Here is a quick rundown of key new capabilities added this month.

Environments

A new top level section in Developer Cloud Service now allows you to define "Environments" - a collection of cloud services that you bundle together under one name. Once you have an environment defined, you'll be able to see the status of your environment on the home page of your project. You can for example define a development, test and production environments - and see the status of each one with a simple glance.

Environment View

This is the first step in a set of future features of DevCS that will help you manage software artifacts across environments in an easier way.

Project Templates

When you create a new project in DevCS you can base it on a template. Up until this release you were limited to templates created by Oracle, now you can define your own templates for your company.

Template can include default artifacts such as wiki pages, default git repositories, and even builds and deployment steps.

This is very helpful for companies who are aiming to standardize development across development teams, as well as for team who have repeating patterns of development.

Project Template

Wiki Enhancments

The wiki in DevCS is a very valuable mechanism for your team to share information, and we just added a bunch of enhancements that will make collaboration in your team even better.

You can now watch specific wiki pages or sections, which will notify you whenever someone updates those pages.

We also added support for commenting on wiki pages - helping you to conduct virtual discussion on their content.

Wiki tracking

More

These are just some of the new features in Developer Cloud Service. All of these features are part of the free functionality that Developer Cloud Service provides to Oracle Cloud customers. Take them for a spin and let us know what you think.

For information on additional new feature check out the What's New in Developer Cloud Service Documentation.

Got technical questions - ask them on our cloud customer connect community page.

 

Running Spring Tool Suite and other GUI applications from a Docker container

Mon, 2018-08-06 01:30

Originally published at javaoraclesoa.blogspot.com

Running an application within a Docker container helps in isolating the application from the host OS. Running GUI applications like for example an IDE from a Docker container, can be challenging. I’ll explain several of the issues you might encounter and how to solve them. For this I will use Spring Tool Suite as an example. The code (Dockerfile and docker-compose.yml) can also be found here. Due to (several) security concerns, this is not recommended in a production environment.

Running a GUI from a Docker container

In order to run a GUI application from a Docker container and display its GUI on the host OS, several steps are needed;

Which display to use?

The container needs to be aware of the display to use. In order to make the display available, you can pass the DISPLAY environment variable to the container. docker-compose describes the environment/volume mappings/port mappings and other things of docker containers. This makes it easier to run containers in a quick and reproducible way and avoids long command lines.

docker-compose

You can do this by providing it in a docker-compose.yml file. See for example below. The environment indicates the host DISPLAY variable is passed as DISPLAY variable to the container.

Docker

In a Docker command (when not using docker-compose), you would do this with the -e flag or with — env. For example;

docker run — env DISPLAY=$DISPLAY containername Allow access to the display

The Docker container needs to be allowed to present its screen on the Docker host. This can be done by executing the following command:

xhost local:root

After execution, during the session, root is allowed to use the current users display. Since the Docker daemon runs as root, Docker containers (in general!) now can use the current users display. If you want to persist this, you should add it to a start-up script.

Sharing the X socket

The last thing to do is sharing the X socket (don’t ask me details but this is required…). This can be done by defining a volume mapping in your Docker command line or docker-compose.yml file. For Ubuntu this looks like you can see in the image below.

Spring Tool Suite from a Docker container

In order to give a complete working example, I’ll show how to run Spring Tool Suite from a Docker container. In this example I’m using the Docker host JVM instead of installing a JVM inside the container. If you want to have the JVM also inside the container (instead of using the host JVM), look at the following and add that to the Dockerfile. As a base image I’m using an official Ubuntu image.

I’ve used the following Dockerfile:

FROM ubuntu:18.04 MAINTAINER Maarten Smeets <maarten.smeets@amis.nl> ARG uid LABEL nl.amis.smeetsm.ide.name=”Spring Tool Suite” nl.amis.smeetsm.ide.version=”3.9.5" ADD https://download.springsource.com/release/STS/3.9.5.RELEASE/dist/e4.8/spring-tool-suite-3.9.5.RELEASE-e4.8.0-linux-gtk-x86_64.tar.gz /tmp/ide.tar.gz RUN adduser — uid ${uid} — disabled-password — gecos ‘’ develop RUN mkdir -p /opt/ide && \ tar zxvf /tmp/ide.tar.gz — strip-components=1 -C /opt/ide && \ ln -s /usr/lib/jvm/java-10-oracle /opt/ide/sts-3.9.5.RELEASE/jre && \ chown -R develop:develop /opt/ide && \ mkdir /home/develop/ws && \ chown develop:develop /home/develop/ws && \ mkdir /home/develop/.m2 && \ chown develop:develop /home/develop/.m2 && \ rm /tmp/ide.tar.gz && \ apt-get update && \ apt-get install -y libxslt1.1 libswt-gtk-3-jni libswt-gtk-3-java && \ apt-get autoremove -y && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* && \ rm -rf /tmp/* USER develop:develop WORKDIR /home/develop ENTRYPOINT /opt/ide/sts-3.9.5.RELEASE/STS -data /home/develop/ws

The specified packages are required to be able to run STS inside the container and create the GUI to display on the host. I’ve used the following docker-compose.yml file:

version: ‘3’ services: sts: build: context: . dockerfile: Dockerfile args: uid: ${UID} container_name: “sts” volumes: - /tmp/.X11-unix:/tmp/.X11-unix - /home/develop/ws:/home/develop/ws - /home/develop/.m2:/home/develop/.m2 - /usr/lib/jvm/java-10-oracle:/usr/lib/jvm/java-10-oracle - /etc/java-10-oracle:/etc/java-10-oracle environment: - DISPLAY user: develop ports: "8080:8080"

Notice this docker-compose file has some dependencies on the host OS. It expects a JDK 10 to be installed in /usr/lib/jvm/java-10-oracle with configuration in /etc/java-10-oracle. Also it expects to find /home/develop/ws and /home/develop/.m2 to be present on the host to be mapped to the container. The .X11-unix mapping was already mentioned as needed to allow a GUI screen to be displayed. There are also some other things which are important to notice in this file.

User id

First the way a non-privileged user is created inside the container. This user is created with a user id (uid) which is supplied as a parameter. Why did I do that? Files in mapped volumes which are created by the container user will be created with the uid which the user inside the container has. This will cause issues if inside the container the user has a different uid as outside of the container. Suppose I run the container onder a user develop. This user on the host has a uid of 1002. Inside the container there is also a user develop with a uid of 1000. Files on a mapped volume are created with uid 1000; the uid of the user in the container. On the host however, uid 1000 is a different user. These files created by the container cannot be accessed by the develop user on the host (with uid 1002). In order to avoid this, I’m creating a develop user inside the VM with the same uid as the user used outside of the VM (the user in the docker group which gave the command to start the container).

Workspace folder and Maven repository

When working with Docker containers, it is a common practice to avoid storing state inside the container. State can be various things. I consider the STS application work-space folder and the Maven repository among them. This is why I’ve created the folders inside the container and mapped them in the docker-compose file to the host. They will use folders with the same name (/home/develop/.m2 and /home/develop/ws) on the host.

Java

My Docker container with only Spring Tool Suite was big enough already without having a more than 300Mb JVM inside of it (on Linux Java 10 is almost double the size of Java 8). I’m using the host JVM instead. I installed the host JVM on my Ubuntu development VM as described here.

In order to use the host JVM inside the Docker container, I needed to do 2 things: Map 2 folders to the container:

And map the JVM path to the JRE folder onder STS: ln -s /usr/lib/jvm/java-10-oracle /opt/ide/sts-3.9.5.RELEASE/jre.

Seeing it work

First allow access to the display:

xhost local:root

Next make available the variable UID:

export UID=$UID

Then build:

docker-compose build Building sts Step 1/10 : FROM ubuntu:18.04 — -> 735f80812f90 Step 2/10 : MAINTAINER Maarten Smeets <maarten.smeets@amis.nl> — -> Using cache — -> 69177270763e Step 3/10 : ARG uid — -> Using cache — -> 85c9899e5210 Step 4/10 : LABEL nl.amis.smeetsm.ide.name=”Spring Tool Suite” nl.amis.smeetsm.ide.version=”3.9.5" — -> Using cache — -> 82f56ab07a28 Step 5/10 : ADD https://download.springsource.com/release/STS/3.9.5.RELEASE/dist/e4.8/spring-tool-suite-3.9.5.RELEASE-e4.8.0-linux-gtk-x86_64.tar.gz /tmp/ide.tar.gz — -> Using cache — -> 61ab67d82b0e Step 6/10 : RUN adduser — uid ${uid} — disabled-password — gecos ‘’ develop — -> Using cache — -> 679f934d3ccd Step 7/10 : RUN mkdir -p /opt/ide && tar zxvf /tmp/ide.tar.gz — strip-components=1 -C /opt/ide && ln -s /usr/lib/jvm/java-10-oracle /opt/ide/sts-3.9.5.RELEASE/jre && chown -R develop:develop /opt/ide && mkdir /home/develop/ws && chown develop:develop /home/develop/ws && rm /tmp/ide.tar.gz && apt-get update && apt-get install -y libxslt1.1 libswt-gtk-3-jni libswt-gtk-3-java && apt-get autoremove -y && apt-get clean && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* — -> Using cache — -> 5e486a4d6dd0 Step 8/10 : USER develop:develop — -> Using cache — -> c3c2b332d932 Step 9/10 : WORKDIR /home/develop — -> Using cache — -> d8e45440ce31 Step 10/10 : ENTRYPOINT /opt/ide/sts-3.9.5.RELEASE/STS -data /home/develop/ws — -> Using cache — -> 2d95751237d7 Successfully built 2d95751237d7 Successfully tagged t_sts:latest

Next run:

docker-compose up

When you run a Spring Boot application on port 8080 inside the container, you can access it on the host on port 8080 with for example Firefox.

Auto-updatable, self-contained CLI with Java 11

Mon, 2018-08-06 01:30
.cb11splash{display:none;}

(Originally published on Medium)

Introduction

Over the course of the last 11 months, we have seen two major releases of Java — Java 9 and Java 10. Come September, we will get yet another release in the form of Java 11, all thanks to the new 6 month release train. Each new release introduces exciting features to assist the modern Java developer. Let’s take some of these features for a spin and build an auto-updatable, self-contained command line interface.

The minimum viable feature-set for our CLI is defined as follows:

  • Display the current bitcoin price index by calling the free coin desk API
  • Check for new updates and if available, auto update the CLI
  • Ship the CLI with a custom Java runtime image to make it self-contained
Prerequisites

To follow along, you will need a copy of JDK 11 early-access build. You will also need the latest version (4.9 at time of writing) of gradle. Of course, you can use your preferred way of building Java applications. Though not required, familiarity with JPMS and JLink can be helpful since we are going to use the module system to build a custom runtime image.

Off we go

We begin by creating a class that provides the latest bitcoin price index. Internally, it reads a configuration file to get the URL of the coin desk REST API and builds an http client to retrieve the latest price. This class makes use of the new fluent HTTP client classes that are part of “java.net.http” module.

var bpiRequest = HttpRequest.newBuilder() .uri(new URI(config.getProperty("bpiURL"))) .GET() .build(); var bpiApiClient = HttpClient.newHttpClient(); bpiApiClient .sendAsync(bpiRequest, HttpResponse.BodyHandlers.ofString()) .thenApply(response -> toJson(response)) .thenApply(bpiJson -> bpiJson.getJsonObject("usd").getString("rate"));

Per Java standards, this code is actually very concise. We used the new fluent builders to create a GET request, call the API, convert the response into JSON, and pull the current bitcoin price in USD currency.

In order to build a modular jar and set us up to use “jlink”, we need to add a “module-info.java” file to specify the CLI’s dependencies on other modules.

module ud.bpi.cli { requires java.net.http; requires org.glassfish.java.json; }

From the code snippet, we observe that our CLI module requires the http module shipped in Java 11 and an external JSON library.

Now, let’s turn our attention to implement an auto-updater class. This class should provide a couple of methods. One method to talk to a central repository and check for the availability of newer versions of the CLI and another method to download the latest version. The following snippet shows how easy it is to use the new HTTP client interfaces to download remote files.

CompletableFuture update(String downloadToFile) { try { HttpRequest request = HttpRequest.newBuilder() .uri(new URI("http://localhost:8080/2.zip")) .GET() .build(); return HttpClient.newHttpClient() .sendAsync(request, HttpResponse.BodyHandlers .ofFile(Paths.get(downloadToFile))) .thenApply(response -> { unzip(response.body()); return true; }); } catch (URISyntaxException ex) { return CompletableFuture.failedFuture(ex); } }

The new predefined HTTP body handlers in Java 11 can convert a response body into common high-level Java objects. We used the HttpResponse.BodyHandlers.ofFile() method to download a zip file that contains the latest version of our CLI.

Let’s put these classes together by using a launcher class. It provides an entry point to our CLI and implements the application flow. Right when the application starts, this class calls its launch() method that will check for new updates.

void launch() { var autoUpdater = new AutoUpdater(); try { if (autoUpdater.check().get()) { System.exit(autoUpdater.update().get() ? 100 : -1); } } catch (InterruptedException | ExecutionException ex) { throw new RuntimeException(ex); } }

As you can see, if a new version of the CLI is available, we download the new version and exit the JVM by passing in a custom exit code 100. A simple wrapper script will check for this exit code and rerun the CLI.

#!/bin/sh ... start EXIT_STATUS=$? if [ ${EXIT_STATUS} -eq 100 ]; then start fi

And finally, we will use “jlink” to create a runtime image that includes all the necessary pieces to execute our CLI. jlink is a new command line tool provided by Java that will look at the options passed to it to assemble and optimize a set of modules and their dependencies into a custom runtime image. In the process, it builds a custom JRE — thereby making our CLI self-contained.

jlink --module-path build/libs/:${JAVA_HOME}/jmods \ --add-modules ud.bpi.cli,org.glassfish.java.json \ --launcher bpi=ud.bpi.cli/ud.bpi.cli.Launcher \ --output images

Let’s look at the options that we passed to jlink:

  • “ module-path” tells jlink to look into the specified folders that contain java modules
  • “ add-modules” tells jlink which user-defined modules are to be included in the custom image
  • “launcher” is used to specify the name of the script that will be used to start our CLI and the full path to the class that contains the main method of the application
  • “output” is used to specify the folder name that holds the newly created self-contained custom image

When we run our first version of the CLI and there are no updates available, the CLI prints something like this:


Say we release a new version (2) of the CLI and push it to the central repo. Now, when you rerun the CLI, you will see something like this:


Voila! The application sees that a new version is available and auto-updates itself. It then restarts the CLI. As you can see, the new version adds an up/down arrow indicator to let the user know how well the bitcoin price index is doing.

Head over to GitHub to grab the source code and experiment with it.

Text Classification with Deep Neural Network in TensorFlow — Simple Explanation

Sun, 2018-07-29 21:30
.cb11splash{display:none;}

(Originally published on andrejusb.blogspot.com)

Text classification implementation with TensorFlow can be simple. One of the areas where text classification can be applied — chatbot text processing and intent resolution. I will describe step by step in this post, how to build TensorFlow model for text classification and how classification is done. Please refer to my previous post related to similar topic — Contextual Chatbot with TensorFlow, Node.js and Oracle JET — Steps How to Install and Get It Working. I would recommend to go through this great post about chatbot implementation — Contextual Chatbots with Tensorflow.

Complete source code is available in GitHub repo (refer to the steps described in the blog referenced above).

Text classification implementation:

Step 1: Preparing Data

  • Tokenise patterns into array of words
  • Lower case and stem all words. Example: Pharmacy = pharm. Attempt to represent related words
  • Create list of classes — intents
  • Create list of documents — combination between list of patterns and list of intents

Python implementation:

Step 2: Preparing TensorFlow Input

  • [X: [0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, …N], Y: [0, 0, 1, 0, 0, 0, …M]]
  • [X: [0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, …N], Y: [0, 0, 0, 1, 0, 0, …M]]
  • Array representing pattern with 0/1. N = vocabulary size. 1 when word position in vocabulary is matching word from pattern
  • Array representing intent with 0/1. M = number of intents. 1 when intent position in list of intents/classes is matching current intent

Python implementation:

Step 3: Training Neural Network

  • Use tflearn — deep learning library featuring a higher-level API for TensorFlow
  • Define X input shape — equal to word vocabulary size
  • Define two layers with 8 hidden neurones — optimal for text classification task (based on experiments)
  • Define Y input shape — equal to number of intents
  • Apply regression to find the best equation parameters
  • Define Deep Neural Network model (DNN)
  • Run model.fit to construct classification model. Provide X/Y inputs, number of epochs and batch size
  • Per each epoch, multiple operations are executed to find optimal model parameters to classify future input converted to array of 0/1

Batch size:

  • Smaller batch size requires less memory. Especially important for datasets with large vocabulary
  • Typically networks train faster with smaller batches. Weights and network parameters are updated after each propagation
  • The smaller the batch the less accurate estimate of the gradient (function which describes the data) could be

Python implementation:

Step 4: Initial Model Testing

  • Tokenise input sentence — split it into array of words
  • Create bag of words (array with 0/1) for the input sentence — array equal to the size of vocabulary, with 1 for each word found in input sentence
  • Run model.predict with given bag of words array, this will return probability for each intent

Python implementation:

Step 5: Reuse Trained Model

  • For better reusability, it is recommended to create separate TensorFlow notebook, to handle classification requests
  • We can reuse previously created DNN model, by loading it with TensorFlow pickle

Python implementation:

Step 6: Text Classification

  • Define REST interface, so that function will be accessible outside TensorFlow
  • Convert incoming sentence into bag of words array and run model.predict
  • Consider results with probability higher than 0.25 to filter noise
  • Return multiple identified intents (if any), together with assigned probability

Python implementation:

Oracle Load Balancer Classic configuration with Terraform

Thu, 2018-07-19 01:30

(Originally published on Medium)

This article provides an introduction to using the Load Balancer resources to provision and configure an Oracle Cloud Infrastructure Load Balancer Classic instance using Terraform

When using the Load Balancer Classic resources with the opc Terraform Provider the  lbaas_endpoint  attribute must be set in the provider configuration.

provider "opc" { version = "~> 1.2" user = "${var.user}" password = "${var.password}" identity_domain = "${var.compute_service_id}" endpoint = "${var.compute_endpoint}" lbaas_endpoint = "https://lbaas-1111111.balancer.oraclecloud.com" }

First we create the main Load Balancer instance resource. The Server Pool, Listener and Policy resources will be created as child resources associated to this instance.

resource "opc_lbaas_load_balancer" "lb1" { name = "examplelb1" region = "uscom-central-1" description = "My Example Load Balancer" scheme = "INTERNET_FACING" permitted_methods = ["GET", "HEAD", "POST"] ip_network = "/Compute-${var.domain}/${var.user}/ipnet1" }

To define the set of servers the load balancer will be directing traffic to we create a Server Pool, sometimes referred to as an origin server pool. Each server is defined by the combination of the target IP address, or hostname, and port. For the brevity of this example we’ll assume we already have a couple instances on an existing IP Network with a web service running on port  8080 

resource "opc_lbaas_server_pool" "serverpool1" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "serverpool1" servers = ["192.168.1.2:8080", "192.168.1.3:8080"] vnic_set = "/Compute-${var.domain}/${var.user}/vnicset1" }

The Listener resource defines what incoming traffic the Load Balancer will direct to a specific server pool. Multiple Server Pools and Listeners can be defined for a single Load Balancer instance. For now we’ll assume all the traffic is HTTP, both to the load balancer and between the load balancer and the server pool. We’ll look at securing traffic with HTTPS later. In this example the load balancer is managing inbound requests for a site  http://mywebapp.example.com  and directing them to the server pool we defined above.

resource "opc_lbaas_listener" "listener1" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "http-listener" balancer_protocol = "HTTP" port = 80 virtual_hosts = ["mywebapp.example.com"] server_protocol = "HTTP" server_pool = "${opc_lbaas_server_pool.serverpool1.uri}" policies = [ "${opc_lbaas_policy.load_balancing_mechanism_policy.uri}", ] }

Policies are used to define how the Listener processes the incoming traffic. In the Listener definition we are referencing a Load Balancing Mechanism Policy to set how the load balancer allocates the traffic across the available servers in the server pool. Additional policy type could also be defined to control session affinity of

resource "opc_lbaas_policy" "load_balancing_mechanism_policy" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "roundrobin" load_balancing_mechanism_policy { load_balancing_mechanism = "round_robin" } }

With that, our first basic Load Balancer configuration is complete. Well almost. The last step is to configure the DNS CNAME record to point the source domain name (e.g. mywebapp.example.com ) to the canonical host name of load balancer instance. The exact steps to do this will be dependent on your DNS provider. To get the  canonical_host_name add the following output. output "canonical_host_name" { value = "${opc_lbaas_load_balancer.lb1.canonical_host_name}" }

Helpful Hint: if you are just creating the load balancer for testing and you don’t have access to a DNS name you can redirect, a workaround is to set the  virtual host  in the listener configuration to the load balancers canonical host name, you can then use the canonical host name directly for the inbound service URL, e.g.

resource "opc_lbaas_listener" "listener1" { ... virtual_hosts = [ "${opc_lbaas_load_balancer.lb1.canonical_host_name}" ] ... } Configuring the Load Balancer for HTTPS

There are two separate aspects to configuring the Load Balancer for HTTPS traffic, the first is to enable inbound HTTPS requests to the Load Balancer, often referred to as SSL or TLS termination or offloading. The second is the use of HTTPS for traffic between the Load Balancer and the servers in the origin server pool.

HTTPS SSL/TLS Termination

To configure the Load Balancer listener to accept inbound HTTPS requests for encrypted traffic between the client and the Load Balancer, create a Server Certificate providing the PEM encoded certificate and private key, and the concatenated set of PEM encoded certificates for the CA certification chain.

resource "opc_lbaas_certificate" "cert1" { name = "server-cert" type = "SERVER" private_key = "${var.private_key_pem}" certificate_body = "${var.cert_pem}" certificate_chain = "${var.ca_cert_pem}" }

Now update the existing, or create a new listener for HTTPS

resource "opc_lbaas_listener" "listener2" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "https-listener" balancer_protocol = "HTTPS" port = 443 certificates = ["${opc_lbaas_certificate.cert1.uri}"] virtual_hosts = ["mywebapp.example.com"] server_protocol = "HTTP" server_pool = "${opc_lbaas_server_pool.serverpool1.uri}" policies = [ "${opc_lbaas_policy.load_balancing_mechanism_policy.uri}", ] }

Note that the server pool protocol is still HTTP, in this configuration traffic is only encrypted between the client and the load balancer.

HTTP to HTTPS redirect

A common pattern required for many web applications is to ensure that any initial incoming requests over HTTP are redirected to HTTPS for secure site communication. To do this we can we can update the original HTTP listeners we created above with a new redirect policy

resource "opc_lbaas_policy" "redirect_policy" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "example_redirect_policy" redirect_policy { redirect_uri = "https://${var.dns_name}" response_code = 301 } } resource "opc_lbaas_listener" "listener1" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "http-listener" balancer_protocol = "HTTP" port = 80 virtual_hosts = ["mywebapp.example.com"] server_protocol = "HTTP" server_pool = "${opc_lbaas_server_pool.serverpool1.uri}" policies = [ "${opc_lbaas_policy.redirect_policy.uri}", ] } HTTPS between Load Balancer and Server Pool

HTTPS between the Load Balancer and Server Pool should be used if the server pool is accessed over the Public Internet, and can also be used for extra security when accessing servers within the Oracle Cloud Infrastructure over the private IP Network.

This configuration assumes the backend servers are already configured to server their content over HTTPS.

To configure the Load Balancer to communicate securely with the backend servers create a Trusted Certificate, providing the PEM encoded Certificate and CA authority certificate chain for the backend servers.

resource "opc_lbaas_certificate" "cert2" { name = "trusted-cert" type = "TRUSTED" certificate_body = "${var.cert_pem}" certificate_chain = "${var.ca_cert_pem}" }

Next create a Trusted Certificate Policy referencing the Trusted Certificate

resource "opc_lbaas_policy" "trusted_certificate_policy" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "example_trusted_certificate_policy" trusted_certificate_policy { trusted_certificate = "${opc_lbaas_certificate.cert2.uri}" } }

And finally update the listeners server pool configuration to HTTPS, adding the trusted certificate policy

resource "opc_lbaas_listener" "listener2" { load_balancer = "${opc_lbaas_load_balancer.lb1.id}" name = "https-listener" balancer_protocol = "HTTPS" port = 443 certificates = ["${opc_lbaas_certificate.cert1.uri}"] virtual_hosts = ["mywebapp.example.com"] server_protocol = "HTTPS" server_pool = "${opc_lbaas_server_pool.serverpool1.uri}" policies = [ "${opc_lbaas_policy.load_balancing_mechanism_policy.uri}", "${opc_lbaas_policy.trusted_certificate_policy.uri} ] } More Information

A Quick Look At What's New In Oracle JET v5.1.0

Wed, 2018-07-18 12:11

On June 18th, the v5.1.0 release of Oracle JET was made available. It was the 25th consecutive on-schedule release for Oracle JET. Details on the release schedule are provided here in the FAQ.

As indicated by the release number, v5.1.0 is a minor release, aimed at tweaking and consolidating features throughout the toolkit. As in other recent releases, new features have been added to support development of composite components, following the Composite Component Architecture (CCA). For details, see the entry on the new Template Slots in Duncan Mills's blog. Also, take note of the new design time metadata, as described in the release notes

Aside from the work done in the CCA area, the key new features and enhancements to be aware of in the release are listed below, sorted alphabetically:

Component Enhancement Description oj-chart New "data" attribute. Introduces new attributes, slots, and custom elements. oj-film-strip New "looping" attribute. Specifies filmstrip navigation behavior, bounded ("off) or looping ("page"). oj-form-layout Enhanced content flexibility. Removes restrictions on the types of children allowed in the "oj-form-layout" component. oj-gantt New "dnd" attribute and "ojMove" event.  Provides new support for moving tasks via drag and drop. oj-label-value New component. Provides enhanced layout flexibility for the "oj-form-layout" component. oj-list-view Enhanced "itemTemplate" slot. Supports including the <LI> element in the template. oj-swipe-actions New component. Provides a declarative way to add swipe-to-reveal functionality to items in the "oj-list-view" component.

For all the details on the items above, see the release notes.

Note: Be aware that in Oracle JET 7.0.0, support for Yeoman and Grunt will be removed from generator-oraclejet and ojet-cli. As a consequence, the ojet-cli will be the only way to use the Oracle JET tooling, e.g., to create new Oracle JET projects from that point on. Therefore, if you haven't transferred from using Yeoman and Grunt to ojet-cli yet, e.g., to command line calls such as "ojet create", take some time to move in that direction before the 7.0.0 release.

As always, your comments and constructive feedback are welcome. If you have questions, or comments, please engage with the Oracle JET Community in the Discussion Forums and also follow @OracleJET on Twitter.

For organizations using Oracle JET in production, you're invited to be highlighted on the Oracle JET site, with the latest addition being a brand new Customer Success Story by Cagemini.

On behalf of the entire Oracle JET development team: "Happy coding!"

Vibrant and Growing: The Current State of API Management

Tue, 2018-07-17 23:00

"Vibrant and growing all the time!" That's how Andrew Bell, Oracle PaaS API Management Architect at Capgemini, describes the current state of API management. "APIs are the doors to organizations, the means by which organizations connect to one another, connect their processes to one another, and streamline those processes to meet customer needs. The API environment is growing rapidly as we speak," Bell says.

"API management today is quite crucial," says Bell's Capgemini colleague Sander Rensen, an Oracle PaaS lead and architect, "especially for clients who want to go on a journey of a digital transformation. For our clients, the ability to quickly find APIs and subscribe to them is a very crucial part of digital transformation.

"It's not just the public-facing view of APIs," observes Oracle ACE Phil Wilkins, a senior Capgemini consultant specializing in iPaaS. "People are realizing that APIs are an easier, simpler way to do internal decoupling. If I expose my back-end system in a particular way to another part of the organization — the same organization — I can then mask from you how I'm doing transformation or innovation or just trying to keep alive a legacy system while we try and improve our situation," Wilkins explains. "I think that was one of the original aspirations of WSDL and technologies like that, but we ended up getting too fine-grained and tying WSDLs to end products. Then the moment the product changed that WSDL changed and you broke the downstream connections."

Luis Weir, CTO of Capgemini's Oracle delivery unit and an Oracle Developer Champion and ACE Director, is just as enthusiastic about the state of API management, but see's a somewhat rocky road ahead for some organizations. "APIs are one thing, but the management of those APIs is something entirely different," Weir explains

"API management is something that we're doing quite heavily, but I don't think all organizations have actually realized the importance of the full lifecycle management of the APIs. Sometimes people think of API management as just an API gateway. That’s an important capability, but there is far more to it,"

Weir wonders if organizations understand what it means to manage an API throughout its entire lifecycle.

Bell, Rensen, Wilkins, and Weir are the authors of Implementing Oracle API Platform Cloud Service, now available from Packt Publishing, and as you'll hear in this podcast, they bring considerable insight and expertise to this discussion of what's happening in API management. The conversation goes beyond the current state of API management to delve into architectural implications, API design, and how working in SOA may have left you with some bad habits. Listen!

This program was recorded on June 27, 2018.

The Panelists Andrew Bell Andrew Bell
Oracle PaaS API Management Architect, Capgemini
Twitter  LinkedIn  Sander Rensen Sander Rensen
Oracle PaaS Lead and Architect, Capgemini
Twitter  LinkedIn  Luis Weir Luis Weir
CTO, Oracle DU, Capgemini
Oracle Developer Champion
Oracle ACE Director
Twitter LinkedIn Phil Wilkins
Senior Consultant specializing in iPaaS
Oracle ACE
Twitter LinkedIn  Additional Resources Coming Soon

How has your role as a developer, DBA, or Sysadmin changed? Our next program will focus on the evolution of IT roles and the trends and technologies that are driving the changes.

Keep Calm and Code On: Four Ways an Enterprise Blockchain Platform Can Improve Developer ...

Thu, 2018-07-12 01:45

A guest post by Sarabjeet (Jay) Chugh, Sr. Director Product Marketing, Oracle Cloud Platform

Situation

You just got a cool new Blockchain project for a client. As you head back to the office, you start to map out the project plan in your mind. Can you meet all of your client’s requirements in time? You're not alone in this dilemma.

You attend a blockchain conference the next day and get inspired by engaging talks, meet fellow developers working on similar projects. A lunchtime chat with a new friend turns into a lengthy conversation about getting started with Blockchain.

Now you’re bursting with new ideas and ready to get started with your hot new Blockchain coding project. Right?

Well almost…

You go back to your desk and contemplate a plan of action to develop your smart contract or distributed application, thinking through the steps, including ideation, analysis, prototype, coding, and finally building the client-facing application.

Problem

It is then that the reality sets in. You begin thinking beyond proof-of-concept to the production phase that will require additional things that you will need to design for and build into your solution. Additional things such as:
 

These things may delay or even prevent you from getting started with building the solution. Ask yourself the questions such as:

  • Should I spend time trying to fulfill dependencies of open-source software such as Hyperledger Fabric on my own to start using it to code something meaningful?
  • Do I spend time building integrations of diverse systems of record with Blockchain?
  • Do I figure out how to assemble components such as Identity management, compute infrastructure, storage, management & monitoring systems to Blockchain?
  • How do I integrate my familiar development tools & CI/CD platform without learning new tools?
  • And finally, ask yourself, Is it the best use of your time to figure out scaling, security, disaster recovery, point in time recovery of distributed ledger, and the “illities” like reliability, availability, and scalability?

If the answer to one or more of these is a resounding no, you are not alone. Focusing on the above aspects, though important, will take time away from doing the actual work to meet your client’s needs in a timely manner, which can definitely be a source of frustration.

But do not despair.

You need to read on about how an enterprise Blockchain platform such as the one from Oracle can make your life simpler. Imagine productivity savings multiplied hundreds of thousands of times across critical enterprise blockchain applications and chaincode.

What is an Enterprise Blockchain Platform?

The very term “enterprise”  typically signals a “large-company, expensive thing” in the hearts and minds of developers. Not so in this case, as it may be more cost effective than spending your expensive developer hours to build, manage, and maintain blockchain infrastructure and its dependencies on your own.

As the chart below shows, the top two Blockchain technologies used in proofs of concept have been Ethereum and Hyperledger.


 

Ethereum has been a platform of choice among the ICO hype for public blockchain use. However, it has relatively lower performance, is slower and less mature compared to Hyperledger. It also uses a less secure programming model based on a primitive language called Solidity, which is prone to re-entrant attacks that has led to prominent hacks like the DOA attack that lost $50M recently.  

Hyperledger Fabric, on the other hand, wins out in terms of maturity, stability, performance, and is a good choice for enterprise use cases involving the use of permissioned blockchains. In addition, capabilities such as the ones listed in Red have been added by vendors such as Oracle that make it simpler to adopt and use and yet retain the open source compatibility.

Let’s look at how enterprise Blockchain platform, such as the one Oracle has built that is based on open-source Hyperledger Fabric can help boost developer productivity.

How an Enterprise Blockchain Platform Drives Developer Productivity

Enterprise blockchain platforms provide four key benefits that drive greater developer productivity:

 
Performance at Scale

  • Faster consensus with Hyperledger Fabric
  • Faster world state DB - record level locking for concurrency and parallelization of updates to world state DB
  • Parallel execution across channels, smart contracts
  • Parallelized validation for commit

Operations Console with Web UI

  • Dynamic Configuration – Nodes, Channels
  • Chaincode Lifecycle – Install, Instantiate, Invoke, Upgrade
  • Adding Organizations
  • Monitoring dashboards
  • Ledger browser
  • Log access for troubleshooting

Resilience and Availability

  • Highly Available configuration with replicated VMs
  • Autonomous Monitoring & Recovery
  • Embedded backup of configuration changes and new blocks
  • Zero-downtime patching

Enterprise Development and Integration

  • Offline development support and tooling
  • DevOps CI/CD integration for chaincode deployment, and lifecycle management
  • SQL rich queries, which enable writing fewer lines of code, fewer lines to debug
  • REST API based integration with SaaS, custom apps, systems of record
  • Node.js, GO, Java client SDKs
  • Plug-and-Play integration adapters in Oracle’s Integration Cloud

Developers can experience orders of magnitude of productivity gains with pre-assembled, managed, enterprise-grade, and integrated blockchain platform as compared assembling it on their own.

Summary

Oracle offers a pre-assembled, open, enterprise-grade blockchain platform, which provides plug-and-play integrations with systems of records and applications and autonomous AI-driven self-driving, self-repairing, and self-securing capabilities to streamline operations and blockchain functionality. The platform is built with Oracle’s years of experience serving enterprise’s most stringent use cases and is backed by expertise of partners trained in Oracle blockchain. The platform rids developers of the hassles of assembling, integrating, or even worrying about performance, resilience, and manageability that greatly improves productivity.

If you’d like to learn more, Register to attend an upcoming webcast (July 16, 9 am PST/12 pm EST). And if your ready to dive right in you can sign up for $300 of free credits good for up to 3500 hours of Oracle Autonomous Blockchain Cloud Service usage.

Build and Deploy Node.js Microservice on Docker using Oracle Developer Cloud

Thu, 2018-07-05 03:48

This is the first blog in the series to come, which will help you understand, how you can build a NodeJS REST microservice application Docker image and push it to DockerHub using Oracle Developer Cloud Service. The next blog in the series would focus on deployment of the container we build here to deploy on Oracle Kubernetes Engine on Oracle Cloud infrastructure.

You can read about the overview of the Docker functionality in this blog.

Technology Stack Used

Developer Cloud Service - DevOps Platform

Node.js Version 6 – For microservice development.

Docker – For Build

Docker Hub – Container repository

 

Setting up the Environment:

Setting up Docker Hub Account:

You should create an account on https://hub.docker.com/. Keep the credentials handy for use in the build configuration section of the blog.

Setting up Developer Cloud Git Repository:

Now login into your Oracle Developer Cloud Service project. And create a Git repository as shown below. You can give a name of your choice to the Git repository. For the purpose of this blog, I am calling it NodeJSDocker. You can copy the Git repository URL and keep it handy for future use. 

Setting up Build VM in Developer Cloud:

Now we have to create a VM Template and VM with the Docker software bundle for the execution of the build.

Click on the user drop down on the right hand top of the page. Select “Organization” from the menu.

Click on the VM Templates tab and then on the “New Template” button. Give a template name of your choice and select the platform as “Oracle Linux 7”. And then click the Create button.

On creation of the template click on “Configure Software” button.

Select Docker from the list of software bundles available for configuration and click on the + sign to add it to the template. Then click on “Done” to complete the Software configuration.

Click on the Virtual Machines tab, then click on “+New VM” button and enter the number of VM(s) you want to create and select the VM Template you just created, which would be “DockerTemplate” for our blog.

 

Pushing Scripts to Git Repository on Oracle Developer Cloud:

Command_prompt:> cd <path to the NodeJS folder>

Command_prompt:>git init

Command_prompt:>git add –all

Command_prompt:>git commit –m “<some commit message>”

Command_prompt:>git remote add origin <Developer cloud Git repository HTTPS URL>

Command_prompt:>git push origin master

Below screen shots are for your reference.

 

Below is the folder structure description for the code that I have in the Git Repository on Oracle Developer Cloud Service.

Code in the Git Repository:

You will need to push the below 3 files in the Developer Cloud hosted Git repository which we have created.

Main.js

This is the main Node JavaScript code snippet which contains two simple methods, first one is to show the message and second one /add is for adding two numbers. The application listens at port 80. 

var express = require("express"); var bodyParser = require("body-parser"); var app = express(); app.use(bodyParser.urlencoded()); app.use(bodyParser.json()); var router = express.Router(); router.get('/',function(req,res){   res.json({"error" : false, "message" : "Hello Abhinav!"}); }); router.post('/add',function(req,res){   res.json({"error" : false, "message" : "success", "data" : req.body.num1 + req.body.num2}); }); app.use('/',router); app.listen(80,function(){   console.log("Listening at PORT 80"); })

Package.json

In this JSON code snippet we define the Node.js module dependencies. We also define the start file, which is Main.js for our project and the Name of the application.

{   "name": "NodeJSMicro",   "version": "0.0.1",   "scripts": {     "start": "node Main.js"   },   "dependencies": {     "body-parser": "^1.13.2",     "express": "^4.13.1"     } }

Dockerfile

This file will contains the commands to be executed to build the Docker container with the Node.js code. It starts by getting the Node.js version 6 Docker image, then adds the two files Main.js and package.json cloned from the Git repository. Run the npm install to download the dependencies in package.json file. Expose port 80 for Docker container. And finally start the application to listen on port 80.

 

FROM node:6 ADD Main.js ./ ADD package.json ./ RUN npm install EXPOSE 80 CMD [ "npm", "start" ]

Build Configuration:

Click on the “+ New Job” button and in the dialog which pops up, give the build job a name of your choice(for the purpose of this blog I have given this as “NodeJSMicroDockerBuild”) and then select the build template (DockerTemplate) from the dropdown, that we had created earlier in the blog. 

As part of the build configuration, add Git from the “Add Source Control” dropdown. And now select the repository we created earlier in the blog, which is NodeJSDocker and the master branch to which we have pushed the code. You may select the checkbox to configure automatic build trigger on SCM commits.

Now from the Builders tab, select Docker Builder -> Docker Login. In the Docker login form you can leave the Registry host empty as we will be using Docker Hub which is the default Docker registry for Developer Cloud Docker Builder. You will have to provide the Docker Hub account username and password in the respective fields of the login form.

In the Builders tab, select Docker Builder -> Docker Build from the Add Builder dropdown. You can leave the Registry host empty as we are going to use Docker Hub which is the default registry. Now, you just need to give the Image name in the form that gets added and you are all done with the Build Job configuration. Click on Save to save the build job configuration.

Note: Image name should be in the format <Docker Hub user name>/<Image Name>

For this blog we can give the image name as - nodejsmicro

Then add Docker Push by selecting Docker Builder -> Docker Push from the Builders tab.Here you just need to mention the Image name, same as you have done in the Docker Build form to push the Docker Image build to the Docker Registry, which in this case is Docker Hub.

Once you execute the build, you will be able to see the build in the build queue.

Once the build gets executed the Docker Image that gets build is pushed to the Docker Registry which is Docker Hub for our blog. You can login into your Docker Hub account to see the Docker repository being created and the image being pushed to it, as seen in the screen shot below.

Now you can pull this image anywhere, then create and run the container, you will have your Node.js microservice code up and running.

 

You can go ahead and try many other Docker commands both using the out of the box Docker Builder functionality and also alternatively using the Shell Builder to run your Docker commands.

In the next blog, of the series, we will deploy this Node.js microservice container on a Kubernetes cluster in Oracle Kubernetes Engine.

Happy Coding!

 **The views expressed in this post are my own and do not necessarily reflect the views of Oracle

 

 

Lessons From Alpha Zero (part 5): Performance Optimization

Tue, 2018-07-03 13:30

Photo by Mathew Schwartz on Unsplash

(Originally published on Medium)

This is the Fifth installment in our series on lessons learned from implementing AlphaZero. Check out Part 1, Part 2, Part 3, and Part4.

In this post, we review aspects of our AlphaZero implementation that allowed us to dramatically improve the speed of game generation and training.

  Overview

The task of implementing AlphaZero is daunting, not just because the algorithm itself is intricate, but also due to the massive resources the authors employed to do their research: 5000 TPUs were used over the course of many hours to train their algorithm, and that is presumably after a tremendous amount of time was spent determining the best parameters to allow it to train that quickly.

By choosing Connect Four as our first game, we hoped to make a solid implementation of AlphaZero while utilizing more modest resources. But soon after starting, we realized that even a simple game like Connect Four could require significant resources to train: in our initial implementation, training would have taken weeks on a single gpu-enabled computer.

Fortunately, we were able to make a number of improvements that made our training cycle time shrink from weeks to about a day. In this post I’ll go over some of our most impactful changes.

  The Bottleneck

Before diving into some of the tweaks we made to reduce AZ training time, let’s describe our training cycle. Although the authors of AlphaZero used a continuous and asynchronous process to perform model training and updates, for our experiments we used the following three stage synchronous process, which we chose for its simplicity and debugability:

While (my model is not good enough):

  1. Generate Games: every model cycle, using the most recent model, game play agents generate 7168 games, which equates to about 140–220K game positions.
  2. Train a New Model: based on a windowing algorithm, we sample from historical data and train an improved neural network.
  3. Deploy the New Model: we now take our new model, transform it into a deployable format, and push it into our cloud for the next cycle of training

Far and away, the biggest bottleneck of this process is game generation, which was taking more than an hour per cycle when we first got started. Because of this, minimizing game generation time became the focus of our attention.

  Model Size

Alpha Zero is very inference heavy during self-play. In fact, during one of our typcal game generation cycles, MCTS requires over 120 Million position evaluations. Depending on the size of your model, this can translate to siginificant GPU time.

In the original implementation of AlphaZero, the authors used an architecture where the bulk of computation was performed in 20 residual layers each with 256 filters. This amounts to a model in excess of 90 megabytes, which seemed overkill for Connect Four. Also, using a model of that size was impractical given our initially limited GPU resources.

Instead, we started with a very small model, using just 5 layers and 64 filters, just to see if we could make our implementation learn anything at all. As we continued to optimize our pipeline and improve our results, we were able to bump our model size to 20X128 while still maintaining a reasonable game generation speed on our hardware.

  Distributed Inference

From the get-go, we knew that we would need more than one GPU in order to achieve the training cycle time that we were seeking, so we created software that allowed our Connect 4 game agent to perform remote inference to evaluate positions. This allowed us to scale GPU-heavy inference resources separately from game play resources, which need only CPU.

  Parallel Game Generation

GPU resources are expensive, so we wanted to make sure that we were saturating them as much as possible during playouts. This turned out to be trickier than we imagined.

One of the first optimizations we put in place was to run many games on parallel threads from the same process. Perhaps the largest direct benefit of this, is that it allowed us to cache position evaluations, which could be shared amongst different threads. This cut the number of requests getting sent to our remote inference server by more than a factor of 2:


Caching was a huge win, but we still wanted to deal with the remaining uncached requests in an efficient manner. To minimize network latency and best leverage GPU parallelization, we combined inference requests from different worker threads into a bucket before sending them to our inference service. The downside to this is that if a bucket was not promptly filled, any calling thread would be stuck waiting until the bucket’s timeout expired. Under this scheme, choosing an appropriate inference bucket size and timeout value was very important.


We found that bucket fill rate varied throughout the course of a game generation batch, mostly because some games would finish sooner than others, leaving behind fewer and fewer threads to fill the bucket. This caused the final games of a batch to take a long time to complete, all while GPU utilization dwindled to zero. We needed a better way to keep our buckets filled.

  Parallel MCTS

To help with our unfilled bucket problem, we implemented Parallel MCTS, which was discussed in the AZ paper. Initially we had punted on this detail, as it seemed mostly important for competitive one-on-one game play, where parallel game play is not applicable. After running into the issues mentioned previously, we decided to give it a try.

The idea behind Parallel MCTS is to allow multiple threads to take on the work of accumulting tree statistics. While this sounds simple, the naiive approach suffers from a basic problem: if N threads all start at the same time and choose a path based on the current tree statistics, they will all choose exactly the same path, thus crippling MCTS’ exploration component.

To counteract this, AlphaZero uses the concept of Virtual Loss, an algorithm that temporarily adds a game loss to any node that is traversed during a simulation. A lock is used to prevent multiple threads from simultaneously modifying a node’s simulation and virtual loss statistics. After a node is visited and a virtual loss is applied, when the next thread visits the same node, it will be discouraged from following the same path. Once a thread reaches a terminal point and backs up its result, this virtual loss is removed, restoring the true statistics from the simulation.


With virtual loss in place, we were finally able to achieve >95% GPU utilization during most of our game generation cycle, which was a sign that we were approaching the real limits of our hardware setup.

Technically, virtual loss adds some degree of exploration to game playouts, as it forces move selection down paths that MCTS may not naturally be inclined to visit, but we never measured any detrimental (or beneficial) effect due to its use.

  TensorRT/TensorRT+INT8

Though it was not necessary to use a model quite as large as that described in the AlphaZero paper, we saw better learning from larger models, and so wanted to use the biggest one possible. To help with this, we tried TensorRT, which is a technology created by Nvidia to optimize the performance of model inference.

It is easy to convert an existing Tensorflow/Keras model to TensorRT using just a few scripts. Unfortunately, at the time we were working on this, there was no released TensorRT remote serving component, so we wrote our own.

With TensorRT’s default configuration, we noticed a small increase in inference throughput (~11%). We were pleased by this modest improvement, but were hopeful to see an even larger performance increase by using TensorRT’s INT8 mode. INT8 mode required a bit more effort to get going, since when using INT8 you must first generate a calibration file to tell the inference engine what scale factors to apply to your layer activations when using 8-bit approximated math. This calibration is done by feeding a sample of your data into Nvidia’s calibration library.

Because we observed some variation in the quality of calibration runs, we would attempt calibration against 3 different sets of sample data, and then validate the resulting configuraton against hold-out data. Of the three calibration attempts, we chose the one with the lowest validation error.


Once our INT8 implementation was in place, we saw an almost 4X increase in inference throughput vs. stock libtensorflow, which allowed us to use larger models than would have otherwise been feasible.


One downside of using INT8 is that it can be lossy and imprecise in certain situations. While we didn’t observe serious precision issues during the early parts of training, as learning progressed we would observe the quality of inference start to degrade, particularly on our value output. This initially led us to use INT8 only during the very early stages of training.

Serendipitously, we were able to virtually eliminate our INT8 precision problem when we began experimenting with increasing the number of convolutional filters in our head networks, an idea we got from Leela Chess. Below is a chart of our value output’s mean average error with 32 filters in the value head, vs. the AZ default of 1:


We theorize that adding additional cardinality to these layers reduces the variance in the activations, which makes the model easier to accurately quantize. These days, we always perfom our game generation with INT8 enabled and see no ill effects even towards the end of AZ training.

  Summary

By using all of these approaches, we were finally able to train a decent-sized model with high GPU utilization and good cycle time. It was initially looking like it would take weeks to perform a full train, but now we could train a decent model in less than a day. This was great, but it turned out we were just getting started — in the next article we’ll talk about how we tuned AlphaZero itself to get even better learning speed.

Part 6 is now out.

Thanks to Vish (Ishaya) Abrams and Aditya Prasad.

Pages