3

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

user3388770
  • 119
  • 1
  • 11
  • 2
    I looked at the source code for Spring Data Solr and see that the collection name is set when the Repository is instantiated. If you change the annotation on the model class, you'll need to find some way to tear down and rebuild the Repository. Unfortunately, I'm not sure how to accomplish that. – KeithL May 11 '18 at 23:48
  • 1
    Could you explain what you're essentially trying to accomplish and why you want to change the collection name? There might be another way to accomplish what you want without changing annotation values at runtime... – Dovmo May 15 '18 at 20:40
  • My Solr collection names can only be determined at runtime based on customers and environment. That's why they cannot be set using the current annotation. – user3388770 May 16 '18 at 17:45
  • Posted a solution below that might meet your needs – Dovmo May 16 '18 at 23:40

1 Answers1

3

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.

Dovmo
  • 8,121
  • 3
  • 30
  • 44