I am using Spring Data Solr and I have the following Solr document model class and have a corresponding SolrCrudRepository for this 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 am trying to modify the annotation '@SolrDocument(collection = "oldCollectionName")' at runtime.
I have a Service which has the following method to find all documents using the repository and the model class
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 alter annotation looks like this
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 this I am correctly getting the newDocumentName set into the annotation map but when calling the testDocumentRepository's find method to find documents. The old collection name is getting picked.
Do I have to do something more for this to work? or I am missing anything?
For reference, I have followed the following tutorial http://www.baeldung.com/java-reflection-change-annotation-params
Why don't you just write a custom SolrRepository
to solve this?
You can inject a SolrTemplate
in your custom repository, allowing you to specify a collection for your query like so:
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 that similarly for repository operation you'd like.
People typically need their own implementations if the standard Spring JPA Repositories don't suit their needs. However, you can still mix your own with the standard SolrCrudRepository
if that's desirable.
See this for an example from Spring.