Micronaut/GORM Unit Tests

I’ve recently revisited Micronaut as I need to re-write some old systems at work. Both of the systems are written in Grails, one provides an API, the other a very lightweight website. So Micronaut seems like the idea candidate. As a Grails developer I want to continue to use Groovy and GORM and both of these are supported.

I made a start on a few basic domain (Entity) classes with a few simple constraints. At this point I wanted to add some tests – yep, test driven development! However I ran in to problems getting the tests to run.

I created a test file following the same pattern as I would do in my Grails projects, but with what felt like common sense adaptations for Hibernate.

package uk.co.channele.mngorm

import io.micronaut.test.annotation.MicronautTest
import spock.lang.Specification

@MicronautTest
class AreaSpec extends Specification {

    void "test constraints"() {
        when: "an empty Area"
        def area = new Area()

        then: "not valid"
        !area.validate()

        when: "set the name"
        area.name = "name"

        then: "valid"
        area.validate()
    }
}

But when I tried to run the test with ./gradlew test I just got an exception:

org.springframework.dao.DataAccessResourceFailureException: Could not obtain current Hibernate Session; 
nested exception is org.hibernate.HibernateException: No Session found for current thread

This didn’t make sense, unit tests in Grails don’t expect the system to be running, mock objects are used instead. After a few late nights of searching/reading/cursing and trying many different variations I found this website https://guides.grails.org/grails-gorm-data-services/guide/index.html (notice no mention of Micronaut!) which gave me this solution:

package uk.co.channele.mngorm

import grails.gorm.transactions.Transactional
import io.micronaut.test.annotation.MicronautTest
import org.grails.orm.hibernate.HibernateDatastore
import org.springframework.transaction.PlatformTransactionManager
import spock.lang.AutoCleanup
import spock.lang.Shared
import spock.lang.Specification

@MicronautTest
@Transactional
class AreaSpec extends Specification {

    @Shared
    @AutoCleanup
    HibernateDatastore hibernateDatastore

    @Shared
    PlatformTransactionManager transactionManager

    void setupSpec() {
        hibernateDatastore = new HibernateDatastore(Area)
        transactionManager = hibernateDatastore.getTransactionManager()
    }

    void "test constraints"() {
        when: "an empty Area"
        def area = new Area()

        then: "not valid"
        !area.validate()

        when: "set the name"
        area.name = "name"

        then: "valid"
        area.validate()
    }
}

Which runs nicely and passes. Now I need to find a way to improve the Micronaut documentation so that potential users don’t suffer the same frustration as me!

Remove Gnome App Menu

I’ve been a Fedora/Gnome user for many years. I like to keep my desktop empty and the clutter to a minimum. So I don’t, for instance, have the window list at the bottom of the display.

In Fedora 31, the latest release as I write this, I noticed that the Application Menu had made a reappearance in the top menu. No worry I thought, I must have accidentally enabled it with the Tweaks Tool. But not so. From a quick search around it looks as though some arrogant jerk has decided that making it easy to remove is a no, no, no before spitting his dummy out.

As I couldn’t just find any up to date instructions to install a shell extension that removes said menu I provide some here.

