java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass

Upgrading from JDK8 to 17+ caused jaxb to run into this errors at run time. Solution remove older Jaxb jars and replace with newer jars that still provide “xml.bind”. When replacing try with 2.3.X jar versions as they still maintain the old sun class path, 3.XX jars have switched to the jarkarta class path which will mean updating some of your project imports and dependencies.

Remove any of the below libs

implementation group:'javax.xml.bind', name: 'jaxb-api', version: '2.3.0'
implementation group:'com.sun.xml.bind',name:'jaxb-impl', version: '2.3.0'
implementation group:'com.sun.xml.bind',name:'jaxb-core', version: '2.3.0'
    

replace with

implementation group: 'jakarta.xml.bind', name: 'jakarta.xml.bind-api', version: '2.3.3'
implementation group: 'org.glassfish.jaxb', name: 'jaxb-runtime', version: '2.3.3'

Chomebook Secure Shell – Remove ssh key from known_hosts

One problem with the Secure Shell plugin is when you need to remove an ssh key from the known_hosts file there is no direct access to the file from the file system. This issue comes up normally when you run into the error message below.

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:C//eoM00fEk4Z8YH6bAp7NdGyhqm24Xsmj/wDl81TEc.
Please contact your system administrator.
Add correct host key in /.ssh/known_hosts to get rid of this message.
Offending ED25519 key in /.ssh/known_hosts:9
Host key for xx.xx.xx.xx has changed and you have requested strict checking.
Host key verification failed.

Which will come up when you re-image an existing host or replace an existing host with another host using the same IP address/host name. The previous way of doing this used to be do (CTRL + SHIFT + J) to bring up the terminal and then run the command “term_.command.removeKnownHostByIndex(INDEX); ” but this doesn’t always work for me as “command” isn’t always available. The most consistent way I have found to resolve this is to bring up Secure Shell and choose Options -> SSH Files you will see your known_hosts file with the ability to modify and save it. Remember to save after your changes and you should be good to go.

No appropriate protocol

I saw this error message once I updated to JDK 11 when trying to send emails initially I didn’t have time to figure out a long term solution so I took a shortcut and removed Tls 1.0 from blocked algorithms in the java.security file. (I know that was a bad move but I was on a time crunch so I wasn’t thinking clearly 🙂 )
Things were ok for a while until an update of JDK replaced my update to java.security file, at this point I figured I would have to keep repeating this dance every few months or get a long term solution.

I use apache commons library to send email and by default it uses < TLS v1.2 and JDK 11+ supports > TLS v1.2. The permanent fix just turned out to be specifying TLS version to be used and my app was able to get back to sending emails without any issues and this time it was future proofed from future update breakage due to JDK updates. Below are the parmeter updates needed.

#Method 1 adding a system property
System.setProperty("mail.smtp.ssl.protocols", "TLSv1.2");
System.setProperty("mail.pop3s.ssl.protocols", "TLSv1.2");
#Method 2 setting value in a property file
spring.mail.properties.mail.smtp.ssl.protocols=TLSv1.2
spring.mail.properties.mail.pop3s.ssl.protocols=TLSv1.2

I went with Method #2 as it allows easier management of properties but every bodies use case is different so you can go with whatever works for your situation.

Update Remi PHP to next version

Since Centos ships with an old PHP version, there are many tutorials on how to install Remi PHP which enables you to use more modern versions of PHP on your site. But when it came time to update from PHP72 to php73/4 I couldn’t find a lot of docs on this so I decided to put this one up to remind me next time am doing this.

First, we will need to enable the PHP version we want to install such as below.

# yum-config-manager --enable remi-php73
# yum-config-manager --enable remi-php74

In my case, I was moving from php72 to 73 before 74 so I enabled 73 and disabled 72.

# yum-config-manager --enable remi-php73
# yum-config-manager --disable remi-php72

After enabling the version you want to move to and disabling your current version, run yum update and restart your webserver.

# yum update
# apachectl restart

To validate the update was successful check the current version of PHP as reported in your terminal, and those are the steps needed to move from one Remi PHP version to another.

# php -v
PHP 7.3.29 (cli) (built: Jun 29 2021 09:30:31) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.29, Copyright (c) 1998-2018 Zend Technologies

Running KVM and docker on the same host with a bridge

I have been running kvm with a bridge on my fedora machine for a while, when trying to run docker on the same host access to the kvm hosts would die as soon as docker came up. I read up online and most places mention that the two technologies should be able to co-exist with each other without any problems, after some further searching I was able to find an article that mentioned that if you have already setup a bridge for KVM you can tell docker to use this bridge. I was able to test this on my setup and it worked allowing docker to run without interfering with the existing bridge. Looking at the interfaces I can still see docker created an interface docker0 but it doesn’t seem to be active.

The docker configuration involved adding this file /etc/docker/daemon.jsonwith the following entry.
{ "bridge": "br0" }
Make sure the bridge number matches your existing bridge number in use by kvm.

WordPress database migration from hell

I finally managed to migrate my wordpress DB to the new server after several weeks of making multiple db dumps and restorations which would fail to load all the content from the old DB. I tried different tools that would export the DB as sql files and used same tools to import even straight command line dumps, but somehow my posts would not display correctly the titles and dates would display but not the post body content.

While trying to trouble shoot the cause I opened the sql file and started running each tables insert query one at a time as you can expect this sucked really bad, but I was ready to do it this way as nothing else was working. When I tried to paste the insert statements for the posts table something weird happened only one character would paste into the sql console which was weird as I expected the several hundred lines I had copied to show up. To look at this some more I posted the text in an editor that could format sql and half way down the file the SQL highlighting changed and displayed half the post as text. This normally happens when there is a character that isn’t escaped properly, it also explained why the backup imports would fail. The weird part with the backup failure is none of the tools would throw an error as you would expect if there was an error with the insert queries. While the curious part of me wanted to investigate this further the rest of me was tired with several weeks of trying to migrate the wordpress data and tried to find another way of moving the data without having to export to SQL files.

The solution I went with was DBeaver which has a data export method of type database which will let you copy a table from one DB to another without having to rely on SQL dumps. This worked like a charm even though it still took a good 10 minutes to copy over everything and keep validating as I went. Like most sites I have an DB backup scripts but since it looks like the backups created in this method may not be of use if I needed them in the future am thinking of just having another offline DB and keep that synced with my main db and use the offline DB for any restorations I might need.

Pay a Finance service or Personally manage your retirement funds?

Of Mountains & Valleys

Like most people I used to put my 401K in safe funds when choosing safe versus risky fund options. My yearly returns also reflected my choices, most of the time I would average 5% or less (mostly less).

A big problem with this method of saving for my retirement was the fact that most of the money in my 401k was coming from the deductions on my check. This would actually be ok if I started working and funding my 401k at 21, but life happens and  I started later in my twenties.

To increase my returns I started following the daily performance of all the funds available in my 401k and I would manually rebalance my account every few months. I also started having larger balances in more aggressive funds and would rebalance every few weeks. This helped raise my yearly returns a few percentage points in some years but not always.

I decided to write some code to automatically rebalance my account for me since I was loosing money in a lot of situations when things would come up or I would forget to log in and rebalance my account. In 2 and a half years that my code has been running it was able to double the balance that was there when it started running, averaging about 20% returns at this rate I will have enough to retire in about 10 yrs if I stop my contributions and less than 10 if I keep adding my contributions.

If my code had not worked my other option would have been to pay for one of the services offered to manage our company’s 401k plans for a certain fee. Right now am happy my money is working just as hard as I do, but I also understand not everyone is in the same position am in since my day job involves writing code. 

Personally, I would suggest if you are trying to improve your 401k returns try and invest more time on a regular basis (days,weeks not months) and learn how the different funds you have available are performing and keep rebalancing your account frequently, some plans will also let you set how you want your account rebalanced every month/pay period automatically for free. If you have some more time and skill you can learn how trading systems work and build something that is able to evaluate your funds and rebalance your account accordingly. The last option which I haven’t tried would be to pay a service to automatically rebalance your account, I feel even if you are going to go with this option to first do option one so that you can use that as a baseline to gauge the paid services performance. 

