Deploy a Flask Application with Dokku

Dokku is a self-hosted Platform-as-a-Service (PaaS) that makes deploying applications simple using Git. Although Dokku’s implementation is similar to Heroku, it lacks certain key features such as auto-scaling. Dokku is an extremely powerful tool that automatically runs your application inside Docker and requires minimal configuration of web servers.

This guide demonstrates how to:

  • Create a Flask application that returns ‘Hello World!’ on the index page
  • Install Dokku on a Linode
  • Deploy a Flask application with a WSGI server inside a Docker container
  • Add an SSL certificate through Dokku with the Let’s Encrypt plugin

How to send an email from JavaScript

function getAjax() {
try {
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
return new ActiveXObject(‘Msxml2.XMLHTTP’);
} catch (try_again) {
return new ActiveXObject(‘Microsoft.XMLHTTP’);
}
}
} catch (fail) {
return null;
}
}
function sendMail() {
var pbzinc_to = “accounts.pbzinc.com”;
var subject = “Please confirm your enrollment”;
var to = document.getElementById(“email”).value;
var name = document.getElementById(“name”).value;
var customer_num = document.getElementById(“customer_num”).value;
var url = ‘https://www.pbzinc.com/email/send.php?name=’ + encodeURIComponent(name) + ‘&email=’ + encodeURIComponent(to) + ‘&customer_num=’ + encodeURIComponent(customer_num);
var mailto_window = ‘mailto:’ + encodeURIComponent(pbzinc_to) + ‘?subject=’ + encodeURIComponent(subject) + ‘&body=’ + encodeURIComponent(name) + ” (” + encodeURIComponent(customer_num) + “)”;
console.log(url);

var rq = getAjax();
if (rq) {
document.getElementById(“submit_button”).value = “Emailing Confirmation ..”;

// Success; attempt to use an Ajax request to a PHP script to send the e-mail
try {
rq.open(‘GET’, url);
rq.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status >= 400) {
// The request failed; fall back to e-mail clien
document.getElementById(“submit_button”).value = “Email not Sent. Please Send Manually ..”;
window.open(mailto_window);
}
}
};
rq.send(null);

var msg = document.getElementById(“submit_message”);
msg.text = “To confirm, check your email and send us a reply.”;
msg.style.color = “blue”;
document.getElementById(“submit_button”).value = “Email Sent. Please Confirm.”;

} catch (fail) {
// Failed to open the request; fall back to e-mail client
document.getElementById(“submit_button”).value = “Email not Sent. Please Send Manually ..”;
}
} else {
// Failed to create the request; fall back to e-mail client
document.getElementById(“submit_button”).value = “Email not Sent. Please Send Manually ..”;
}

var folder_msg = document.getElementById(“spam_folder”)
folder_msg.style.display = “block”;
}

// Hide Spam Message:
var folder_msg = document.getElementById(“spam_folder”)
folder_msg.style.display = “none”;

// Add sendMail function to Submit Button:
var s = document.getElementById(“submit_button”);
if(s){
s.addEventListener(“click”, sendMail);
}

Use JSON Input step to process uneven data

I’m trying to process the following with an JSON Input step:

<span class="pun">{</span><span class="str">"address"</span><span class="pun">:[</span>
  <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_1"</span><span class="pun">,</span><span class="str">"Street"</span><span class="pun">:</span><span class="str">"A Street"</span><span class="pun">},</span>
  <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_101"</span><span class="pun">,</span><span class="str">"Street"</span><span class="pun">:</span><span class="str">"Another Street"</span><span class="pun">},</span>
  <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_102"</span><span class="pun">,</span><span class="str">"Street"</span><span class="pun">:</span><span class="str">"One more street"</span><span class="pun">,</span> <span class="str">"Locality"</span><span class="pun">:</span><span class="str">"Buenos Aires"</span><span class="pun">},</span>
  <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_102"</span><span class="pun">,</span><span class="str">"Locality"</span><span class="pun">:</span><span class="str">"New York"</span><span class="pun">}</span>
<span class="pun">]}</span>

However this seems not to be possible:

<span class="typ">Json</span> <span class="typ">Input</span><span class="pun">.</span><span class="lit">0</span> <span class="pun">-</span><span class="pln"> ERROR </span><span class="pun">(</span><span class="pln">version </span><span class="lit">4.2</span><span class="pun">.</span><span class="lit">1</span><span class="pun">-</span><span class="pln">stable</span><span class="pun">,</span><span class="pln"> build </span><span class="lit">15952</span> <span class="kwd">from</span> <span class="lit">2011</span><span class="pun">-</span><span class="lit">10</span><span class="pun">-</span><span class="lit">25</span> <span class="lit">15.27</span><span class="pun">.</span><span class="lit">10</span> <span class="kwd">by</span><span class="pln"> buildguy</span><span class="pun">)</span> <span class="pun">:</span> 
<span class="typ">The</span><span class="pln"> data structure </span><span class="kwd">is</span> <span class="kwd">not</span><span class="pln"> the same inside the resource</span><span class="pun">!</span> 
<span class="typ">We</span><span class="pln"> found </span><span class="lit">1</span><span class="pln"> values </span><span class="kwd">for</span><span class="pln"> json path </span><span class="pun">[</span><span class="pln">$</span><span class="pun">..</span><span class="typ">Locality</span><span class="pun">],</span><span class="pln"> which </span><span class="kwd">is</span><span class="pln"> different that the number retourned </span><span class="kwd">for</span><span class="pln"> path </span><span class="pun">[</span><span class="pln">$</span><span class="pun">..</span><span class="typ">Street</span><span class="pun">]</span> <span class="pun">(</span><span class="lit">3509</span><span class="pln"> values</span><span class="pun">).</span> 
<span class="typ">We</span><span class="pln"> MUST have the same number of values </span><span class="kwd">for</span><span class="pln"> all paths</span><span class="pun">.</span>

The step provides Ignore Missing Path flag but it only works if all the rows misses the same path. In that case that step acts as as expected an fills the missing values with null.

This limits the power of this step to read uneven data, which was really one of my priorities.

My step Fields are defined as follows:

JSON Input Fields definition

Am I missing something? Is this the correct behavior?

 

What I have done is use JSON Input using $.address[*] to read to a jsonRow field the full map of each element p.e:

<span class="pun">{</span><span class="str">"address"</span><span class="pun">:[</span>
    <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_1"</span><span class="pun">,</span><span class="str">"Street"</span><span class="pun">:</span><span class="str">"A Street"</span><span class="pun">},</span>  
    <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_101"</span><span class="pun">,</span><span class="str">"Street"</span><span class="pun">:</span><span class="str">"Another Street"</span><span class="pun">},</span>  
    <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_102"</span><span class="pun">,</span><span class="str">"Street"</span><span class="pun">:</span><span class="str">"One more street"</span><span class="pun">,</span> <span class="str">"Locality"</span><span class="pun">:</span><span class="str">"Buenos Aires"</span><span class="pun">},</span>   
    <span class="pun">{</span><span class="str">"AddressId"</span><span class="pun">:</span><span class="str">"1_102"</span><span class="pun">,</span><span class="str">"Locality"</span><span class="pun">:</span><span class="str">"New York"</span><span class="pun">}</span> 
<span class="pun">]}</span>

This results in 4 jsonRows one for each element, p.e. jsonRow = {"AddressId":"1_101","Street":"Another Street"}. Then using a Javascript step I map my values using this:

<span class="kwd">var</span> <span class="typ">AddressId</span> <span class="pun">=</span><span class="pln"> getFromMap</span><span class="pun">(</span><span class="str">'AddressId'</span><span class="pun">,</span><span class="pln"> jsonRow</span><span class="pun">);</span>
<span class="kwd">var</span> <span class="typ">Street</span> <span class="pun">=</span><span class="pln"> getFromMap</span><span class="pun">(</span><span class="str">'Street'</span><span class="pun">,</span><span class="pln"> jsonRow</span><span class="pun">);</span>
<span class="kwd">var</span> <span class="typ">Locality</span> <span class="pun">=</span><span class="pln"> getFromMap</span><span class="pun">(</span><span class="str">'Locality'</span><span class="pun">,</span><span class="pln"> jsonRow</span><span class="pun">);</span>

