SolrDocument annotations cannot be set at run time
I’m using Spring Data Solr, I have the following Solr document model class, and I have a corresponding SolrCrudRepository class
@SolrDocument(collection = "oldCollectionName")
public class TestDocument {
@Id
@Indexed(name = "id", type = "string")
private String id;
@Field(value = "name")
private String name;
@Field(value = "externalid")
private Integer externalId;
}
I’m trying to modify the comment “@SolrDocument(collection = “oldCollectionName”)” at runtime.
I have a service that has the following methods to find all documents using the repository and model classes
public List<TestDocument> getDocumentsByName(String name){
String newSolrDocument = getModifiedSolrCollectionName();
alterAnnotationValue(TestDocument.class, SolrDocument.class, newSolrDocument);
SolrDocument solrDocument = TestDocument.class.getAnnotation(SolrDocument.class);
LOGGER.info("Dynamically set SolrDocument Annotaation: "+solrDocument.collection());
return testDocumentRepository.findByName(name);
}
The code to modify the comments is shown below
public void alterAnnotationValue(Class<?> targetClass, Class<? extends Annotation> targetAnnotation, Annotation targetValue) {
try {
Method method = Class.class.getDeclaredMethod(ANNOTATION_METHOD, null);
method.setAccessible(true);
Object annotationData = method.invoke(targetClass);
Field annotations = annotationData.getClass().getDeclaredField(ANNOTATIONS);
annotations.setAccessible(true);
Map<Class<? extends Annotation>, Annotation> map = (Map<Class<? extends Annotation>, Annotation>) annotations.get(annotationData);
map.put(targetAnnotation, targetValue);
} catch (Exception e) {
e.printStackTrace();
}
}
Using it, I correctly set newDocumentName to the annotation map, but when calling testDocumentRepository’s find method to find the document. Selecting old collection name.
Do I need to do more to make it work? Or am I missing something?
As a reference, I followed the tutorial http://www.baeldung.com/java-reflection-change-annotation-params
Solution
Why don’t you write a custom SolrRepository
to solve this problem?
You can inject a SolrTemplate
in your custom repository so that you can specify a collection for your query:
public class TestDocumentRepositoryImpl implements TestDocumentRepository {
private SolrOperations solrTemplate;
...
public CustomSolrRepositoryImpl(SolrOperations solrTemplate) {
super();
this.solrTemplate = solrTemplate;
}
@Override
public TestDocument findOneSpecifyingCollection(String collection, String id) {
return solrTemplate.getById(collection, id, TestDocument.class);
}
}
You can do something similar to your favorite repository operations.
If the standard Spring JPA repository doesn’t suit their needs, people often need their own implementations. However, you still can mix Use the standard SolrCrudRepository
if needed.
See this uses the example from Spring as an example.