Finally did the deep dive on the Star Wars animated series and watched both Clone Wars and Rebels. It was great how each series found its stride by season two and really took the deep dive on the history and future of the universe. Super excited for all the new shows on Disney+

Merrimac Old Home Days Softball

I played in the Merrimac Old Home Days softball tournament for the first time today. We lost our first game (8:30am), but since it was double elimination we joined the loser’s bracket and ended up playing four more games, but ended up getting eliminated in the loser bracket semi-finals. The last game ended over 8 hours after our first pitch. We had a rag tag bunch, but had a great time and pulled off some great wins.

Franklin Pierce University Disc Golf

We recently rented a house on Pearly Pond in Rindge, NH and I walked around the nearby Franklin Pierce University campus. They recently set up a disc golf course and after two trips to the campus I was able to put together this map of the course showing all nine tees and holes. I couldn’t find any information about it online so I thought I would share it here.

Running Down a Bug

One thing I love about writing software is how you can almost always count on finding a solution to a problem. It probably is also why I like crossword puzzles and sudoku, but get annoyed with solitaire. Very rarely in my 20+ years of development have I come across an issue where I threw my hands up and said, “it can’t be fixed”. I would like to say it happens less now because I have written and reviewed so many lines of code that I know all the patterns and can bend the frameworks to my will. The truth is my experience has just taught me there is a logical reason why the issue is happening and it just requires time and effort to figure it out. Being one of the lead developers on the team probably factors in since I can’t just pass it off when I am at my wit’s end.

I recently worked on a bug that really gave me a run for my money and is likely to be used at my next interview when I get the “Tell me about a bug you have fixed and how you figured it out.”

I am currently working on a mobile app and in order to support automated testing by QA we deploy the app to a Digital.ai Continuous Testing digital assurance lab formerly known as SeeTest. The app is built using a combination of the Ionic and Angular frameworks to output to both Android and iOS. The Jenkins pipeline build automatically uploads a supported version of the app binaries to the SeeTest server. The apps can then be installed on over 100 different devices in the browser or in the Appium automated testing tools. Everything was working fine until a few weeks ago, if you tried to install the app onto an iOS device the installation would fail. We had just finished a release and since this was happening in the next release nobody really noticed for a couple weeks. As QA started working on their automated testing for the next release they filed a blocking issue and it was assigned to the development team. Since I had been working on build related stuff it was assumed that it was related to my changes, so I volunteered to take a look at it.

The first task was to reproduce the issue and I quickly confirmed the latest build failed to install on a device in SeeTest. Next up I confirmed the install of the recently released version worked. Now I had to try and isolate to find more specifics around when it broke, since this was a build bug I had to try to reproduce the Jenkins build process locally to generate a similar IPA files. I grabbed an old shell script which I had used when our build machine broke and could now generate the artifact locally in about 10 minutes. The fun was just getting started as I pulled down one revision at a time, stored the generated artifacts for reference and tried installing them on SeeTest devices. After a few hours and a couple false positives I narrowed it down to one specific commit. Well that was easy, not so fast!

The changes in the commit included some new and complicated integrations, but nothing really jumped out as being problematic regarding the packaging of the application, especially since the TestFlight build worked just fine. I started the next round of my troubleshooting by removing things one at a time to see when things broke. After a few rounds of 15 minute builds and testing in SeeTest I wasn’t able to isolate the issue, some of the changes were intertwined with other changes so it was hard to pull out pieces. Nothing was jumping out to me so I reached out to the team that manages SeeTest to see if they could provide more details, but I was not hopeful. It was slow going and I had run into this one zip file in the change containing a bunch of source code from a different project and it wasn’t giving me a good feeling.

After meeting with the rest of team we figured it better for me to try adding things from the commit one at a time instead of removing them. I was overjoyed to have a new strategy and immediately set out with the new plan. It didn’t take long to see that the big zip file was the problem, but it didn’t make any sense to me why it would be causing problems since it was very isolated from the iOS build and packaging process. I continued the same strategy and one folder at a time I updated the old zip file with changes from the new zip file. After six attempts the installation still worked fine and I was getting to some of the bigger more complicated changes. I knew this was going to yield results, but could take a few more days.

Thankfully my luck changed when I heard back from the person managing our SeeTest installation and they were able to confirm the issue and escalated it up to Digital.ai. I still figured it was something to do with our code change, but if I could get some log statements with more details than “Installation fail” it would help me find the problem. The next morning I was invited onto a call with Digital.ai and we reproduced the issue and also got some detailed logs from the server. I had the bug on the run at this point and it only took about 20 minutes for me to track down exactly why the issue was happening.