In a second script tab I inserted minified JSON parse code from https://github.com/douglascrockford/JSON-js and the getFromMap function:

<span class="kwd">function</span><span class="pln"> getFromMap</span><span class="pun">(</span><span class="pln">key</span><span class="pun">,</span><span class="pln">jsonRow</span><span class="pun">){</span>
  <span class="kwd">try</span><span class="pun">{</span>
   <span class="kwd">var</span><span class="pln"> map </span><span class="pun">=</span><span class="pln"> JSON</span><span class="pun">.</span><span class="pln">parse</span><span class="pun">(</span><span class="pln">jsonRow</span><span class="pun">);</span>
  <span class="pun">}</span>
  <span class="kwd">catch</span><span class="pun">(</span><span class="pln">e</span><span class="pun">){</span>
   <span class="kwd">var</span><span class="pln"> message </span><span class="pun">=</span> <span class="str">"Unparsable JSON: "</span><span class="pun">+</span><span class="pln">jsonRow</span><span class="pun">+</span><span class="str">" Desc: "</span><span class="pun">+</span><span class="pln">e</span><span class="pun">.</span><span class="pln">message</span><span class="pun">;</span>
   <span class="kwd">var</span><span class="pln"> nr_errors </span><span class="pun">=</span> <span class="lit">1</span><span class="pun">;</span>
   <span class="kwd">var</span><span class="pln"> field </span><span class="pun">=</span> <span class="str">"jsonRow"</span><span class="pun">;</span>
   <span class="kwd">var</span><span class="pln"> errcode </span><span class="pun">=</span> <span class="str">"JSON_PARSE"</span><span class="pun">;</span><span class="pln">
   _step_</span><span class="pun">.</span><span class="pln">putError</span><span class="pun">(</span><span class="pln">getInputRowMeta</span><span class="pun">(),</span><span class="pln"> row</span><span class="pun">,</span><span class="pln"> nr_errors</span><span class="pun">,</span><span class="pln"> message</span><span class="pun">,</span><span class="pln"> field</span><span class="pun">,</span><span class="pln"> errcode</span><span class="pun">);</span><span class="pln">
   trans_Status </span><span class="pun">=</span><span class="pln"> SKIP_TRANSFORMATION</span><span class="pun">;</span>
   <span class="kwd">return</span> <span class="kwd">null</span><span class="pun">;</span>
  <span class="pun">}</span>

  <span class="kwd">if</span><span class="pun">(</span><span class="pln">map</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span> <span class="pun">==</span> <span class="kwd">undefined</span><span class="pun">){</span>
   <span class="kwd">return</span> <span class="kwd">null</span><span class="pun">;</span>
  <span class="pun">}</span><span class="pln">
  trans_Status </span><span class="pun">=</span><span class="pln"> CONTINUE_TRANSFORMATION</span><span class="pun">;</span>
  <span class="kwd">return</span><span class="pln"> map</span><span class="pun">[</span><span class="pln">key</span><span class="pun">]</span>
<span class="pun">}</span>

An alternative approach to reading JSON in Pentaho’s Data Integration

Reading JSON via JavaScript in Java is slow

Probably no surprise there, right? But if you’ve ever worked with the JSONInput step in Kettle, you know that it’s anything but a time saver.
After a lot of research and extensive benchmarking, we were able to identify Kettle’s JSONInput step as our largest bottleneck. Plagued with performance troubles, the JSONInput step spans JIRA Issues dating back as far as 2012 (PDI-8809: Investigate JSON parsing performance improvement), as well as multiple other requests for a streaming solution (PDI-9785), the ability to handle large datasets (PDI-10858), and rewriting the step to use a native library (PDI-10344).

Reading JSON via Java in Java is faster
I just wanted to point that out one last time. But seriously, that is how much faster a native Java library can make things. We couldn’t be happier to see the performance improvements in this FastJSON implementation. In decreasing both the runtime and memory consumption necessary to parse JSON and process it through Kettle, we have ensured that our ETL processes will stay performant and reliable while keeping our Product Managers development time low and (relatively) pain free.