Enable support for java.time.* with Jackson-jr

Jackson-jr is super neat, but does not (yet) support serialization of java.time.* (e.g. java.time.LocalDate, LocalDateTime) out-of-the-box. However, it is actually super easy to extend it. My example is in Groovy, but it will also work in Java if you add some boilerplate code such as “;”.

First create some utility class to encapsulate the Jackson-jr extension:

package test.json

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.jr.ob.JSON
import com.fasterxml.jackson.jr.ob.JacksonJrExtension
import com.fasterxml.jackson.jr.ob.api.ExtensionContext
import com.fasterxml.jackson.jr.ob.api.ReaderWriterProvider
import com.fasterxml.jackson.jr.ob.api.ValueReader
import com.fasterxml.jackson.jr.ob.api.ValueWriter
import com.fasterxml.jackson.jr.ob.impl.JSONReader
import com.fasterxml.jackson.jr.ob.impl.JSONWriter

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

class JsonUtil {

    static JSON buildJSON() {
        JacksonJrExtension jacksonJrExtension = new JacksonJrExtension() {

            @Override
            protected void register(ExtensionContext ctxt) {
                ctxt.insertProvider(new LocalDateTimeReaderWriterProvider())
            }

        }

        JSON.builder().register(jacksonJrExtension).build()
    }

    static class LocalDateTimeReaderWriterProvider extends ReaderWriterProvider {

        @Override
        ValueReader findValueReader(JSONReader readContext, Class<?> type) {
            type == LocalDateTime ? new LocalDateTimeValueReader() : null
        }

        @Override
        ValueWriter findValueWriter(JSONWriter writeContext, Class<?> type) {
            type == LocalDateTime ? new LocalDateTimeValueWriter() : null
        }

    }

    static class LocalDateTimeValueReader extends ValueReader {

        LocalDateTimeValueReader() {
            super(LocalDateTime)
        }

        @Override
        Object read(JSONReader reader, JsonParser p) throws IOException {
            LocalDateTime.parse(p.text, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
        }

    }

    static class LocalDateTimeValueWriter implements ValueWriter {

        @Override
        void writeValue(JSONWriter context, JsonGenerator g, Object value) throws IOException {
            String localDateTimeString = ((LocalDateTime) value).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            context.writeValue(localDateTimeString)
        }

        @Override
        Class<?> valueType() {
            LocalDateTime
        }

    }

}

Define some class that contains the LocalDateTime and should be converted to json and vice versa:

package test.json

import java.time.LocalDateTime

class MyClass {

    LocalDateTime time
    String someOtherValue // just to check that we did not break anything else

}

Finally use it:

package test.json

import com.fasterxml.jackson.jr.ob.JSON

import java.time.LocalDateTime

class Application {

    static final JSON JACKSON = JsonUtil.buildJSON() // static final so we do not create it again and again, it is thread safe.

