7

I am using Spring Data for MongoDB and I need to be able to configure collection at runtime.

My repository is defined as:

@Repository
public interface EventDataRepository extends MongoRepository<EventData, String> {
}

I tried this silly example:

@Document(collection = "${mongo.event.collection}")
public class EventData implements Serializable {

but mongo.event.collection did not resolve to a name as it does with a @Value annotation.

A bit more debugging and searching and I tried the following: @Document(collection = "#{${mongo.event.collection}}")

This produced an exception:

Caused by: org.springframework.expression.spel.SpelParseException: EL1041E:(pos 1): After parsing a valid expression, there is still more data in the expression: 'lcurly({)'
    at org.springframework.expression.spel.standard.InternalSpelExpressionParser.doParseExpression(InternalSpelExpressionParser.java:129)
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:60)
    at org.springframework.expression.spel.standard.SpelExpressionParser.doParseExpression(SpelExpressionParser.java:32)
    at org.springframework.expression.common.TemplateAwareExpressionParser.parseExpressions(TemplateAwareExpressionParser.java:154)
    at org.springframework.expression.common.TemplateAwareExpressionParser.parseTemplate(TemplateAwareExpressionParser.java:85)

Perhaps I just don't know how to quite use SPel to access values from Spring's Property Configurer.

When stepping through the code, I see that there is a way to specify collection name or even expressions, however, I am not sure which annotation should be used for this purpose or how to do it.

Thanks. -AP_

Alex Paransky
  • 985
  • 2
  • 10
  • 21
  • Maybe that's your problem? https://jira.spring.io/browse/DATAMONGO-1043 `...` which version of spring-data-mongodb are you using? – Benjamin M Apr 13 '15 at 11:40
  • It could be (I am using 1.7.0-RELEASE), however, the issue you mentioned deals with expressions in queries between multiple invocations. However, you did clue me that it has to be a proper SPEL expression, so I changed it. See updated question. – Alex Paransky Apr 13 '15 at 13:38

4 Answers4

6

You can solve this problem by just using SPeL:

@Document(collection = "#{environment.getProperty('mongo.event.collection')}")
public class EventData implements Serializable {
    ...
}

Update Spring 5.x:

Since Spring 5.x or so you need an additional @ before environment:

@Document(collection = "#{@environment.getProperty('mongo.event.collection')}")
public class EventData implements Serializable {
    ...
}

Docs:

Oliver Koch
  • 103
  • 1
  • 7
5

So, at the end, here is a work around that did the trick. I guess I really don't know how to access data from Spring Properties Configurer using the SPeL expressions.

In my @Configuration class:

@Value("${mongo.event.collection}")
private String
    mongoEventCollectionName;

@Bean
public String mongoEventCollectionName() {
    return
        mongoEventCollectionName;
}

On my Document:

@Document(collection = "#{mongoEventCollectionName}")

This, appears to work and properly pick up the name configured in my .properties file, however, I am still not sure why I could not just access the value with $ as I do in the @Value annotation.

Alex Paransky
  • 985
  • 2
  • 10
  • 21
  • This answer helped me in some directions, but I keep getting an error "Property or field 'mongoEventCollectionName' cannot be found on null". the injection into the bean seems to work fine, but not the one into `@Document` – jmmut Feb 07 '17 at 12:15
  • 1
    I got it working thanks to [this answer](http://stackoverflow.com/a/21045404/2375586): set the ApplicationContext into the MongoMappingContext. – jmmut Feb 07 '17 at 17:12
3

define your entity class like

@Document(collection = "${EventDataRepository.getCollectionName()}")
public class EventData implements Serializable {

Define a custom repository interface with getter and setter methods for "collectionName"

public interface EventDataRepositoryCustom {

    String getCollectionName();

    void setCollectionName(String collectionName);
}

provide implementation class for custom repository with "collectionName" implementation

public class EventDataRepositoryImpl implements EventDataRepositoryCustom{

    private static String collectionName = "myCollection";

    @Override
    public String getCollectionName() {
        return collectionName;
    }

    @Override
    public void setCollectionName(String collectionName) {
        this.collectionName = collectionName;
    }
}

Add EventDataRepositoryImpl to the extends list of your repository interface in this it would look like

@Repository
public interface EventDataRepository extends MongoRepository<EventData, String>, EventDataRepositoryImpl  {
}

Now in your Service class where you are using the MongoRepository set the collection name, it would look like

@Autowired
EventDataRepository  repository ;

repository.setCollectionName("collectionName");
Lee Meador
  • 12,829
  • 2
  • 36
  • 42
pranay
  • 31
  • 1
0

Entity Class

@Document    // remove the parameters from here


public class EscalationCase 
{

}

Configuration class

public class MongoDBConfiguration {

    private final Logger logger = LoggerFactory.getLogger(MongoDBConfiguration.class);

    @Value("${sfdc.mongodb.collection}") //taking collection name from properties file 
    private String collectionName;

    @Bean

    public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, MongoMappingContext context) {

        MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDbFactory), context);
        converter.setTypeMapper(new DefaultMongoTypeMapper(null));
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory, converter);
        if (!mongoTemplate.collectionExists(collectionName)) {
            mongoTemplate.createCollection(collectionName);  // adding the collection name here
        }
        return mongoTemplate;

    }
}
Tilman Hausherr
  • 17,731
  • 7
  • 58
  • 97
vineel
  • 1