Skip to content

Custom converter not used for Iterable type from 2.4.1 #1343

@loolzaaa

Description

@loolzaaa

I have a custom converter JsonNode <-> PGobject (PGobject represent JSON type for PostgreSQL):

@Configuration
@RequiredArgsConstructor
public class CustomJdbcConfiguration extends AbstractJdbcConfiguration {

    private final ObjectMapper objectMapper;

    @Override
    protected List<?> userConverters() {
        return Arrays.asList(
                new JsonNodeToJsonConverter(),
                new JsonToJsonNodeConverter()
        );
    }

    @ReadingConverter
    class JsonToJsonNodeConverter implements Converter<PGobject, JsonNode> {
        @Override
        public JsonNode convert(PGobject json) {
            try {
                return objectMapper.readTree(json.getValue());
            } catch (JsonProcessingException | NullPointerException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    @WritingConverter
    class JsonNodeToJsonConverter implements Converter<JsonNode, PGobject> {
        @Override
        public PGobject convert(JsonNode jsonNode) {
            PGobject json = new PGobject();
            json.setType("jsonb");
            try {
                json.setValue(objectMapper.writeValueAsString(jsonNode));
            } catch (SQLException | JsonProcessingException e) {
                e.printStackTrace();
            }
            return json;
        }
    }
}

Also, i have a simple repo @Query method:

@Repository
public interface UserRepository extends CrudRepository<User, Long> {
    @Modifying
    @Query("UPDATE users SET config = :config::jsonb WHERE login = :login")
    void updateConfigByLogin(@Param("config") JsonNode config, @Param("login") String login);
}

Before Spring Data JDBC this converter used normally: old version of code

But, from 2.4.1 version there is a check for Iterable in StringBasedJdbcQuery:

JdbcValue jdbcValue;
if (value instanceof Iterable) {
    // ..........
    Class<?> elementType = resolvableType.getGeneric(0).resolve();
    Assert.notNull(elementType, "@Query Iterable parameter generic type could not be resolved!");
    // ..........
} else {
    jdbcValue = converter.writeJdbcValue(value, type, 
             JdbcUtil.targetSqlTypeFor(JdbcColumnTypes.INSTANCE.resolvePrimitiveType(type)));
}

JsonNode implements Iterable interface, but Class<?> elementType is null, so assert is failed and custom converter never applied. If manually run else block, conversion goes normally.

Metadata

Metadata

Assignees

Labels

type: regressionA regression from a previous release

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions