You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-user@lucene.apache.org by Peter Hanning <pe...@gmail.com> on 2010/06/03 20:35:42 UTC

Does SolrJ support nested annotated beans?

When modeling documents with a lot of fields (hundreds) the bean class used
with SolrJ to interact with the Solr index tends to get really big and
unwieldy. I was hoping that it would be possible to extract groups of
properties into nested beans and move the @Field annotations along.

Basically, I want to refactor something like the following:

  // Imports have been omitted for this example.
  public class TheBigOne
  {
    @Field("UniqueKey")
    private String uniqueKey;
    @Field("Name_en")
    private String name_en;
    @Field("Name_es")
    private String name_es;
    @Field("Name_fr")
    private String name_fr;
    @Field("Category")
    private String category;
    @Field("Color")
    private String color;
    // Additional properties, getters and setters have been omitted for this
example.
  }

into something like the following:

  // Imports have been omitted for this example.
  public class TheBigOne
  {
    @Field("UniqueKey")
    private String uniqueKey;
    private Names names = new Names();
    private Classification classification = new Classification();
    // Additional properties, getters and setters have been omitted for this
example.
  }

  // Imports have been omitted for this example.
  public class Names
  {
    @Field("Name_en")
    private String name_en;
    @Field("Name_es")
    private String name_es;
    @Field("Name_fr")
    private String name_fr;
    // Additional properties, getters and setters have been omitted for this
example.
  }

  // Imports have been omitted for this example.
  public class Classification
  {
    @Field("Category")
    private String category;
    @Field("Color")
    private String color;
    // Additional properties, getters and setters have been omitted for this
example.
  }

This did not work however as the DocumentObjectBinder does not seem to walk
the nested object graph. Am I doing something wrong, or is this not
supported?

I see JIRA tickets 1129 and 1357 could alleviate this issue somewhat for the
Name* fields once 1.5 comes out. Still, it would be great to be able to nest
beans without using dynamic names in the field annotations like in the
Classification example above.


As a quick and naive test I tried to change the DocumentObjectBinder's
collectInfo method to something like the following:

  private List<DocField> collectInfo(Class clazz) {
    List<DocField> fields = new ArrayList<DocField>();
    Class superClazz = clazz;
    ArrayList<AccessibleObject> members = new ArrayList<AccessibleObject>();
    while (superClazz != null && superClazz != Object.class) {
      members.addAll(Arrays.asList(superClazz.getDeclaredFields()));
      members.addAll(Arrays.asList(superClazz.getDeclaredMethods()));
      superClazz = superClazz.getSuperclass();
    }
    for (AccessibleObject member : members) {
      if (member.isAnnotationPresent(Field.class)) {
        member.setAccessible(true);
        fields.add(new DocField(member));
      } // BEGIN changes
      else { // A quick test supporting only Field, not Method and others
        if (member instanceof java.lang.reflect.Field) {
          java.lang.reflect.Field field = (java.lang.reflect.Field) member;
          fields.addAll(collectInfo(field.getType()));
        }
      } // END changes
    }
    return fields;
  }

This worked in that SolrJ started walking down into nested beans, checking
for and handling @Field annotations in the nested beans. However, when
trying to retrieve the values of the fields in the nested beans, SolrJ still
tried to look for them in the main bean as far as I can tell.

ERROR 2010-06-02 09:28:35,326 (main) () (SolrIndexer.java:335 main) -
Exception encountered:
java.lang.RuntimeException: Exception while getting value: private
java.lang.String Names.Name_en
        at
org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.get(DocumentObjectBinder.java:377)
        at
org.apache.solr.client.solrj.beans.DocumentObjectBinder.toSolrInputDocument(DocumentObjectBinder.java:71)
        at
org.apache.solr.client.solrj.SolrServer.addBeans(SolrServer.java:56)
...
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String
field Names.Name_en to TheBigOne
        at
sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
        at
sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
        at
sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
        at
sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
        at java.lang.reflect.Field.get(Field.java:358)
        at
org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.get(DocumentObjectBinder.java:374)
        ... 7 more

My conclusion is that the @Field annotation can presently only be put in the
main bean and nested beans are not supported. It seems that more more than a
simple patch is required to rewrite how SolrJ collects document fields from
nested beans.

Shall I go ahead and create a JIRA ticket with this information?

Best Regards,
Peter

-- 
View this message in context: http://lucene.472066.n3.nabble.com/Does-SolrJ-support-nested-annotated-beans-tp868375p868375.html
Sent from the Solr - User mailing list archive at Nabble.com.

Re: Does SolrJ support nested annotated beans?

Posted by Mark Miller <ma...@gmail.com>.
I've started an issue building on the quick test attempt below. Issue 1945:

https://issues.apache.org/jira/browse/SOLR-1945


-- 
- Mark

http://www.lucidimagination.com

On 6/4/10 10:12 PM, Thomas J. Buhr wrote:
> +1
>
> Good question, my use of Solr would benefit from nested annotated beans as well.
>
> Awaiting the reply,
>
> Thom
>
>
> On 2010-06-03, at 1:35 PM, Peter Hanning wrote:
>
>>
>> When modeling documents with a lot of fields (hundreds) the bean class used
>> with SolrJ to interact with the Solr index tends to get really big and
>> unwieldy. I was hoping that it would be possible to extract groups of
>> properties into nested beans and move the @Field annotations along.
>>
>> Basically, I want to refactor something like the following:
>>
>>   // Imports have been omitted for this example.
>>   public class TheBigOne
>>   {
>>     @Field("UniqueKey")
>>     private String uniqueKey;
>>     @Field("Name_en")
>>     private String name_en;
>>     @Field("Name_es")
>>     private String name_es;
>>     @Field("Name_fr")
>>     private String name_fr;
>>     @Field("Category")
>>     private String category;
>>     @Field("Color")
>>     private String color;
>>     // Additional properties, getters and setters have been omitted for this
>> example.
>>   }
>>
>> into something like the following:
>>
>>   // Imports have been omitted for this example.
>>   public class TheBigOne
>>   {
>>     @Field("UniqueKey")
>>     private String uniqueKey;
>>     private Names names = new Names();
>>     private Classification classification = new Classification();
>>     // Additional properties, getters and setters have been omitted for this
>> example.
>>   }
>>
>>   // Imports have been omitted for this example.
>>   public class Names
>>   {
>>     @Field("Name_en")
>>     private String name_en;
>>     @Field("Name_es")
>>     private String name_es;
>>     @Field("Name_fr")
>>     private String name_fr;
>>     // Additional properties, getters and setters have been omitted for this
>> example.
>>   }
>>
>>   // Imports have been omitted for this example.
>>   public class Classification
>>   {
>>     @Field("Category")
>>     private String category;
>>     @Field("Color")
>>     private String color;
>>     // Additional properties, getters and setters have been omitted for this
>> example.
>>   }
>>
>> This did not work however as the DocumentObjectBinder does not seem to walk
>> the nested object graph. Am I doing something wrong, or is this not
>> supported?
>>
>> I see JIRA tickets 1129 and 1357 could alleviate this issue somewhat for the
>> Name* fields once 1.5 comes out. Still, it would be great to be able to nest
>> beans without using dynamic names in the field annotations like in the
>> Classification example above.
>>
>>
>> As a quick and naive test I tried to change the DocumentObjectBinder's
>> collectInfo method to something like the following:
>>
>>   private List<DocField>  collectInfo(Class clazz) {
>>     List<DocField>  fields = new ArrayList<DocField>();
>>     Class superClazz = clazz;
>>     ArrayList<AccessibleObject>  members = new ArrayList<AccessibleObject>();
>>     while (superClazz != null&&  superClazz != Object.class) {
>>       members.addAll(Arrays.asList(superClazz.getDeclaredFields()));
>>       members.addAll(Arrays.asList(superClazz.getDeclaredMethods()));
>>       superClazz = superClazz.getSuperclass();
>>     }
>>     for (AccessibleObject member : members) {
>>       if (member.isAnnotationPresent(Field.class)) {
>>         member.setAccessible(true);
>>         fields.add(new DocField(member));
>>       } // BEGIN changes
>>       else { // A quick test supporting only Field, not Method and others
>>         if (member instanceof java.lang.reflect.Field) {
>>           java.lang.reflect.Field field = (java.lang.reflect.Field) member;
>>           fields.addAll(collectInfo(field.getType()));
>>         }
>>       } // END changes
>>     }
>>     return fields;
>>   }
>>
>> This worked in that SolrJ started walking down into nested beans, checking
>> for and handling @Field annotations in the nested beans. However, when
>> trying to retrieve the values of the fields in the nested beans, SolrJ still
>> tried to look for them in the main bean as far as I can tell.
>>
>> ERROR 2010-06-02 09:28:35,326 (main) () (SolrIndexer.java:335 main) -
>> Exception encountered:
>> java.lang.RuntimeException: Exception while getting value: private
>> java.lang.String Names.Name_en
>>         at
>> org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.get(DocumentObjectBinder.java:377)
>>         at
>> org.apache.solr.client.solrj.beans.DocumentObjectBinder.toSolrInputDocument(DocumentObjectBinder.java:71)
>>         at
>> org.apache.solr.client.solrj.SolrServer.addBeans(SolrServer.java:56)
>> ...
>> Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String
>> field Names.Name_en to TheBigOne
>>         at
>> sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
>>         at
>> sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
>>         at
>> sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
>>         at
>> sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
>>         at java.lang.reflect.Field.get(Field.java:358)
>>         at
>> org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.get(DocumentObjectBinder.java:374)
>>         ... 7 more
>>
>> My conclusion is that the @Field annotation can presently only be put in the
>> main bean and nested beans are not supported. It seems that more more than a
>> simple patch is required to rewrite how SolrJ collects document fields from
>> nested beans.
>>
>> Shall I go ahead and create a JIRA ticket with this information?
>>
>> Best Regards,
>> Peter
>>
>> --
>> View this message in context: http://lucene.472066.n3.nabble.com/Does-SolrJ-support-nested-annotated-beans-tp868375p868375.html
>> Sent from the Solr - User mailing list archive at Nabble.com.
>>
>


