Skip to main content

Open Source Consultant, Software Developer and System Administrator

If you are interrested in hiring a consultant for the effective use of open source software on an enterprise grade, take a look around in the About section to see, what I have to offer.

Blog and snippets

Various snippets or code parts I found useful, so I keep them here for reference.

Null repsentation needed when using converters in Vaadin 8 binder

TextFields in Vaadin8 are no longer allowed to get a null set as value. This usually is no problem unless we use a Converter for the field binding. In that case a null value about to be bound will raise an assertion error. It also won't help if that field is bound with asRequired.

The solution in this case is to use withNullRepresentation before adding the Converter in the binding builder. This adds another converter at first, that turns null values into "something" so the real converter has to actually work.

See

https://github.com/christoph-frick/try-vaadin8/commit/8eee2ce6880b7a3dd4ce1526cf533ef356d3ec50

and

https://github.com/vaadin/framework/issues/8725

Trying out Vaadin 8

Started a repo to try out the new/changed stuff from Vaadin 8. Lessons learned so far:

  • Immediate on fields is gone. They are now immediate by default.
  • Converter on fields is gone. You convert either in the Binder or you have to write your own field.
  • Use the Binder builder as a builder (chain your calls) -- even if your e.g. Groovy gives you builderish behaviour with with.
  • The CallbackDataProvider is basically the same as the LazyContainer from Viritin.
  • Creating your own CustomField becomes easier, since you get some proper guidance on what to implement. Yet making that field properly propagate change events is still on you.
  • For a composite field it's easiest to build it up using again a Binder and delegate addValueChangeListener down to it.

The repository is here: https://github.com/christoph-frick/try-vaadin8

Better handling of namespaced keywords in maps with Clojure 1.9

Clojure 1.9 (or rather the alphas as of writing this) add some nice shortcuts to deal with maps containing namespaced keywords.

First of all there is now a reader macro #:ns{} to put the namespace on all keys in that map:

user=> (def customer #:customer{:id 42 :name "Acme"})
#'user/customer
user=> customer ; even prints as such
#:customer{:id 42, :name "Acme"}
user=> (assoc customer :something/else 23) ; once you mix, you get the regular output
{:customer/id 42, :customer/name "Acme", :something/else 23}
user=> (:customer/id customer) ; get works as expected
42
user=> #::{:id 23} ; also :: works as expected
#:user{:id 23}

The destructuring side of things got some enhancements too. The :keys destructuring not can also be used with a namespace:

user=> (let [{:customer/keys [id name]} customer] [id name])
[42 "Acme"]
user=> (def order #:order{:id 42
                          :customer customer
                          :items [#:order-item{:id 23
                                               :name "WiFi wire"
                                               :amount 2
                                               :price 64.0}]})
#'user/order
user=> (let [{{:customer/keys [id name]} :order/customer, :order/keys [items]} order]
         [id name (transduce (map (fn [{:order-item/keys [amount price]}] (* amount price))) + 0 items)])
[42 "Acme" 128.0]

Updated Vaadin starter to official Spring plugin

Finally came around to update the Spring-Boot Groovy Vaadin Starter to the official Spring plugin. The only major difference now is the handling of the widgetset via annotation instead of configuration.

Also the "close-to-tweetable" example got an update.

// run with `spring run vaadin.groovy`
@Grapes([
@Grab('com.vaadin:vaadin-spring-boot-starter:1.0.0'),
@Grab('com.vaadin:vaadin-archetype-application:7.6.8'),
])
import com.vaadin.ui.*

@com.vaadin.spring.annotation.SpringUI
@com.vaadin.annotations.Theme("valo")
class MyUI extends UI {
        protected void init(com.vaadin.server.VaadinRequest request) {
                setContent(new Label("Hello World!"))
        }
}