During the installation process on the SeeTest device, the IPA is uploaded to a server, unpacked and re-signed with a different certificate. The log files showed that one of the files inside our IPA could not be re-signed because it couldn’t be read. The file in question has a ridiculously long name because it is meant to mock an HTTP request with a bunch of querystring parameters. A quick reading of the logs shows the re-signing process is running on Windows and the full file path to the file is 334 characters, which exceeds the default file path allowed in Windows. After removing the file from the zip file the SeeTest install succeeded and if I put it back in it would fail. Rather than wait for the fix to SeeTest, I just removed the file from our packaging process since it wasn’t really necessary.

After spending four days on the issue, I was happy to have found a solution and was also happy to see it wasn’t related to my build changes. I learned a bunch of different things about SeeTest and also realized how problematic it is to just drop in a giant zip file with an unknown number of changes. The other key takeaway is how much I prefer the strategy of adding changes than trying to remove them. Now we wait for the next bug to come my way and torpedo my planned work.

About a year ago I was still recovering from a mystery illness and decided to go for a morning walk around the neighborhood before starting my workday. It turned into a routine and is something I look forward to every morning now, rain or shine. #mileaday

Played softball for the first time in a couple years last night and it was fantastic. I am still rusty but still played well in the field and at the plate.

Today marks the 413th day since I last went into an office for work, it is also the day when I will receive my first COVID vaccination.

Scheduled my Moderna or Pfizer vaccination about an hour before the announcement of the JnJ “pause”. One week to go.

Turkish Coffee

I love coffee and last year I added a few new things to my bag of tricks. Last Christmas my in-laws bought me a coffee roaster and every three days I fire it up and make some fresh beans for my espresso machine. It has been fun learning how to roast, but it has also saved me from going to the local coffee shop every couple weeks to buy a bag of beans.

I also learned about Vietnamese style coffee by finally getting around to learning how to use my Vietnamese coffee brewer. It was really fun to research the various brewing techniques and make an educated guess based on all the different videos and blogs out there on the subject.

This year for Christmas my in-laws continued with the new tradition and are helping me expand my coffee horizons even further with Turkish coffee. The first present I opened was the coffee pot called a cezve as well as a wooden spoon. The next up were the cups or fincan and saucers which are about the size of the small espresso cups. The last present included finely ground turkish coffee and some special spices.

The next day I spent thirty minutes researching on the internet to see how I was supposed to properly brew cofee in the cezve. There were lots of different videos and most of them had similar instructions, but each one had its own special technique for one part of the process. I weighed the various options and came up with my plan. The following steps were for creating two cups of coffee.

  1. Add a teaspoon of the special spice to the cezve
  2. Add a teaspoon of sugar to the cezve
  3. Stir the spices and sugar to combine them
  4. Add about 3 fincan cups of cold water to the cezve
  5. Stir it up a little bit to mix the dried ingrediens with the water
  6. Turn on one of the burners on the stove to low
  7. Put the cezve over the heat and keep a close eye on it
  8. Bubbles will start to form where the surface of the coffee meets the side of the cezve, a little after that happens but before the foam starts filling in you should remove it from the heat
  9. Using the wooden spoon scoop the top layer of foam evenly into each fincan
  10. Put the cezve back on the heat very briefly until it starts bubbling a little bit
  11. Remove it from the heat and carefully fill up the fincan, taking care to pour so you don’t interfere with the foam
  12. Serve with fresh water and a sweet treat

Some videos recommended completely mixing the contents of the cezve before adding the heat instead of just loosely mixing it. Another part that will require fine tuning and practice is the time of the scooping of the foam and the subsequent pouring of the coffee. There is a very fine balance around when you scoop the foam and how long you heat the coffee. Overall the entire process should take about 7-10 minutes. Thankfully there aren’t too many different knobs and levers to mess with so I should be able to find a sweet spot after about a half dozen or so attempts.

JAVA Home and macOS

I decided to take the leap a couple weeks ago and installed macOS Big Sur. I have had a couple small issues like the display not waking up from sleep and my JAVA IDE not rendering some text properly, but it seems pretty solid. There was one issue with my development tools related to the JAVA_HOME settings and I wanted to document for future me.

In macOS you can run the following command in Terminal to list out all the different versions of JAVA installed.

$/usr/libexec/java_home -V
    Matching Java Virtual Machines (3):
    12.0.1 (x86_64) “Oracle Corporation” - “OpenJDK 12.0.1” /Library/Java/JavaVirtualMachines/openjdk-12.0.1.jdk/Contents/Home
    1.8.211.12 (x86_64) “Oracle Corporation” - “Java” /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
    1.8.0_211 (x86_64) “Oracle Corporation” - “Java SE 8” /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home

You can then specify the active JAVA in Terminal by adding the following to your .bash_profile and specifying the version to use.

export JAVA_HOME=$(/usr/libexec/java_home -v 1.8.0_211)