In the Software application search for “remove app menu”. I installed the one that seems to be by rastersoft.com. (Direct link is https://extensions.gnome.org/extension/591/remove-app-menu/ ) Select the version/extension (only 3.6 and 2 available currently) and a zip file will be downloaded.

Now go to a command line, navigate to the folder containing the zip file (most likely Downloads) and type:

gnome-extensions install RemoveAppMenu@rastersoft.com.v2.shell-extension.zip

If you’re not running Wayland you can restart the shell with Alt F2 and the command r. I just restarted the machine. When you’re back up and running go in to the Tweaks Tool, Extensions tab and enable the extension. Job done.

wlan blocked

Just this week I replaced the hard drive in my laptop with a solid-state drive. As part of the process I did a clean install of Fedora 28 Workstation to the drive.

The install went very smoothly but when got into using the machine (which is now so fast!) I noticed that wi-fi was disabled. I usually use my machine on a wired connection, so it was no biggie but it’s one of those nagging things that I had to fix. I had used wi-fi in the past few weeks, so it was a new problem.

With this kind of thing you work through the list of recent changes and usually it’s one of those. So I plugged in the old drive, booted to that and found that wi-fi was still unavailable. I booted to an older kernel; still nothing.

Scouring the internet for a solution I found some useful commands. This first, iwconfig, I was familiar with. It was giving:

virbr0    no wireless extensions.
virbr0-nic no wireless extensions.
lo no wireless extensions.
wlp9s0 IEEE 802.11 ESSID:off/any
Mode:Managed Access Point: Not-Associated Tx-Power=off
Retry short limit:7 RTS thr:off Fragment thr:off
Encryption key:off
Power Management:off
enp5s0 no wireless extensions.

So the OS knew about the device. Then lspci -v gives lots of output, but of interest here is:

09:00.0 Network controller: Qualcomm Atheros AR9285 Wireless Network Adapter (PCI-Express) (rev 01)
Subsystem: Dell Wireless 1702 802.11bgn Half-size Mini PCIe Card [AR9002WB-1NGCD]
Flags: bus master, fast devsel, latency 0, IRQ 19
Memory at f7e00000 (64-bit, non-prefetchable) [size=64K]
Capabilities: [40] Power Management version 3
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit-
Capabilities: [60] Express Legacy Endpoint, MSI 00
Capabilities: [100] Advanced Error Reporting
Capabilities: [140] Virtual Channel
Capabilities: [160] Device Serial Number [ Redacted ]
Capabilities: [170] Power Budgeting
Kernel driver in use: ath9k
Kernel modules: ath9k

But the command of interest was rfkill which gave:

ID TYPE      DEVICE    SOFT      HARD
0 wlan phy0 blocked blocked
1 bluetooth hci0 blocked unblocked

The device was there, but disabled in hardware. I tried the Fn-F2 key combo and that was switching airplane mode on/off, but it never enabled wi-fi.

Further Googling found a similar problem affecting Asus devices. So following that advice I reset the BIOS (set default values on this machine) and rebooted. This fixed the problem.

sendmail

I have recently been setting up a website for a friend. As part of this process I needed to sort out my mail server so that he could have a pretty email address.

For a long time I’ve been able to receive/access email to accounts on that server, but I’ve never configured it to allow sending via those accounts.

Setting this up took a few evenings of internet research. I found many old posts, most of them relating to old versions of sendmail. These seemed to need additional configuration, often involving SASL and/or cyrus.

My server is running CentOS 6, so sendmail is at version 8.12. It was in such a state that I started by uninstalling email services (sendmail and postfix) and reinstalling just sendmail (also sendmail-cf). It seems that SASL2 is already installed. Cyrus is unused.

The interesting lines from sendmail.mc are as follows:

define(`confAUTH_OPTIONS', `A p')dnl
TRUST_AUTH_MECH(`LOGIN PLAIN')dnl
define(`confAUTH_MECHANISMS', `LOGIN PLAIN')dnl
define(`confCACERT_PATH', `/etc/pki/tls/certs')dnl
define(`confCACERT', `/etc/pki/tls/certs/ca-bundle.crt')dnl
define(`confSERVER_CERT', `/etc/pki/tls/certs/server-cert.pem')dnl
define(`confSERVER_KEY', `/etc/pki/tls/certs/server-key.pem')dnl
DAEMON_OPTIONS(`Port=smtp, Name=MTA')dnl
DAEMON_OPTIONS(`Port=submission, Name=MSA, M=Ea')dnl
MASQUERADE_DOMAIN(channel-e.co.uk)dnl
MASQUERADE_DOMAIN(domain-two.co.uk)dnl
MASQUERADE_DOMAIN(domain-three.co.uk)dnl
MAILER(smtp)dnl
MAILER(procmail)dnl

Of note are the authentication mechanisms. The default install lists many and it wasn’t until I reduced the list to the two shown that I was able to log in to send email. I masquerade all of the domains that users need to send from.

Don’t forget to enable ports through the firewall too.