JOOQ – inline Converter not being applied

Tags: , , ,



In my build.gradle I use a converter in my forcedTypes. This works fine where i need it.

forcedType {
    userType = 'java.util.List<stormsensor.thor.dto.telemetry.FlowEventType>'
    converter = 'stormsensor.thor.config.jooq.StringToFlowEventTypeListConverter'
    includeExpression = '.*\.FLOW_EVENTS'
    includeTypes = '.*'
}

However, I am trying to convert a comma separated string into a list of enums for a specificuse case:

DataType<List<FlowEventType>> LIST_TYPE = SQLDataType.VARCHAR.asConvertedDataType(new StringToFlowEventTypeListConverter());

ctx.select(
  groupConcatDistinct(NOTIFICATION_RULE.FLOW_EVENT_TYPE).as(field(name("notifications"), LIST_TYPE))
)
.from(NOTIFICATION_RULE)
.groupBy(MONITORING_POINT_ID)
.fetchInto(BatchNotificationRuleModel.class);

This throws an exception

org.jooq.exception.MappingException: An error ocurred when mapping record to class stormsensor.thor.dto.notification.batch.BatchNotificationRuleModel
    at org.jooq.impl.DefaultRecordMapper$MutablePOJOMapper.map(DefaultRecordMapper.java:802)
    at org.jooq.impl.DefaultRecordMapper.map(DefaultRecordMapper.java:500)
    at org.jooq.impl.ResultImpl.into(ResultImpl.java:1284)
    at org.jooq.impl.AbstractResultQuery.fetchInto(AbstractResultQuery.java:1550)
    at org.jooq.impl.SelectImpl.fetchInto(SelectImpl.java:3746)
    at stormsensor.thor.repository.notification.BatchNotificationRuleRepositoryJdbcImpl.save(BatchNotificationRuleRepositoryJdbcImpl.java:98)
Caused by: org.jooq.exception.DataTypeException: Cannot convert from CRITICAL_DEPTH,NON_TIDAL_CSO (class java.lang.String) to interface java.util.List
    at org.jooq.tools.Convert$ConvertAll.fail(Convert.java:1194)
    at org.jooq.tools.Convert$ConvertAll.from(Convert.java:1083)
    at org.jooq.tools.Convert.convert0(Convert.java:324)
    at org.jooq.tools.Convert.convert(Convert.java:316)
    at org.jooq.tools.Convert.convert(Convert.java:387)
    at org.jooq.impl.AbstractRecord.get(AbstractRecord.java:275)
    at org.jooq.impl.DefaultRecordMapper$MutablePOJOMapper.map(DefaultRecordMapper.java:830)
    at org.jooq.impl.DefaultRecordMapper$MutablePOJOMapper.map(DefaultRecordMapper.java:762)
    ... 72 more

This is the model I am fetching into:

@Data
@NoArgsConstructor
public class BatchNotificationRuleModel implements Serializable {
    private static final long serialVersionUID = 1L;

    private List<FlowEventType> notifications;
    private List<MessageProtocolType> protocols;
}

Am I missing something?

UPDATE:

I am able to convert inline using

//...
.groupBy(MONITORING_POINT_ID)
.fetchStream().map(e -> {
    Converter<String, List<FlowEventType>> converter = new StringToFlowEventTypeListConverter();
    List<FlowEventType> notifications = e.get(field(name("notifications"), String.class), converter);
    return BatchNotificationRuleModel.builder().notifications(notifications).build();
}).collect(toList());

What is the difference between the initial converter I apply vs the late stage map conversion?

Answer

While it seems reasonable to expect that Field.as(Field) would use the argument field’s name and type for type coercion, this is not the case. As per the Javadoc:

Create an alias for this field based on another field’s name.

In order to coerce your expression to the desired data type, you have to do this, manually:

groupConcatDistinct(NOTIFICATION_RULE.FLOW_EVENT_TYPE)
  .coerce(LIST_TYPE)
  .as("notifications")

See Field.coerce(DataType)



Source: stackoverflow