Re: Does SolrJ support nested annotated beans?

Posted by "Thomas J. Buhr" <th...@superstringmedia.com>.
+1

Good question, my use of Solr would benefit from nested annotated beans as well.

Awaiting the reply,

Thom


On 2010-06-03, at 1:35 PM, Peter Hanning wrote:

> 
> When modeling documents with a lot of fields (hundreds) the bean class used
> with SolrJ to interact with the Solr index tends to get really big and
> unwieldy. I was hoping that it would be possible to extract groups of
> properties into nested beans and move the @Field annotations along.
> 
> Basically, I want to refactor something like the following:
> 
>  // Imports have been omitted for this example.
>  public class TheBigOne
>  {
>    @Field("UniqueKey")
>    private String uniqueKey;
>    @Field("Name_en")
>    private String name_en;
>    @Field("Name_es")
>    private String name_es;
>    @Field("Name_fr")
>    private String name_fr;
>    @Field("Category")
>    private String category;
>    @Field("Color")
>    private String color;
>    // Additional properties, getters and setters have been omitted for this
> example.
>  }
> 
> into something like the following:
> 
>  // Imports have been omitted for this example.
>  public class TheBigOne
>  {
>    @Field("UniqueKey")
>    private String uniqueKey;
>    private Names names = new Names();
>    private Classification classification = new Classification();
>    // Additional properties, getters and setters have been omitted for this
> example.
>  }
> 
>  // Imports have been omitted for this example.
>  public class Names
>  {
>    @Field("Name_en")
>    private String name_en;
>    @Field("Name_es")
>    private String name_es;
>    @Field("Name_fr")
>    private String name_fr;
>    // Additional properties, getters and setters have been omitted for this
> example.
>  }
> 
>  // Imports have been omitted for this example.
>  public class Classification
>  {
>    @Field("Category")
>    private String category;
>    @Field("Color")
>    private String color;
>    // Additional properties, getters and setters have been omitted for this
> example.
>  }
> 
> This did not work however as the DocumentObjectBinder does not seem to walk
> the nested object graph. Am I doing something wrong, or is this not
> supported?
> 
> I see JIRA tickets 1129 and 1357 could alleviate this issue somewhat for the
> Name* fields once 1.5 comes out. Still, it would be great to be able to nest
> beans without using dynamic names in the field annotations like in the
> Classification example above.
> 
> 
> As a quick and naive test I tried to change the DocumentObjectBinder's
> collectInfo method to something like the following:
> 
>  private List<DocField> collectInfo(Class clazz) {
>    List<DocField> fields = new ArrayList<DocField>();
>    Class superClazz = clazz;
>    ArrayList<AccessibleObject> members = new ArrayList<AccessibleObject>();
>    while (superClazz != null && superClazz != Object.class) {
>      members.addAll(Arrays.asList(superClazz.getDeclaredFields()));
>      members.addAll(Arrays.asList(superClazz.getDeclaredMethods()));
>      superClazz = superClazz.getSuperclass();
>    }
>    for (AccessibleObject member : members) {
>      if (member.isAnnotationPresent(Field.class)) {
>        member.setAccessible(true);
>        fields.add(new DocField(member));
>      } // BEGIN changes
>      else { // A quick test supporting only Field, not Method and others
>        if (member instanceof java.lang.reflect.Field) {
>          java.lang.reflect.Field field = (java.lang.reflect.Field) member;
>          fields.addAll(collectInfo(field.getType()));
>        }
>      } // END changes
>    }
>    return fields;
>  }
> 
> This worked in that SolrJ started walking down into nested beans, checking
> for and handling @Field annotations in the nested beans. However, when
> trying to retrieve the values of the fields in the nested beans, SolrJ still
> tried to look for them in the main bean as far as I can tell.
> 
> ERROR 2010-06-02 09:28:35,326 (main) () (SolrIndexer.java:335 main) -
> Exception encountered:
> java.lang.RuntimeException: Exception while getting value: private
> java.lang.String Names.Name_en
>        at
> org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.get(DocumentObjectBinder.java:377)
>        at
> org.apache.solr.client.solrj.beans.DocumentObjectBinder.toSolrInputDocument(DocumentObjectBinder.java:71)
>        at
> org.apache.solr.client.solrj.SolrServer.addBeans(SolrServer.java:56)
> ...
> Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String
> field Names.Name_en to TheBigOne
>        at
> sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
>        at
> sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
>        at
> sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:37)
>        at
> sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:18)
>        at java.lang.reflect.Field.get(Field.java:358)
>        at
> org.apache.solr.client.solrj.beans.DocumentObjectBinder$DocField.get(DocumentObjectBinder.java:374)
>        ... 7 more
> 
> My conclusion is that the @Field annotation can presently only be put in the
> main bean and nested beans are not supported. It seems that more more than a
> simple patch is required to rewrite how SolrJ collects document fields from
> nested beans.
> 
> Shall I go ahead and create a JIRA ticket with this information?
> 
> Best Regards,
> Peter
> 
> -- 
> View this message in context: http://lucene.472066.n3.nabble.com/Does-SolrJ-support-nested-annotated-beans-tp868375p868375.html
> Sent from the Solr - User mailing list archive at Nabble.com.
>