Skip to content
Advertisement

Micronaut fails to load and use my `TypeConverter` implementation

I have a controller method, that takes in a POJO.

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor

public class Dto {    
    private LocalDate endDate;
    private String token;
    private TransactionType type;   
}

Transaction type is a simple enum, but I want to use a custom conversion from the inbound value to the transaction type.

@Slf4j
@Controller("/api/transactions")
public class IssuerTransactionController {
    @Get(value = "/{?tr*}", produces = APPLICATION_JSON)
    public List<String> get(Dto tr) {
        return new ArrayList<>();
    }
}

I have written a converter:

@Slf4j
@Singleton
public class TransactionTypeConverter implements TypeConverter<String, TransactionType> {
    @Override
    public Optional<TransactionType> convert(String value, Class<TransactionType> targetType, ConversionContext context) {
        return Arrays.stream(TransactionType.values())
                .filter(txnType -> StringUtils.equals(txnType.getTransactionType(), value) || StringUtils.equals(txnType.name(), value))
                .findFirst();
    }
}

Micronaut is not using the type converter to transform the inbound value?
Is some special registration process needed in order for Micronaut to know that it should be using the converter?

If I add a constructor to TransactionTypeConverter I can see that the class is never actually created by Micronaut at all.

If I add it as a regular dependency to the controller, it’s loaded (no surprise there), but still not used. Is there a step I am missing?

Advertisement

Answer

Seems you are using the Binding from Multiple Query values functionality which under the hood is just creating the map of the query parameters you passed in and uses the Jackson to convert the map into your own POJO. So it does not rely on the system converters but only on the Jackson itself. What you can do is just use Jacksons @JsonCreator annotation to customize the conversation.

Something like this should work.

public enum TransactionType {
    A ("A"),
    B ("B");

    private final String transactionType;

    TransactionType(String transactionType){
        this.transactionType = transactionType;
    }

    public String getTransactionType() {
        return transactionType;
    }

    @JsonCreator
    public static TransactionType forValue(Collection<String> values) {           
        if(values == null || values.isEmpty()){
            return null;
        }
        String value = values.get(0);
        return Arrays.stream(TransactionType.values())
            .filter(txnType -> StringUtils.equals(txnType.getTransactionType(), value) || StringUtils.equals(txnType.name(), value))
            .findFirst().orElse(null);
    }
}

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement