2

I am trying to use the SpEL to load the same Document into different collections based on some rules that i have defined.

So to start with what i have:

-first of all the document:

@Document(collection = "#{@mySpecialProvider.getTargetCollectionName()}")
public class MongoDocument {
// some random fields go in
}

-second i have the provider bean that should provide the collection name:

@Component("mySpecialProvider")
public class MySpecialProvider {

public String getTargetCollectionName() {
// Thread local magic goes in bellow
    String targetCollectionName = (String) RequestLocalContext.getFromLocalContext("targetCollectionName");
    if (targetCollectionName == null) {
        targetCollectionName = "defaultCollection";
    }
    return targetCollectionName;
 }
}

The problem is that when i try to insert a document into a specific collection that should be generated by the provider i get the following stacktrace:

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

I also tried making the spring component ApplicationContextAware but still no luck.

4

2 回答 2

4

正如我承诺的那样,我会带着我的问题的答案回来。要让它工作,您需要在应用程序上下文 XML 文件中对mongoTemplate bean 进行以下设置:

<mongo:db-factory dbname="${myDatabaseName.from.properties.file}" mongo-ref="mongo"/>
<bean id="mongoMappingContext" class="org.springframework.data.mongodb.core.mapping.MongoMappingContext"/>   
<bean id="mappingMongoConverter" class="org.springframework.data.mongodb.core.convert.MappingMongoConverter" c:mongoDbFactory-ref="mongoDbFactory"
            c:mappingContext-ref="mongoMappingContext"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"
            c:mongoDbFactory-ref="mongoDbFactory" c:mongoConverter-ref="mappingMongoConverter"/>

并且使用上面的设置和我在我的问题中建议的解决方案。您可以使用相同的域对象并将其存储到基于您选择的设置的多个集合中。

编辑:

由于有人在相关问题中要求它,因此我还将在此处更新 ThreadLocal 上下文的逻辑:

创建一个包含以下实现的RequestLocalContext类:

private static final ThreadLocal<Map> CONTEXT = new ThreadLocal<Map>() {
        protected Map initialValue() {
            Map localMap = new HashMap();
            localMap.put(LocalContextKeys.CONVERSATION_CONTEXT, new HashMap());
            return localMap;
        };
    };

public static void putInLocalContext(Object key, Object value) {
    Map localMap = CONTEXT.get();
    localMap.put(key, value);
}

 public static Object getFromLocalContext(Object key) {
    Map localMap = CONTEXT.get();
    return localMap.get(key);
}

其中LocalContextKeys是一个枚举,其中包含ThreadLocal上下文Map中允许的键。请注意,这些键是用户定义的,因此您可以随意放入您可能需要的任何东西。

于 2013-08-12T07:24:22.750 回答
1

您可以改用 mongo 模板的方法:save(Object objectToSave, String collectionName)。

于 2013-08-10T13:11:14.787 回答