Fixed my problem with creating an ArgumentFactory binder suggested in this post.
So what I needed was to create a class that just contained one field of type Map<String, Object>
implemented the Arugment
interface from org.skife.jdbi.v2.tweak
so I ended up with the following
public class NotificationPayloadArgument implements Argument {
private NotificationPayload payload;
NotificationPayloadArgument(NotificationPayload payload) {
this.payload = payload;
}
@Override
public void apply(int i, PreparedStatement preparedStatement, StatementContext statementContext)
throws SQLException {
preparedStatement.setString(i, toString());
}
@Override
public String toString() {
return new JSONObject(payload).toString();
}
}
To make this work I of course needed to implement a Factory class which implements the org.skife.jdbi.v2.tweak.ArgumentFactory<T>
interface with my newly created type, so the factory ended up as such:
public class NotificationPayloadFactory implements ArgumentFactory<NotificationPayload> {
@Override
public boolean accepts(Class<?> expectedType, Object value, StatementContext ctx) {
return value instanceof NotificationPayload;
}
@Override
public Argument build(Class<?> expectedType, NotificationPayload value, StatementContext ctx) {
return value;
}
}
and of course lastly also as mentioned in Does JDBI accept UUID parameters? I had to register my factory:
jdbi.registerArgumentFactory(new NotificationPayloadFactory());
I tried to do this with just a factory for a Map<String, Object>
but could not make it work for that, and there was a risk for NPE.
EDIT
The reason I am Overriding the toString()
in NotificationPayload
is because I need the payload in json format some places where I need a String object. But else it can be removed and then just use the new JSONObject(payload).toString()
in the preparedStatement.setString()
where toString()
is called.