Archive for April, 2019

There is a Reason I’m an Apple Fan

Saturday, April 27th, 2019

Apple Computers

Over the course of the last few weeks, I've noticed that my Late 2016 15" MacBook Pro was "rocking" a little on my desk. As if the bottom of the case was "bowed", and so pressing on the space next to the trackpad made the back-end lift up. Now I've heard about the damaged Li-Ion batteries, and even replaced one in a battery pack on my Mom's old 13" MacBook Pro several years ago, but I was in a bit of denial about this one, as I was hoping it was "something else". 🙂

Finally, yesterday I called Apple to see if the local Naperville Apple Store could replace the battery without having to ship it to the Service Center. They were vague - saying it was possible, but that would depend on a lot of things. In the end, I really had to just take it to them, and see. So I made a Genius Bar appointment.

When they saw it, they agreed - damaged Li-Ion battery, but that it'd have to go out for service. I'd be without it for 3 - 5 days. That's too long for me, as it's the only place I get my email, and notifications, and some of those are very important. So I knew it was time to get a new machine, migrate over, and then send the old one back for repair, and keep it as a spare.

Luckily, the Apple Store has a "Secret Supply" of high-end configurations that don't show up on the web site, and they had exactly the machine I would have ordered, so I could migrate things over last night. But the real surprise is that Apple would do this for free. Wow... a $300 battery replacement for free. 🙂

Sure... they probably do this because of the fire hazard, but to me - it's just free. Now I'll take it to the Apple Store today, they will ship it off to get fixed, and when it returns in a week or so, it'll be a great back-up machine.

Added a Few Things to Timeless

Saturday, April 27th, 2019

Javascript

My friend, that asked for the Timeless project, pinged me yesterday to say that he really would like to have a "clear" button on the page so that it cleared out all the data in the table. I said I'd look at it today - as soon as I got back up to speed with my new laptop. More on that later. 🙂

What I needed to do was to add a function to wipe out the HandsOnTable, and that wasn't too bad... simply get the row count, and clear out the timestamp data:

  /*
   * Function to clear out the timestamps from the table, and then refresh
   * the table to make sure that it's all cleared out and ready to go.
   */
  function wipeTable(tid) {
    var rows = $(tid).handsontable('countRows');
    for (var i = 0; i < rows; i++) {
      $(tid).handsontable('setDataAtCell', i, 0, '');
      $(tid).handsontable('setDataAtCell', i, 1, '');
    }
  }

Then I just needed to update the HandsOnTable formatter for the computed difference so that if the timestamp cell was empty, we put null in the computed column, and then that would work for both the clearing and the totally empty rows:

  /*
   * The Timeline table needs to have a computed 'diff' for the current line
   * to the previous line. These are all msec times, so it's just a difference
   * of two numbers. Shouldn't be hard. :)
   */
  var timeDiff = function(instance, td, row, col, prop, value) {
    if (instance.getDataAtCell(row, 0)) {
      var a = instance.getDataAtCell(row, 1);
      var b = instance.getDataAtCell((row - 1), 1);
      value = ($.isNumeric(a) ? a : 0) - ($.isNumeric(b) ? b : 0);
    } else {
      value = null;
    }
    Handsontable.NumericRenderer.apply(this, arguments);
  }

And then I needed to place a button in the header of the panel with the table:

  <div class="panel-heading">
    <h3 class="panel-title"><span id="timelineTitle">Timeline Evolution Worksheet</span>
      <form id="wipe_table" class="navbar-form navbar-right pullright"
            role="search" style="margin-top: -8px; display: visible;">
        <button id="wipeTable" class="btn btn-default">
          <span class="glyphicon glyphicon-trash"></span>
        </button>
      </form>
    </h3>
  </div>

Finally, I needed to disable the default function of the form, and wipe the table with:

  // set up the form components to work as we need them
  $("#wipe_table").submit( function(e) {
    e.preventDefault();
    wipeTable('#timelineTable');
  });

Now we have the "trash can" icon in the panel header, and it works like a charm!

Timeless Clear Table

HandsOnTable really is a nice tool. I can see doing a lot of cool things with it.

Finally Moving to Heroku

Wednesday, April 24th, 2019

Heroku

This morning, I realized it was about time to really shop around and see if Heroku or AWS was the right choice for my projects. Now I've heard, and mentioned, that it's likely that the best solution is Heroku, and after digging into all the capabilities and costs, it really is far easier and cheaper to use Heroku and just let it be done. The support for Clojure is first class, and the tools have gotten a lot better, and the pricing has come down, and that was all it took.

