Custom converter spring data mongodb

998 Views Asked by At

I'm trying to implement mu custom converter to be used in a specific find méthode. So i implemented another mongoConfig with a custom mongoTemplate uses my custom converter as bellow.

Here my attribute declared inside my entity called CommOutPut.

private List<Map<String, Object>> calls;

My find méthode is defined as bellow:

public List<CommOutput> getListCommSupervision(Date startDate, Date endDate, String whereComp) {
    Query query = new Query();
    if (startDate != null && endDate != null) {
        query.addCriteria(Criteria.where("creationDate").gte(startDate).lte(endDate));
    } else {
        if (whereComp != null) {
            Criteria criteria = Criteria.where(StringUtils.substringBefore(whereComp, ":")).is(StringUtils.substringAfter(whereComp, ":"));
            query.addCriteria(criteria);
        }
    }
    query.with(Sort.by("_id"));
    query.fields().include("creationDate").include("_id").include("commStatus")
            .include("commId").include("personId").include("sendWay")
            .include("commForceTreatment").include("errors").include("sysSourceIds")
            .include("calls.segmentId").include("calls.isFailureAllowed").include("calls.retHttp")
            .include("calls.retCode").include("orderStatus").include("commVectorStatus")
            .include("distributorId");
    
    return mongoTemplateCustom.find(query, CommOutput.class);
}

My original mongoConfig Bean:

@Configuration
@Data
public class MongoDaoTools extends MongoAutoConfiguration {
    private String env;
    
    private final DatabaseProperties properties;
    
    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoDatabaseFactory databaseFactory) {
        MongoMappingContext context = new MongoMappingContext();
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(databaseFactory);
        MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        converter.afterPropertiesSet();
        return converter;
    }
    
    
    @Bean
    public MongoClient mongoClient() {
        ConnectionString connectionString = new ConnectionString(properties.getDatabaseUri());
        return MongoClients.create(connectionString);
    }
    
    @Bean
    public MongoDatabaseFactory mongoDatabaseFactory(MongoClient client) {
        return new SimpleMongoClientDatabaseFactory(client, properties.getDatabase());
    }
    
    @Bean
    public MongoTemplate mongoTemplate(MongoDatabaseFactory databaseFactory,MappingMongoConverter mappingMongoConverter) throws Exception {
        return new MongoTemplate(databaseFactory,mappingMongoConverter);
    }
}

My converter class annotated with @ReadingConverter:

public class ArrayListToMapConverter implements Converter<ArrayList, List<Map<String, Object>>> {
@Override
public List<Map<String, Object>> convert(ArrayList source) {
    System.out.println("**************il est dans convert***************");
    List<Map<String, Object>> resultList = new ArrayList<>();
    for (Object item : source) {
        if (item instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> mapItem = (Map<String, Object>) item;
            resultList.add(mapItem);
        }
    }
    return resultList;
}

}

Here my custom mongoConfig contains my custom converter annotated with @Configuration:

public class MongoConfig extends MongoAutoConfiguration {
private final DatabaseProperties properties;

public MongoConfig(DatabaseProperties properties) {
    this.properties = properties;
}

@Bean
@Primary
public MongoClient mongoClient() {
    ConnectionString connectionString = new ConnectionString(properties.getDatabaseUri());
    return MongoClients.create(connectionString);
}

@Bean
@Primary
public MongoDatabaseFactory mongoDatabaseFactory(MongoClient client) {
    return new SimpleMongoClientDatabaseFactory(client, properties.getDatabase());
}

@Bean
@Qualifier("mongoTemplateCustom")
public MongoTemplate mongoTemplateCustom(MongoDatabaseFactory databaseFactory) {
    MongoMappingContext context = new MongoMappingContext();
    DbRefResolver dbRefResolver = new DefaultDbRefResolver(databaseFactory);
    MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, context);
    converter.setCustomConversions(customConversions());
    converter.setTypeMapper(new DefaultMongoTypeMapper(null));
    return new MongoTemplate(databaseFactory, converter);
}



@Bean
@Primary
public MongoCustomConversions customConversions() {
    System.out.println("Il passe par lààààààà");
    List<Converter<?, ?>> converters = new ArrayList<>();
    converters.add(new ArrayListToMapConverter());
    return new MongoCustomConversions(converters);
}

}

After retrieving data from data base, i'm performing a loop in my business layer and here is the issue!

if (comm.getCalls() != null && !comm.getCalls().isEmpty()) {
        for (Map<String, Object> call : comm.getCalls()) { // 

java.lang.ClassCastException: class java.util.ArrayList cannot be cast to class java.util.Map (java.util.ArrayList and java.util.Map are in module java.base of loader 'bootstrap')

I guess that my converter was not be called correctly.

1

There are 1 best solutions below

0
BARHOUMI On

converter must be like this:

public class ArrayListToMapConverter implements Converter<ArrayList, Map<String, Object>> {
@Override
public Map<String, Object> convert(ArrayList source) {
    Map<String, Object> resultMap = new HashMap<>();
    for (Object item : source) {
        if (item instanceof Map) {
            @SuppressWarnings("unchecked")
            Map<String, Object> mapItem = (Map<String, Object>) item;
            resultMap.putAll(mapItem);
        }
    }
    return resultMap;
}

}