ƒ/8 and be there

Lock down can be difficult some days. I’m lucky that I can work from home and I’m finding that helps greatly. I recognise that I do have to have some breaks from work. There are a few loops that I walk, but once you’ve done them a few times they become – well – a bit boring.

Having found an interesting video about filters on YouTube I decided to set myself a “lock down challenge” and set off out with my camera.

The rules: only one lens, only one aperture setting and only one picture setting (though I did cheat on the last of these). The lens I chose was my 35mm ƒ/2, the aperture setting was ƒ/8 (obviously) and the picture setting was black and white with a (simulated) orange filter.

It was very enjoyable. I was out for two and a half hours just ambling along the tow path and back long the cycle lane. I’m also quite pleased with the results. (See Wikipedia for more on the expression “ƒ/8 and be there”.)

Laundry

Grails 4 Resources

So you’ve spent a day or two carefully migrating your Grails 2.4.4 application to Grails 4.0.2. Yet you find that the files in src/main/webapp aren’t accessible from your views. Annoying right!

I’m sure this is documented somewhere, but I’m damned if I could find it again. The solution is to add a reference to them in your application.yml file:

grails:
    resources:
        pattern: /**

Update: After further reading I find this (in section 3.3.2, Step 7):

If you have static assets in your web-app directory of your Grails 2.x application such as HTML files, TLDs etc. these need to be moved. For public assets such as static HTML pages and so on these should go in src/main/resources/public.

TLD descriptors and non public assets should go in src/main/resources/WEB-INF.

As noted earlier, src/main/webapp folder can also be used for this purpose but it is not recommended.

http://docs.grails.org/3.2.3/guide/single.html#upgrading2x

I have now updated my project and moved everything from /src/main/webapp into grails-app/assets folders. I’ve also replaced all instances of the <g:javascript> tag with <asset:javascript>. This gives the added bonus that, in Intellij IDEA, one can ctrl-click the file name and it links to the file.

Grails g:javascript tag/AJAX Calls

This works in development but is broken in live, still seeking a solution.

The bulk of the code that I write uses the Grails framework, though I am increasingly working with Micronaut recently. My main project at work uses Grails 2.4.4, and that is the project in which I found this issue. (I don’t consider it a bug, but it required that I investigate/understand and so I’m sharing my solution.)

A pattern that I commonly use when I want to present a modal dialog is to capture a button press and then use jQuery to make an AJAX call to retieve the content for the dialog. The controller then renders the template with a model and returns it as HTML. This works very well.

As functionality has been added the busier pages now have multiple dialog boxes available, resulting in a set of (empty) divs at the bottom of the page and a set of $("#modalName").dialog(...) calls when the page loads. This doesn’t cause any problems. The content of these modal dialogs often requires that they have different dimensions anyway.

Each page only really needs one modal dialog, it’s the content that is different depending on the user action. On one page, when I needed to add yet another dialog, I decided to refactor to a single reusable instance.

As the dialog was to have different content I could no longer set the dialog title in the page. Instead I changed the controller to return a JSON response that contained not only the HTML but also a title string. The code in the page then sets the modal dimensions, title and content. On initial inspection this seemed to work.

What I actually found was that the javascript file referenced by the modal content was not loading. (A side note here. I keep my javascript separate from my GSPs where possible. It allows code reuse (good), but you can’t refer to variables presented by the model (bad). I link to them using the built in <g:javascript src="..."/> tag.)

In this “single model” way of working I am using GroovyPageRenderer in the controller to render the modal template to HTML for inclusion in the JSON response. The page renders just fine, but the link to the javascript file, created by the g:javascript tag is missing the context path. Consquently, of course, it never loads. The solution that I found was to use a normal script tag and including the resource in the src attribute:

<script src="${resource(dir: "/")}/js/customers/_modalEditAddress.js"></script>

As I type this I wonder what other solutions are available. I had a quick look at the attributes that are available in the g:javascript tag and there might be options there. Also I wonder if anything can be passed to GroovyPageRenderer.

This works in development but is broken in live, still seeking a solution.

Micronaut/GORM Services

After another long evening of trying to get Micronaut to work as expected out of the box I’m beginning to think that the developers really don’t want anyone to use GORM!

Yesterday I was trying to convert one of my Grails apps to Micronaut. Moving the domain classes to entities was easy. Here is my Route entity (with unnecessary elements removed):

@Entity
class Route implements GormEntity<Route> {

    String grade
    Colour colour
    Date firstSeen
    Date removed

    static belongsTo = [line:Line]

}

Next we want a service. The pattern in latest versions of Grails and Micronaut is to define the service as an interface and then, optionally, provide an (abstract) implementation. Perhaps this is an underlying Hibernate pattern, see https://gorm.grails.org/latest/hibernate/manual/index.html#dataServices. A simple service might look something like this:

@Service(Route)
interface RouteService {

    List<Route> list() {}
    
    Route get(Serializable id) {}

}

This seemingly empty file gives hints to GORM to provide two methods. The first returns a list of all Routes, the second the Route with the given ID. In the controller then we can then write:

@Controller("/routes")
class RouteController {

    @Inject RouteService service

    @Get("/")
    def index() {
        return service.list()
    }

    @Get("/{id}")
    def get(Serializable id) {
         return service.get(id)
    }

}

At this point I expected to be able to run the app and be able to get a list of routes, or a single route, in JSON format. Instead, I got this exception:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: 
could not initialize proxy [uk.co.channele.uclimb.domain.Colour#65] - no Session 
(through reference chain: java.util.ArrayList[0]->
uk.co.channele.uclimb.domain.Route["colour"]->
uk.co.channele.uclimb.domain.Colour$HibernateProxy$y3jqGOWU["name"])

So my evening of searching the interwebs began. Coming from a Grails background I tried creating a service with actual methods, but this didn’t work. (Also, I found that replacing @Inject with @Autowired didn’t work.)

I found various Jackson annotations that allowed me to exclude the colour field but excluding line wasn’t obvious. I found some stuff about making fetches “eager” and about marking items as transient, but none of these helped.

Finally I did find a solution and that was to add in a dependency so that Jackson with work with Hibernate:

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-hibernate5:2.10.2'

Why was this so difficult to find? Did I do something wrong when creating the application, there are lots of features available? I’d used the command:

mn create-app --features=hibernate-gorm,jdbc-hikari --lang=groovy uk.co.channele.uclimb

So I think it’s reasonable that I expected the application to render entities to JSON. Who knows?? As always, I hope that others might find this post useful.