The first thing to do was to sign up at Heroku for an account, and then set up that account with the right SSH key, and 2FA with Authy on my iPhone, and then put in the credit card info to be a Validated user - and get more free hours a month for the "Free" dynes. All this was very nice, and really smooth. I liked that the 2FA with Authy is as easy as it is, because it pulls in the account information and icon, and it just plain works.

The next thing was to walk through the example Clojure project to see how it's done. What really matters is that it works, and then I can pick out things from that project - which also uses Jetty, and pull them into my project to get it going as well. As expected, that went very well, and the documentation is really first rate. Just what I've heard I could expect.

Finally, I followed their instructions to scale down the dynos to 0 on the example project, and started to work on converting my project from the old deployment model I had to using Heroku. First off, we needed to pull in the Procfile and app.json from the example project, and then update them to match what we needed for this project. The Procfile was updated to be:

  web: java $JVM_OPTS -cp target/timeless-standalone.jar timeless.main web

because the old init.d scripts I'm used to writing had this same basic line in them. We have to fix up the Uberjar file name, but we'll do that in a minute, but this will launch the Jetty server on the right port, and have everything cooking just fine.

The app.json was updated to be:

{
  "name": "Timeless: Sequencing timestamps",
  "description": "A service/app that helps sequence timestamps from log files.",
  "image": "heroku/clojure"
}

and here, it's pretty obvious what to update - just the name and description.

At this point, we can create the application at Heroku:

  $ heroku create

We need to make a few changes to the code so that it would work with the Heroku infrastructure. First, we had to update the project.clj to add these entries:

  :min-lein-version "2.7.1"
  :plugins [[environ/environ.lein "0.3.1"]]
  :hooks [environ.leiningen.hooks]
  :dependencies [[org.clojure/clojure "1.10.0"]
                 ;; ...other dependencies...
 
                 ;; Heroku environment tools
                 [environ "1.0.0"]]
  :uberjar-name "timeless-standalone.jar"
  :profiles {:uberjar {:main timeless.main, :aot :all}}

Then, in main.clj, we needed to pull the port for Jetty from Heroku's environment variables, and to do this, we updated the code to read:

