Sunday, January 15, 2017

Kotlin Properties and the Vaadin 8 BeanBinder

Vaadin 8 (currently in beta) comes with a whole new DataBinding API that makes heavy use of the Java 8 Lambda Features.

Unfortunately Java has no concept of a Property, so one of the new ways to bind a Bean Property is writing something like (Taken from the documentation):

binder.bind(nameField, Person::getName, Person::setName);

Since Kotlin has a concept for a property you may want to write something like:

binder.forField(nameField)
        .bind(Person::name)


Thats possible with an extension method for the Vaadin Binder that could probably look like this:

fun <BEAN, T> Binder.BindingBuilder<BEAN, T>.bind(prop: KMutableProperty<T>) {
    this.bind(
            ValueProvider { bean: BEAN -> prop.getter.call(bean) },
            Setter { bean: BEAN, v: T -> prop.setter.call(bean, v) })
}

Have fun with Kotlin & Vaadin!




Wednesday, September 14, 2016

Hibernate JSON Types in Kotlin: A TypeCasting puzzler and generic collections

Trying to persist JSON types in Postgresql using Hibernate I came across the excellent post from Vlad Mihalcea How to map JSON objects using generic Hibernate Types.

I just wanted to have it as Kotlin code, as mostly all of my project is coded in Kotlin. So I used the Java-to-Kotlin conversion which as usual left me with some puzzlers, one of them I'd like to mention:

class JsonBinarySqlTypeDescriptor : AbstractJsonSqlTypeDescriptor() {

    override fun <X : Any> getBinder(
            javaTypeDescriptor: JavaTypeDescriptor<X>): ValueBinder<X> {

        return object : BasicBinder<X>(javaTypeDescriptor, this) {
            @Throws(SQLException::class)
            override fun doBind(
                    st: PreparedStatement,
                    value: X,
                    index: Int,
                    options: WrapperOptions) {
                st.setObject(index,
                        javaTypeDescriptor.unwrap<X>(
                                value,
                                (JsonNode::class.java as Class<X>),
                                options),
                        getSqlType())
            }

The most puzzling research was up, when it came to passing the JsonNode type to

protected abstract void doBind(PreparedStatement st, J value, ...
in BasicBinder. I had to cast it to Class<X>, it's still an unchecked conversion, but at last it works.


Ome thing I would wish I had a starting idea for is how to persist generic collections,  Let's start with passing in the TypeReference Jackson needs as a Hibernate Type Parameter (String only...)

private lateinit var jsonObjectClass: Class<*>
private var jsonTypeReference: TypeReference<*>? = null
override fun setParameterValues(parameters: Properties) {
    jsonObjectClass = (parameters.get(
            DynamicParameterizedType.PARAMETER_TYPE)

            as DynamicParameterizedType.ParameterType)
            .getReturnedClass()
    val jsonTypeParam = parameters.get("json.typereference") as String?
    if (jsonTypeParam != null) {
        jsonTypeReference = Class.forName(jsonTypeParam)
                .getConstructor().newInstance() as TypeReference<*>
    }
}

Now, when we set this on a Collection like this:

@Type(type = "jsonb",
 parameters = arrayOf(Parameter(name = "json.typereference",
 value = "de.eiswind.xino.datalayer.entities.PermissionTypeReference")))
var permissions: MutableList<Permission> = ArrayList<Permission>()
We can pass in any custom TypeReferene instance to Jackson to deserialize generic collections!
class PermissionTypeReference :
        TypeReference<MutableList<Permission>>() {
}
At last we need to make the proper call to Jackson for the deserialization:
override fun fromString(string: String): Any {
    if (jsonTypeReference == null) {
        return JacksonUtil.fromString(string, jsonObjectClass)
    } else {
        return JacksonUtil.fromString(string,
                jsonTypeReference as TypeReference<*>)
    }
}
JacksonUtil has the corresponding overloaded methods:
fun <T> fromString(string: String, clazz: Class<T>): T {
    try {
        return OBJECT_MAPPER.readValue(string, clazz)
    } catch (e: IOException) { ...
fun <T> fromString(string: String, reference: TypeReference<T>): T {
    try {
        return OBJECT_MAPPER.readValue(string, reference)
    } catch (e: IOException) { ...
There's one thing that hit me terrible in the next morning hours, we have to think about clone()!
fun <T : Any> clone(value: T): T {
    return when (value) {
        is ArrayList<*> -> {
            val newList = ArrayList<Any?>()
            for (elem in value) {
                newList.add(fromString(
                        toString(elem), elem.javaClass))
            }
            newList as T        }
        else ->
            fromString(toString(value), value.javaClass)
    }
}

Friday, January 22, 2016

Consuming p2 Repositories from Maven - Update

I always have been struggling with p2. Tycho somewhat made things easier. But I always tried to find ways to use the eclipse p2 repositories with maven and bndtools.

Today I installed Package Drone to see if this solves my troubles, and believe it, it does. I uploaded the p2-repository zip from RAP and I was able to consume the databinding-bundles with plain maven and bnd-tools. Strike!


Tuesday, July 14, 2015

In-Container Selenium Tests

Currently I'm evaluating vaadin's testbench selenium framework. But the principles should be working with other frameworks too, as long as you find a way to register your http session while running the test. For the setup, I'm running vaadin with spring boot and the vaadin-spring add-on. The Selenium Tests are running the complete Spring Boot container.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = VaadinApplication.class)
@WebIntegrationTest

In the Main UI class I register the UI instance in a simple List Bean called UIRegsitry:

if (uiRegistry != null) {
    uiRegistry.getRegisteredUIs().add(this);
    addDetachListener(event -> uiRegistry.getRegisteredUIs().remove(this));
}

The Registry is optional and gets injected only when running the selenium tests:

@Autowired(required = false)
private UIRegistry uiRegistry;


Now "inside" the selenium test we can access all of the Vaadin UI Beans in the UI Scope:


UI uiUnderTest = uiRegistry.getRegisteredUIs().get(0);
uiUnderTest.access(() -> bookView = applicationContext.getBean(BookView.class)).get();
productIdentifiers = bookView.getProduct().getProductIdentifiers();

So now we can enter a value with selenium and directly check if all the bindings are working properly by accessing the involved model instances.

It should be possible to do similar stuff with arquillian and the http session for "regular" webapps.