    static void main(String[] args) {
        final LocalDateTime now = LocalDateTime.now()
        MyClass myObject = new MyClass(time: now, someOtherValue: 'whatever')
        String myObjectJsonString = JACKSON.asString(myObject)
        MyClass myObjectFromJson = JACKSON.beanFrom(MyClass, myObjectJsonString)
        assert myObjectFromJson.time == now
        assert myObjectFromJson.someOtherValue == 'whatever'
    }

}

It hope that it works for you as well

CodeNarc 1.5 with Grails 4

When I bumped CodeNarc from 1.4 to 1.5 at my Grails 4.x project, I kept getting the “groovy/text/TemplateEngine” error which is reported here: https://github.com/CodeNarc/CodeNarc/issues/449

The suggested solution was not too clear, so here is exactly what you gotta do – add the following to build.gradle:

codenarc "org.codenarc:CodeNarc:${codenarc.toolVersion}"
codenarc 'org.codehaus.groovy:groovy-templates'

Grails 4 IntegrationsTest cannot compile when using OpenClover

I just recently upgraded a Grails 2 plugin to Grails 4 and that gave me a weird problem that probably also applies to Grails 4 applications.

Every time I ran ./gradlew check with gradle-clover-plugin (OpenClover) enabled, then I would get compile errors (“unable to resolve class” for /grails-app/**/*.groovy) during compileIntegrationTestGroovy.

After endless trial-and-error, I realised that I had to delete the /src/main/java even though it was empty!!!

I had already copied all the content from /src/main/java to /src/main/groovy during the upgrade process, but forgot to delete the /src/main/java folder.

Specify embedded Redis URI / port in Micronaut tests

Just a quick tip: If you need to specify the embedded Redis URI for Micronaut tests (e.g. when testing connectivity to Redis), then you just have to write the following in application.yml:

redis.embedded:
    uri: redis://localhost:1337

Here is how to set the port:

redis.embedded:
    port: 1337

You can just open EmbeddedRedisServer from micronaut-redis-lettuce and check out the code yourself.

Resolve DNS using VPN (openconnect) rather than default-ISP DNS on Ubuntu 18.04

Ubuntu 18.04 has a nice GNOME GUI for VPN, but it still takes a little effort to get it fully working. Here is what I did:

I connect to a VPN that is based on Cisco AnyConnect, which means that I must use OpenConnect and that is not installed by default. Fortunately, Ubuntu has some useful documentation (https://help.ubuntu.com/community/NetworkManager) that points out which packages to install. I used the following commands to install OpenConnect for Network Manager:

sudo apt-get install network-manager-openconnect
sudo apt-get install network-manager-openconnect-gnome

Once that is done, then I can setup my VPN connection.

  1. Open “Settings” -> “Network”
  2. In the VPN-section, click the “+”
  3. Select “Cisco AnyConnect Compatible VPN (openconnect)”
  4. Give the VPN a sensible name, write the URL to the VPN in the “Gateway” field and leave the rest as default. This is sufficient in my case.
  5. Now you can turn the VPN “on” by clicking “off” in “Settings” -> “Network”.

However, when the VPN is turned on, it fails to use the DNS from the VPN which means that I cannot access the internal websites behind the VPN unless I know the IP-adresses. I have tried many different solutions that didn’t work until I found something useful (https://bugs.launchpad.net/ubuntu/+source/network-manager/+bug/1688018). Do the following:

  1. sudo gedit /etc/NetworkManager/system-connections/<NAME_OF_YOUR_VPN_CONNECTION>
  2. Add the following to the “[ipv4]” section: dns-priority=-1
  3. Restart the network manager: sudo systemctl restart NetworkManager.service

I hope that this guide saved you from having to read page after page of solutions that does not work – I wasted enough time on that 🙂

How to install HP LaserJet M1132 MFP on Windows 10

I have tried countless guides on how to install the driver for “HP LaserJet M1132 MFP” on Windows 10. It worked perfectly on Windows 8 and it also works on my laptop with Windows 10 but not my desktop computer with Windows 10. The driver installation just stops after extracting archive is complete, but the actual installation never continues. Windows 10 also tries to install the driver using HP Smart, but that does not work either.

However, I found a solution that worked for me:

  1. Unplug the USB cable to the printer (otherwise windows 10 will keep trying to install the printer driver using HP Smart)
  2. Remove any existing HP-driver for the printer and HP Smart (if Windows 10 installed that already)
  3. Download the driver: https://support.hp.com/us-en/drivers/selfservice/hp-laserjet-pro-m1132-multifunction-printer-series/3965842/model/3965843
  4. Run the driver executable (LJM1130_M1210_MFP_Full_Solution.exe)
  5. Wait for the extraction dialog to complete and then nothing happens. (It should probably have started the installation, but that seems to fail)
  6. Then go to “%userprofile%\AppData\Local\Temp\” (i.e. “C:\Users\<YOUR_USERNAME>\AppData\Local\Temp\”) and locate the latest modified folder which contains HpSetup.exe and run that file. Now the driver will be installed and it works!

Do let me know if it works for you as well or if you have any issues with it 🙂

Adding @GrailsCompileStatic to all production grails code (not test grails code)

When coding Groovy, @CompileStatic can help to spot errors and improve performance of production code. Unfortunately, @CompileStatic is optional and hence easy to forget, but thankfully Groovy has documented a way to make @CompileStatic for all production code: http://docs.groovy-lang.org/latest/html/documentation/#_static_compilation_by_default
(Test code is not affected, because it is nice with flexibility when testing.)

However, with Grails you really want to use @GrailsCompileStatic instead of @CompileStatic, because it saves you from adding @CompileDynamic all the places that dynamic Grails functionality is used while still ensuring that your own code is @CompileStatic. Unfortunately, the above solution cannot be used for applying @GrailsCompileStatic to all production code. This is due to @GrailsCompileStatic is not available at the Compile Configuration and trying to @Grab it from grails-core only yields new dependency problems.

Eventually, I realised that @GrailsCompileStatic is just @CompileStatic with some extensions – those can be included in the Compile Configuration manually and then it works as expected.

This is my src/groovyCompile/groovyConfig.groovy:

import groovy.transform.CompileStatic
import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer


// Extensions are copied from @GrailsCompileStatic due to that @GrailsCompileStatic is not available in the Compile Configuration
List extensions = ['org.grails.compiler.ValidateableTypeCheckingExtension',
'org.grails.compiler.HttpServletRequestTypeCheckingExtension',
'org.grails.compiler.WhereQueryTypeCheckingExtension',
'org.grails.compiler.DynamicFinderTypeCheckingExtension',
'org.grails.compiler.DomainMappingTypeCheckingExtension',
'org.grails.compiler.RelationshipManagementMethodTypeCheckingExtension']
ASTTransformationCustomizer grailsCompileStatic = new ASTTransformationCustomizer([extensions: extensions], CompileStatic)
configuration.addCompilationCustomizers(grailsCompileStatic)

At build.gradle, I also added the following:

compileGroovy.groovyOptions.configurationScript = file('src/groovyCompile/groovycConfig.groovy')

Let me know if this works for you – feedback is the best motivator!

How to start local ActiveMQ (build from source) on Ubuntu when the ActiveMQ package has previously been installed

This is the frustration of the day. I downloaded the ActiveMQ source and compiled it with no issues – however I could not start ActiveMQ (using ./activemq start) and the console output did not really explain what was wrong:
./activemq: 344: ./activemq: "/usr/bin/java" -Djava.util.logging.config.file=logging.properties -Djava.security.auth.login.config=/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//conf/login.config -Dactivemq.classpath="/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//conf:/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//lib/" -Dactivemq.home="/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT/" -Dactivemq.base="/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT/" -Dactivemq.conf="/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//conf" -Dactivemq.data="/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//data" -jar "/home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//bin/activemq.jar" : not found

However, when running “./activemq” without any task parameter, then it gave me a hint:
Configuration of this script:
The configuration of this script is read from the following files:
/etc/default/activemq /home/MY_USER/.activemqrc /home/MY_USER/git/activemq/assembly/target/apache-activemq-5.12.1-SNAPSHOT//bin/env
This script searches for the files in the listed order and reads the first available file.

To my surprise, there was actually a file at “/etc/default/activemq” – this was a leftover from a previous ActiveMQ installation (Ubuntu package) – I had forgotten to use the –purge option when I removed the ActiveMQ package:
sudo apt-get remove activeMQ --purge

I ran the remove command again with the purge option and now I can start ActiveMQ with no problems 🙂

Getting wireless to stop disconnecting on HP ProBook 430 G2 on Ubuntu 14.04 (Linux)

The default wireless driver settings for the HP ProBook 430 G2 on Ubuntu Linux 14.04 makes the internet connection drop frequently and the wireless connection first works again when the machine has been rebooted (or the wireless netcard driver has been removed and added again). The solution is to change the driver settings (disable e.g. power save mode) – here is a guide for your convenience and such that I don’t forget how to do it 🙂

This guide is only made for “HP ProBook 430 G2”. It might work for other computers, but the wireless netcard driver probably has a different name and different settings. Please tell me if you get it to work for other models 🙂

1. Find the wireless netcard model – open a terminal using CTRL+ALT+T and write the following command:
ls /sys/class/net/wlan0/device/driver/module/drivers

Mine says “pci:rtl8723be”, where “rtl8723be” is the driver name. If you have a different driver, then you need to replace “rtl8723be” in the rest of this guide with whatever your terminal outputs after the colon (pci:).

Now we need to check the driver settings – this requires the program sysutils that is not installed by default – try to write the following command in the terminal:
sudo apt-get install sysfsutils

Write the following command in the terminal to get the current driver settings (replace “rtl8723be” if you use a different driver):
systool -v -m rtl8723be

In the “Parameters:” section, there should be a number of settings. Look at the value that is written next to the power save settings “fwlps” and “ips” – if it says “Y” or “1” then that is probably the reason why your internet connection gets disrupted.

You can see what the two settings means by writing the following in the terminal (replace “rtl8723be” if you use a different driver):
modinfo rtl8723be

Disable power save by writing the following in a terminal (replace “rtl8723be” if you use a different driver):
echo 'options rtl8723be ips=0' | sudo tee -a /etc/modprobe.d/rtl8723be.conf
echo 'options rtl8723be fwlps=0' | sudo tee -a /etc/modprobe.d/rtl8723be.conf

Remove and add the wireless netcard driver by writing this in a terminal (replace “rtl8723be” if you use a different driver):
sudo rmmod rtl8723be && sudo modprobe rtl8723be

Verify the new settings by once again writing this in a terminal (replace “rtl8723be” if you use a different driver):
systool -v -m rtl8723be

In the “Parameters:” section, “fwlps” and “ips” should now be “N” and your internet connection should stop crashing. Feel free to post a comment 🙂

Add after body hook hack in wordpress (e.g. for Facebook Like button SDK) without modifying header.php

I wish to add the Facebook Like button to my wordpress – this requires that I add the following code right after <body<:
<div id="fb-root"></div><script>(function(d, s, id) {
...
}(document, 'script', 'facebook-jssdk'));</script>

My solution
Make a functions.php file in your child theme and add the following code (or append it to your main functions.php if you are silly enough to not use child themes). It abuses the body_class hook by finishing the <body< tag and then prints the actual content:
add_action('body_class','hook_after_body');

function hook_after_body()
{?>
<div id="fb-root"></div><script>(function(d, s, id) {
<script>(function(d, s, id) {
...
}(document, 'script', 'facebook-jssdk'));</script
<?}

Solutions that I don’t like

  • I could just override header.php in my (child)theme, but then my modifications will be lost, if I update my wordpress theme. Plus it makes it harder for me to know what code that I have changed.
  • I could also just use a plugin to get extra hooks, but I hate to install extra plugins because they makes me depend code from more on other people and the plugins can also be a security risk.


Fernando pointed out that this generates invalid HTML. While there are some ways of adding content after the body (http://wordpress.stackexchange.com/questions/73370/how-to-inject-content-after-body), I have decided to just use override header.php in my child theme – I had to do that anyway.