Skip to content

Different default converters in 3.3 breaks existing code #1101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Enrice opened this issue May 26, 2025 · 3 comments
Open

Different default converters in 3.3 breaks existing code #1101

Enrice opened this issue May 26, 2025 · 3 comments

Comments

@Enrice
Copy link

Enrice commented May 26, 2025

I just switched from Version 3.2.12 to 3.3.0 and it broke my code, I got:
org.springframework.ldap.odm.core.impl.InvalidEntryException: Missing converter from class java.lang.String to class java.lang.Long, this is needed for field xxx on Entry class Yyy.

The reason seems to be different default converters are used now:

GenericConversionService conversionService = new GenericConversionService();

is creating a org.springframework.core.convert.support.GenericConversionService whereas it used to be a org.springframework.core.convert.support.DefaultConversionService which actually CAN convert String to Long.

@Enrice Enrice changed the title Different default converter in 3.3 breaks existing code Different default converters in 3.3 breaks existing code May 26, 2025
@Enrice
Copy link
Author

Enrice commented May 30, 2025

To work around this I tried to use DefaultConversionService instead, which is also not a good replacement, because it lacks a StringToNameConverter which has been added by the now deprecated ConversionServiceConverterManager.

I COULD of course write my own ConversionService to have the best of both worlds, but this seems overly verbose to me.

@fanonwue
Copy link

fanonwue commented Jun 11, 2025

More of a workaround, but you can use ConverterUtils.addDefaultConverters(conversionService) to add Spring LDAP's default converters to any conversion service. This is how DefaultDirectoryMapper does it:

private static ConverterManager createDefaultConverterManager() {
	GenericConversionService conversionService = new GenericConversionService();
	ConverterUtils.addDefaultConverters(conversionService);
	return new ConversionServiceConverterManager(conversionService);
}

You then need to provide your own converters, but converting a string to int/long and vice versa is trivial. Here's an example from my (Kotlin) codebase (using DefaultConversionService, which includes those converters):

@Bean
fun objectDirectoryMapper() = DefaultObjectDirectoryMapper().apply {
    val conversionService = DefaultConversionService()
    ConverterUtils.addDefaultConverters(conversionService)
    this.setConversionService(conversionService)
}

@Bean
fun ldapTemplate(
    contextSource: ContextSource, 
    objectDirectoryMapper: ObjectDirectoryMapper
) = LdapTemplate(contextSource).apply {
    setIgnorePartialResultException(true)
    this.objectDirectoryMapper = objectDirectoryMapper
}

@Enrice
Copy link
Author

Enrice commented Jun 11, 2025

Well, as I said, my workaround was even easier (more or less the same as yours):

public class LdapConversionService extends DefaultConversionService {
    public LdapConversionService() {
        ConverterUtils.addDefaultConverters(this);
    }
}

but I am still not convinced...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants