Java – SolrDocument annotations cannot be set at run time

SolrDocument annotations cannot be set at run time… here is a solution to the problem.

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.

Related Problems and Solutions