Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot resolve bean in SpEL for Spring Data MongoDB collection name

I am trying to customize the collection name where an entity class is saved into and indexed, using Spring Data MongoDB and Spring Batch. The class is declared as follows:

@Document
@CompoundIndex(name = "unique_source", def = "{'fid': 1, 'sid': 1}", unique = true, background = true)
public class VariantSource {
    ...
}

And the item writer:

public class VariantSourceMongoWriter extends MongoItemWriter<VariantSource> {

    public VariantSourceEntityMongoWriter(MongoOperations mongoOperations, String collectionName) {
        setTemplate(mongoOperations);
        setCollection(collectionName);
    }
}

Saving works fine: the objects are written into the collection provided as argument. The problem is that the indexes are created in the default collection, named after the class name (variantSource).

After reading this and this, I created the following:

public class MongoCollections {

    public String getCollectionFilesName() {
        return "my_custom_collection_name"; // TODO Dynamic value
    }
}


@Configuration
public class MongoCollectionsConfiguration {

    @Bean
    public MongoCollections mongoCollections() {
        return new MongoCollections(); 
    }


@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {MongoCollectionsConfiguration.class})
public class VariantSourceMongoWriterTest {

    @Autowired
    private MongoCollections mongoCollections;

}

I have checked the instance is correctly autowired into the unit tests, but I can't make it work with SpEL.

After changing the @Document annotation to look like this:

@Document(collection = "#{@mongoCollections.getCollectionFilesName()}")

the following exception is thrown:

org.springframework.expression.spel.SpelEvaluationException: EL1057E:(pos 1): No bean resolver registered in the context to resolve access to bean 'mongoCollections'

And if I use this:

@Document(collection = "#{mongoCollections.getCollectionFilesName()}")

the exception is this one:

org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 0): Property or field 'mongoCollections' cannot be found on null

Finally, the following creates a collection with the name as specified, symbols included:

@Document(collection = "@mongoCollections.getCollectionFilesName()")
like image 441
arklad Avatar asked Jan 17 '17 13:01

arklad


2 Answers

As pointed by this answer, to fix the injection:

@Document(collection = "#{mongoCollections.getCollectionFilesName()}") 

SpelEvaluationException: EL1007E:(pos 0): Property or field 'mongoCollections' cannot be found on null

(or a direct method bean: @Document(collection = "#{getCollectionFilesName}")), try setting the ApplicationContext into the MongoMappingContext (which is used to instantiate the MongoConverter, and later the MongoTemplate):

@Bean
public MongoMappingContext MongoMappingContext() {
    MongoMappingContext mappingContext = new MongoMappingContext();
    mappingContext.setApplicationContext(applicationContext);
    return mappingContext;
}
like image 85
jmmut Avatar answered Sep 30 '22 00:09

jmmut


Make sure that your bean mongoCollections is registered in the application context, and also correct the SpEL expression as below.

@Document(collection = "#{@mongoCollections.getCollectionFilesName()}")

like image 44
Felipe Tapia Avatar answered Sep 30 '22 00:09

Felipe Tapia