(defn handle-args
  "Function to parse the arguments to the main entry point of this project and
  do what it's asking. By the time we return, it's all done and over."
  [args app]
  (let [[params [action]] (cli args
             ["-p" "--port"     "Listen on this port" :default 8080 :parse-fn #(Integer. %)]
             ["-s" "--ssl-port" "Listen on this port" :default 8443 :parse-fn #(Integer. %)]
             ["-v" "--verbose" :flag true])
        quiet? (:quiet params)
        fixed? (:fixed params)
        port (Integer. (or (env :port) (:port params) 5000))]
    (cond
      (= "web" action)
		      (try
		        (jt/run-jetty app {:port port})
		        ; finally, close down the async jobs
		        (finally
		          ))
      :else
        (do
          (info "Welcome to Timeless!")
          (println "Welcome to Timeless")))))

the key being to check the :port value with the env function, and then put that in the or before the default from the CLI args. It makes sense, they will want to set the port on the process so that they can stack a lot of them on a single box.

After this, it's as simple as deploying the app with:

  $ git push heroku master
  $ heroku ps:scale web=1

and it should all be running just fine.

When I added the CNAME records to my DNS for this domain, I get a certificate problem because we're moving from bobbeaty.com to herokuapp.com - so I still have to figure that out to make things really smooth, but this is a huge step in the right direction.

UPDATE: the key is not to add it as a CNAME - but a simply web permanent redirection. If we do that, then we can add it as: bobbeaty.com/timeless and we're all good!

RedHat Assumes Stewardship of OpenJDK 8 and 11

Monday, April 22nd, 2019

java-logo-thumb.png

Interesting, that a few days after I move off Oracle's JDKs for my laptop, RedHat announces that it's going to assume stewardship of OpenJDK 8 and 11 from Oracle. It seems that Oracle wants to get out of the enterprise java business as it moved J2EE support to the Eclipse Foundation, and this just makes it clear that they really don't want to be in the Java business - at all.

This could be that they can't make enough money on it - or that they are just more interested in GraalVM, which they control, and can be used to compile a large subset of Java code into machine code. With this control, what do they need with the OpenJDK spec? It's just weight and cost. Better to get someone else to take care of that, and get back to making money licensing what they can.

It's just sad, but all too familiar, with Oracle. Glad I moved off. I'll stick with AdoptOpenJDK until there's a reason to move.

Finally Updating to AdoptOpenJDK for JDK 8 and JDK 11

Thursday, April 18th, 2019

java-logo-thumb.png

This morning I decided to really dig into the Homebrew support for AdoptOpenJDK - and while I was initially a little unsure of the AdoptOpenJDK group, after reading their web site, and digging into their Homebrew cask, I was convinced to give it a try. It will keep things moving with updates on the JDKs - delivering JDK 1.8.0r212 as of today, and that's what my biggest fear was. So let's get to it.

In order to get the very latest AdoptOpenJDK (11), it was as simple as:

  $ brew cask install adoptopenjdk

which resulted in my installation directory looking like:

  $ ls /Library/Java/JavaVirtualMachines/
  1.6.0_26-b03-383.jdk/    jdk1.7.0_45.jdk/         jdk1.8.0_144.jdk/
  adoptopenjdk-11.0.2.jdk/ jdk1.7.0_51.jdk/         jdk1.8.0_181.jdk/
  jdk-10.0.2.jdk/          jdk1.7.0_75.jdk/         jdk1.8.0_40.jdk/
  jdk1.7.0_13.jdk/         jdk1.8.0_131.jdk/        openjdk-11.0.2.jdk/

At this point, I could remove the openjdk-11.0.2.jdk/ install, as that's from Oracle, proper, and I really just want to let that go due to the licensing...

  $ brew cask uninstall java

and then re-select the correct JDK 11 with:

  $ setjdk 11; echo $JAVA_HOME
  /Library/Java/JavaVirtualMachines/adoptopenjdk-11.0.2.jdk/Contents/Home

So it was installed properly, and picked up the new installation from AdoptOpenJDK. Good. Now in order to pick up the older versions, we can follow the instructions on the Homebrew cask:

  $ brew tap AdoptOpenJDK/openjdk
  $ brew cask install adoptopenjdk8

and after this, we have the following installed on my machine:

  $ ls
  1.6.0_26-b03-383.jdk/    jdk1.7.0_13.jdk/         jdk1.8.0_131.jdk/
  adoptopenjdk-11.0.2.jdk/ jdk1.7.0_45.jdk/         jdk1.8.0_144.jdk/
  adoptopenjdk-8.jdk/      jdk1.7.0_51.jdk/         jdk1.8.0_181.jdk/
  jdk-10.0.2.jdk/          jdk1.7.0_75.jdk/         jdk1.8.0_40.jdk/

and I have to admit, I'm a little concerned about the lack of a release number on the AdoptOpenJDK 8's directory - but maybe that will be handled a little differently as they version them. We will have to wait and see.

At this point, we can:

  $ setjdk 1.8; echo $JAVA_HOME
  /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
  $ java -version
  openjdk version "1.8.0_212"
  OpenJDK Runtime Environment (AdoptOpenJDK)(build 1.8.0_212-b03)
  OpenJDK 64-Bit Server VM (AdoptOpenJDK)(build 25.212-b03, mixed mode)

To make sure that we don't cleanup the old versions with Homebrew, when I install a new one, I added the following to my ~/.bashrc:

  export HOMEBREW_NO_INSTALL_CLEANUP=1

Which Homebrew says will keep from doing the automatic cleanups on the installs.

To do a final check with the AdoptOpenJDK 1.8.0r212, I checked what Leiningen was saying:

  $ lein --version
  Leiningen 2.8.3 on Java 1.8.0_212 OpenJDK 64-Bit Server VM

At this point, I've got AdoptOpenJDK 1.8.0r212, and 11.0.2, and updating each is very simple with brew. I just need to:

  $ brew update
  $ brew cask upgrade adoptopenjdk
  $ brew cask upgrade adoptopenjdk8

and then when I want, I can clean up the older versions with:

  $ brew update
  $ brew cleanup adoptopenjdk
  $ brew cleanup adoptopenjdk8

This is so much cleaner, and I don't have to worry about the crazy licensing from Oracle. It's a lot nicer place to be.

Oracle Java JDK 8r211 Updates License

Wednesday, April 17th, 2019

java-logo-thumb.png

This morning I got an update notice on Java 8 on my machine - it was for JDK 8r211, and during the normal update process, the installer popped up a dialog box where it was very clear that the terms of the license for JDK 8r211 have changed.

Specifically, it stated that this JDK was only for non-commercial use, and if it was going to be used in a commercial environment, then a license would have to be obtained from Oracle.

This is the JDK 11 license, and why I went through the pain to get OpenJDK 11 on my laptop, because I just can't see even pretending to use a product that I know I won't ever use in production. Now, I have to stick with the version of JDK 8 I've got installed, because I don't see an easy path to get OpenJDK 8 from Homebrew. There's an old cask, but I don't know that it's any more current than what I have - and I don't know that I need anything more current.

Just seems so short-sighted by Oracle, but they see a revenue stream, and go after it.

DataGraph 4.3 for Amazing Scientific Plotting

Tuesday, April 16th, 2019

DataGraph1.5.jpg

This afternoon, after reading a Master's Thesis on the prediction of the Corn Spot Prices, I was talking to a friend about using Mathematica, and how much I'd really enjoy getting back into the mathematically-based work I did in my Thesis, and how if this new work was put in a service, Clojure would be the obvious choice, and plotting would be easily done with DataGraph, which is just a beautiful way to create publication-quality plots.

Here's an evolution of an electron pulse evolution in GaAs:

GaAs Pulse Evolution

I've been using this for years, and now I read in the 4.4 beta release notes, they are going to be adding tools to make it easier to get data into the app, and so it might make it all a lot easier for me and intergrating it with Clojure. That would be very nice.

Fun Egg Hunt at The Shop

Tuesday, April 16th, 2019

cubeLifeView.gif

This morning we had a Spring Egg Hunt at The Shop, and some of the eggs had candy, and others had tickets that could be redeemed for prizes up at the front desk. Given when I come into the office, it was pretty hard not to find a bunch of eggs. They were all just laying out in the open.

After I'd found a few, I decided to lay it all out on my desk to see what I'd managed to haul in. Not too bad for just walking around the office. 🙂

Climate Egg Hunt Loot

Updated Potentials to Xcode 10.2, and up to GitHub

Monday, April 15th, 2019

GitHub Source Hosting

This morning I was looking back at an older project I had on macOS - Potentials, an engine that solves the 2D Poisson equation for a space where you can place conductors, dielectrics, and charge sheets, all of different shapes and sizes, and then use the vecLib CLAPACK call to solve the system of equations very quickly. Finally, it outputs the V(x,y) and E(x,y) to a file for plotting.

I remember writing it on a NeXTSTEP 3.3 Turbo Color Slab, because there was a plotting package that could read the data file, and until I could get around to putting that code into the app, I'd be able to check the results on the plotting package - HippoDraw. Sadly, that app moved to what it is today, on Windows, and I was just not motivated enough to do the plotting on NeXTSTEP.

This morning, I decided to get it out, and get it going on macOS 10.14.4 and Xcode 10.2. I had expected some challenges, and I was not disappointed, but I was also not denied.

The first thing was to allow Xcode 10.2 to tell me of the issues. Some were easy localization fixes, others weren't as easy to see. For example, vecLib has been merged into the Accelerate Framework. So in the code, where I'd had:

  #import <vecLib/clapack.h>

I had to replace it with:

  #import <Accelerate/Accelerate.h>

And then I dropped the vecLib Framework from the list of Frameworks to link to - face it - it was gone. 🙂 Then I needed to add in the Accelerate Framework to resolve the CLAPACK functions. This was something that I had forgotten to do, but it's really not too bad.

Changes to Potentials for Xcode 10

At this point, it built and ran just fine.

I then removed the old origin from the git repo, created a new repo on GitHub, and then pushed it all up there. It's so much more convenient to have it up there, as opposed the old git server that I had running on my own network. Just not even close.

Finish it off with a decent README, and we are now ready to work on writing that visualization of the output that I've wanted. Because it seems that there is no really good open source ObjC graphing packages for flattened 3D plots into 2D, and that's what I need - something that can plot these electric fields in 2D. Something to work on going forward.

Accessing Gists from the Desktop

Wednesday, April 10th, 2019

GitHub Source Hosting

This morning I was thinking about the snippet manager I saw on Twitter... and then I realized that Gists on GitHub are exactly that - and why not just check out the status of the Sublime Text 3 plugin that deals with Gists... and the Vim plugin to do something similar.

I had to update the access token for the Sublime Text 3 plugin, and then it was working fine. But one thing I noticed was that the Gists showed up in the editor as modified files. While that's understandable if you realize the model for this is to read the Gist, and then paste it into the editor window, it's not really the workflow I expected to see.

Additionally, the syntax highlighting wasn't being triggered, so the Gists all had the syntax type of 'Text' - which was really annoying... given that the extension was exactly what you'd need to trigger the syntax type of the file. So that wasn't as nice as I expected. But it still worked.

Then I went to Vim and updated the Gist plugin, and that was interesting, but not as horrible as it could be. Still... it's a bunch of command-line steps, but it's OK. Again, there was another auth token from GitHub, which is nice, but that's about it.

The difference is that when you load a Gist into a Vim buffer, it is not seen as modified, and the syntax highlighting is correct. So those are nice to see in Vim, and while it's not amazing, it is nice to see it done right.

In the end, I'm glad to have updated these things - even if I really wish there was a nice macOS client like Dash that worked with Gists.