Some people argue that your 401k should be treated like a marathon where you setup your preferences and leave it and only rebalance a few times a year. This is what I did with my account for almost ten years and in 2.5 years of aggressively rebalancing as the market changed I was able to add to my account as much as I had been able to contribute in 10yrs, without having to depend on salary increases to increase my contributions. So for me am sticking with the sprint, if it means I will need fewer years to build my retirement nest to where I would like it to be.

Note: All thoughts written here are my own, and should not be taken as financial advice, am not a financial expert just someone who likes to solve real world problems using code.

Angular2: Property binding ngFor not used by any directive on an embedded template

Just brushing up on some Angular2 and run into this error it didn’t make sense since I was using a tutorial from the official angular site. It turns out the language is changing faster that the documentation can keep up with :). The cause for the error was using # with ngFor instead of let so instead of *ngFor="#Item of Items" do *ngFor="let Item of Items" My previous angular2 apps are locked to earlier versions of angular thats why I hadn’t run into this issue, but this time around I was starting a new project with the latest angular2 version.

Converting selinium code to headless tests with PhantomJS

The word test here is used ambiguously as I use selenium for more than just UI tests, it makes a great tool for browser automation which I use it for this purpose a lot. While writing your browser automation most of the time it’s easier to do it in browser mode by using the firefox or chrome driver so that you can visually inspect the HTML. Once you are done writing the code and finished testing sometimes you would prefer to switch it to headless mode so that it can be run without having a UI, at which point you are likely to tryout PhantomJS driver and your fully tested code starts throwing all sorts of errors like “Element not found” or “Stale Element Exception”. If all this errors go away if you switch back to chrome or firefox driver then the likeliest cause of your troubles is you might need to add delays in most places where you have the browser loading new data compared to the other browser drivers.
To me this seemed a bit counter intuitive at first as I though headless mode should run faster therefore requiring even less time to load UI changes, but I guess it might actually take a little longer since all the browser rendering is being done is software only. Just thought to put this out there as I have run into the issue a few times.

Automate letsencrypt certificate renewal

I recently switched from self signed certs to free SSL certs from letsencrypt and for the first time I could load my https url without getting the annoying prompt from chrome due to self signed certificates. The only problem is the certs expire pretty fast in about 90 days as of this writing, while this is nothing to complain about since the certs are free handling the renewal each time manually would be a pain and also leave me in a bind in case I forgot to do it.
I decided to automate the renewal process to save myself the hassle of having to do it manually and found two resources here and here on how to do it, I went with a combination of the two methods as my requirements were different.
I wanted the renewal to be run from a script to support email notification on success or failures which is similar to the first source and use the webroot plugin to perform renewal as it has lesser steps to perform renewal reducing any failure points during the process like the second source. The script needed to be able to run everyday and check cert expiration I didn’t want to hard code the cron job to run based on how long the certs are valid that way if letsencrypt changes the life of the certs no change is required on my side.
Let’s get started I won’t cover the install as that’s covered by letsencrypt site, I would advise you to read the different install methods and choose the one that best fits your needs.
After performing the install
Create your config file which will contain the arguments submitted to letsencrypt api I named mine “muthii.com.ini”

rsa-key-size = 4096
server = https://acme-v01.api.letsencrypt.org/directory
text = True
authenticator = webroot
agree-tos = True
renew-by-default = True
email = root@domain.com
webroot-path = /your/webserver/path

Run the command used to create/renew your certs, which creates the certs for you and shows you the path to find them.
[cc lang=”bash”]/root/.local/share/letsencrypt/bin/letsencrypt -c /path/muthii.com.ini -d muthii.com -d www.muthii.com auth[/cc]

Only run the above command if you haven’t created your certs or are ready to renew your current certs, otherwise just grab the script file and add it to your cron. Make sure to change the emails and file paths based on your setup. I have commented out the echo statements and only enable then for testing

For someone doing this for the first time locate your ssl.conf file used by your server and set the paths to the new certs

SSLCertificateFile /etc/letsencrypt/live/domain.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain.com/fullchain.pem

Once you are done setting up head over to SSLLabs and test your certificate is recognized as expected, then setup a cron job to run the script daily .

0 2 * * * sh /path/SSLRenew.sh