I ran into an issue after the upgrade because the 1.8.21.12 plugin was new in the list and I had only specified version 1.8, so my JAVA_HOME was getting set to the plugin instead of the JDK. After changing it from 1.8 to the more specific 1.8.0_211 I was back in business.

Source: Notes for Geeks: java_home and JAVA_HOME on macOS

SpringBoot Arguments

I recently ran into an issue with our deployment of a SpringBoot application because of some confusion around how to pass arguments when launching it.

The command to run an app looks like this java -jar ${APP_NAME}.jar

You can pass arguments to Spring boot either

  • Using the -D Java property notation by adding it as a VM argument between java and -jar

  • Using -- style notation after the jar name

For example, java -DenvTarget=dev test-api.jar --server.port=8008 would set the envTarget property to dev and the server.port to 8008

Apache2 Subdomain Redirect Fun

Last year I set my son up with his own domain name and learned how to use virtual hosts in Apache 2 to host his site alongside mine. It seems like a long time ago, but for the most part it was a pretty straightforward process and within a couple hours he was up and running. Fast forward to yesterday when I was trying to configure a redirect for a subdomain on my site. I started messing around with my site’s virtual host configuration file and realized an existing redirect softball.keegsands.org now sent the browser to my son’s domain. I blindly hacked away at the configuration file for an hour or so, but since it was almost 70 degrees in November I decided to go outside instead.

This morning I picked up where I left off and started at the beginning and verifying that the DNS stuff was configured correctly. There were a couple differences between our DNS settings. My son’s domain had www set up as an A record, while mine had it set up as a CNAME. It shouldn’t really matter, but for consistency sake I switched mine to have www as an A record. Next I tried to add a new virtual host for my subdomain and that didn’t seem to work and just added an extra level of complexity.

Finally I started reading about virtual hosts and was certain I was in the right place, I just needed to get the configuration correct. During the initial set up I do remember an issue where my son’s site would end up being the default virtual host for all traffic to the Apache server, so I focused on why calls to the softball subdomain weren’t being handled by my site’s virtual host. The problem was with the ServerAlias property for my site was set for only www.keegsands.org, I switched it to *.keegsands.org and it started doing the proper rewrite of the URL.

Hosting my own site has been a little annoying at times, but just having that extra experience messing around at this level definitely makes me happy.

At the beginning of the school year we upgraded my son from my old 2011 MacBook Pro to a new MacBook Air. Today I finally fixed the wobbly display hinge and removed all of the stickers. Now it is as good as new and ready for the museum.

Shortcuts Folder Support in iOS14

One update I was looking forward to in iOS 14 was folder support in Shortcuts. Over the years I have expiremented with Shortcuts and most of them were just simple utilities, but at some point I decided to do a deep dive and write one to make publishing my podcast easier. It took a lot of trial and error, but eventually I had a main shortcut for the process and it would call out to a few different specialized utility shortcuts for different things. The developer in me couldn’t resist trying to breaking it out for easier testing and flexibility, thankfully Shortcuts was built for developers and a Shortcut can be built as a little function that receive arguments and returns a result.

It wasn’t the easiest process because the code block dragging and dropping is a bit tedious and I would have loved being able to just type in text, because it would have saved me a ton of time. The organization of the shortcuts was always daunting too, because everything was just a giant grid of unrelated shortcuts and I was always moving things around so they stayed grouped together.

Well, now in iOS14 there is support for folders and it gave me the chance to go back and revisit my Shortcuts. As an added bonus I hooked up a keyboard and mouse to make things even easier. The first part of any good reorganization is getting rid of the old unused stuff and I had plenty of that. A bunch of shortcuts seemed to just have been added randomly and others were utilities that were no longer necessary thanks to advancements to iOS, like saving a file to iCloud Drive.

After cleaning up a bit I started testing each shortcut to see if they still worked and was frustrated to find a lot of them were broken as Shortcuts has grown over the years. In some cases the parameters I originally entered were just blank and it took me quite a while to wire them back up and occasionally I wasn’t even able to get them working again. I understand how difficult backward compatibility can be, but there wasn’t even a hint of even the simplest things upgrading successfully. Luckily I knew this was a problem, because I had fixed up my podcast release shortcut a few months ago and it was really frustrating.

Next, I put all the shortcuts into new folders one for utilities and another for all the podcast related helper shortcuts. I had already moved things around a little for using the Shortcuts widget and the return of Shortcuts support on Apple Watch. I now have a nice clean interface for Shortcuts on my iPad and iPhone. The last thing I did was clean up a bunch of Share Sheet shortcuts, which are now nicely grouped in its on “smart” folder.

Overall Shortcuts continues to be an integral part of my experience on my Apple devices. I hope it eventually shows up in a future release of macOS.