[jira] [Commented] (SOLR-1945) Allow @Field annotations in nested classes using DocumentObjectBinder

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[jira] [Commented] (SOLR-1945) Allow @Field annotations in nested classes using DocumentObjectBinder

JIRA jira@apache.org

    [ https://issues.apache.org/jira/browse/SOLR-1945?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13607635#comment-13607635 ]

Mark S commented on SOLR-1945:
------------------------------


I thought I would just share workaround code until this issue is resolved.

The SolrMapperForSimplePojoList class should do the following:
* Simple List<?> -> Solr @Field Map -> Solr Document
* Solr Document -> Solr @Field Map ->  Simple List<?>

 ->

{code:java}
        List<ShoppingItem> shoppingItems = ...
{code}

 <- ->

{code:java}
public static class ShoppingList {

        @Field("id")
        private String id;

        @Field("shopping_items*")
        protected Map<String, Object> shoppingItemMap = new LinkedHashMap<String, Object>(16);
               
                // ...
}
{code}

{code:java}
public static class ShoppingItem {

        private Float quantity;

        private String product;

        private String description;
}
{code}


 <- ->

{code}
SolrInputDocument[
    id=1,
    shopping_items[0].quantity_f=1.0,
    shopping_items[0].product_s=25W SOLDERING IRON STARTER KIT WITH DMM,
    shopping_items[0].description_s=This kit contains everything needed for basic electronics work.,
    shopping_items[1].quantity_f=2.0,
    shopping_items[1].product_s=Standard Microphone Insert,
    shopping_items[1].description_s=Replacement electret mic inserts for tape recorders, etc,
    shopping_items[2].quantity_f=1.0,
    shopping_items[2].product_s=11 DIGIT FLUORO DISPLAY,
    shopping_items[2].description_s=Vacuum fluorescent display,
    shopping_items[3].quantity_f=1.0,
    shopping_items[3].product_s=LEAD FREE SOLDER 0.71MM 200G ROLL,
    shopping_items[3].description_s=99.3% tin, 0.7% copper lead-free.
]
{code}

 <-

Note*:  Also includes workaround ordering issue outlined here: https://issues.apache.org/jira/browse/SOLR-4422

                         
h2. The Workaround:  SolrMapperForSimplePojoList
{code:java}
package test;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * This will only work for a POJO that contains simple fields, such as String, Integer etc.
 * It will not work for complex field types such as a Collection, List, Map etc.
 *
 * This class exists because in SOLRJ @Field annotations cannot exist inside nested classes (Simple Types Only).
 *
 *
 * @see https://issues.apache.org/jira/browse/SOLR-1945
 * @author user
 *
 */
public class SolrMapperForSimplePojoList {

    private SolrMapperForSimplePojoList(){

    }

    public static <T> Map<String, Object> convertPojoListToSolrjDynamicFieldMap(
            List<T> pojoList, List<String> pojoFieldNames,
            List<String> solrjFieldNameTemplates  ) {

        try{

            Map<String, Object> solrjDynamicFieldMap = new LinkedHashMap<String, Object>();

            for (int pojoIndex = 0; pojoIndex < pojoList.size(); pojoIndex++) {

                T pojo = pojoList.get(pojoIndex);

                for (int pojoFieldNameIndex = 0; pojoFieldNameIndex < pojoFieldNames.size(); pojoFieldNameIndex++) {

                    String pojoFieldName = pojoFieldNames.get(pojoFieldNameIndex);
                    Object pojoFieldObject = getFieldValue(pojo, pojoFieldName);

                    solrjDynamicFieldMap.put(getSolrjFieldName(pojoIndex, solrjFieldNameTemplates.get(pojoFieldNameIndex) ), pojoFieldObject);
                }

            }

            return solrjDynamicFieldMap;
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }

    private static String getSolrjFieldName(Integer index, String solrjFieldNameTemplate ){
        StringBuffer solrjDynamicFieldName = new StringBuffer();

        solrjDynamicFieldName.append(solrjFieldNameTemplate.substring(0, solrjFieldNameTemplate.indexOf("[") + 1) );
        solrjDynamicFieldName.append(index);
        solrjDynamicFieldName.append(solrjFieldNameTemplate.substring(solrjFieldNameTemplate.indexOf("]")) );

        return solrjDynamicFieldName.toString();
    }

    private static Object getFieldValue(Object pojo, String pojoFieldName){


        try {

//          Field pojoField = pojo.getClass().getField(pojoFieldName);
//          pojoField.setAccessible(true);
//          Object pojoFieldObject = pojoField.get(pojo);

            Method method = pojo.getClass().getMethod("get" + pojoFieldName.substring(0, 1).toUpperCase() + pojoFieldName.substring(1));
            Object pojoFieldObject = method.invoke(pojo, (Object[]) null);
            return pojoFieldObject;
        } catch (Exception e) {
            // Ignore
        }
        return null;

    }


    /**
     * Unfortunately, the DocumentObjectBinder creates a HashMap for Map fields annotated with @Field, so order is lost.
     *
     * @see https://issues.apache.org/jira/browse/SOLR-4422
     *
     *
     * @see org.apache.solr.client.solrj.beans.DocumentObjectBinder
     *
     * @param solrjDynamicFieldMap
     * @param solrjFieldNameTemplates
     * @param pojoClass
     * @param pojoFieldNames
     * @return
     */
    public static <T> List<T> convertSolrjDynamicFieldMapToPojoList(
            Map<String, Object> solrjDynamicFieldMap, List<String> solrjFieldNameTemplates,
            Class<T> pojoClass, List<String> pojoFieldNames ){

        try{

            solrjDynamicFieldMap = getMapSortedByIndexValue(solrjDynamicFieldMap);

            List<T> pojoList = new ArrayList<T>();

            int pojoIndex = 0;
            T pojo = null;


            for (Map.Entry<String, Object> solrjDynamicFieldMapEntry : solrjDynamicFieldMap.entrySet()) {
                String solrjDynamicFieldMapEntryKey = solrjDynamicFieldMapEntry.getKey();
                Object solrjDynamicFieldMapEntryValue = solrjDynamicFieldMapEntry.getValue();


                Integer pojoIndexFound = extractIndexValue(solrjDynamicFieldMapEntryKey);

                if (pojoIndexFound == null){
                    // A non expected value. (Non-Collection value)
                    // Value accidentally picked up by @Field regex, such as "shopping_items_grouping_count_i"
                    continue;
                }


                if (pojoList.size() == 0){
                    pojo = pojoClass.newInstance();
                    pojoList.add(pojo);
                }

                if ( pojoIndexFound > pojoIndex ){
                    pojo = pojoClass.newInstance();
                    pojoList.add(pojo);
                    pojoIndex++;
                }


                for (int solrjFieldNameIndex = 0; solrjFieldNameIndex < solrjFieldNameTemplates.size(); solrjFieldNameIndex++) {

                    String solrFieldName = getSolrjFieldName(pojoIndex, solrjFieldNameTemplates.get(solrjFieldNameIndex) );

                    if (solrjDynamicFieldMapEntryKey.equals(solrFieldName)){
                        String pojoFieldName = pojoFieldNames.get(solrjFieldNameIndex);
                        setFieldValue(pojo, pojoFieldName, solrjDynamicFieldMapEntryValue);
                    }

                }


            }

            return pojoList;
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }

    private static Integer extractIndexValue( String value ){
        int pojoIndexStart = value.indexOf("[");
        int pojoIndexEnd = value.indexOf("]");

        if ( pojoIndexStart == -1 || pojoIndexEnd == -1 || pojoIndexStart >= pojoIndexEnd ){
            return null;
        }

        String indexStringValue =  value.substring(pojoIndexStart + 1, pojoIndexEnd );

        if (indexStringValue == null || indexStringValue.trim().length() == 0){
            return null;
        }

        try{
            return Integer.parseInt(indexStringValue);
        }catch(NumberFormatException e ){
            return null;
        }
    }

    private static void setFieldValue(Object pojo, String pojoFieldName, Object value){

        try {

//          Field pojoField = pojo.getClass().getField(pojoFieldName);
//          pojoField.setAccessible(true);
//          pojoField.set(pojo, solrjDynamicFieldMapEntryValue);

            Method method = pojo.getClass().getMethod("set" + pojoFieldName.substring(0, 1).toUpperCase() + pojoFieldName.substring(1), value.getClass() );
            method.invoke(pojo, value);
        } catch (Exception e) {
            // Ignore
        }

    }

    private static Map<String, Object> getMapSortedByIndexValue( Map<String, Object> unsortedMap ){

         final int BEFORE = -1;
//         final int SAME = 0;  // This will result in one value replacing the other..
         final int AFTER = 1;

         Comparator<String> comparator = new Comparator<String>() {
             public int compare(String s1, String s2) {


//              BEFORE: A negative number if s1 comes before s2;
//              AFTER:  A positive number if s1 comes after s2;
//              SAME:   0.  Only if you want to replace a value.

                 Integer s1IndexValue = extractIndexValue(s1);
                 Integer s2IndexValue = extractIndexValue(s2);

                 final int DEFAULT = BEFORE;

                 if (s1IndexValue == null && s2IndexValue == null) {
                     return DEFAULT;
                 } else if (s1IndexValue != null && s2IndexValue == null) {
                     return AFTER;
                 } else if (s1IndexValue == null && s2IndexValue != null) {
                     return BEFORE;
                 } else {

                     if  (s1IndexValue > s2IndexValue){
                         return AFTER;
                     }else if (s1IndexValue < s2IndexValue){
                         return BEFORE;
                     }else{
                         return DEFAULT;
                     }
                 }
             }
         };
         SortedSet<String> sortedSet = new TreeSet<String>(comparator);
         sortedSet.addAll(unsortedMap.keySet());

         Map<String, Object> sortedMap = new LinkedHashMap<String, Object>();
         for (String key : sortedSet) {
             sortedMap.put(key, unsortedMap.get(key));
         }

         return sortedMap;

    }

}

{code}


h2. The Test class:  SolrMapperForSimplePojoListTest
{code:java}
package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.beans.DocumentObjectBinder;
import org.apache.solr.client.solrj.beans.Field;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.client.solrj.util.ClientUtils;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.SolrInputField;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import test.HttpSolrServerTestSupport;

public class SolrMapperForSimplePojoListTest {

    private static SolrTestClient solrTestClient = new SolrHttpTestClient();
//    private static SolrTestClient solrTestClient = new SolrMockTestClient();

    private List<ShoppingItem> getDefaultShoppingItems() {
        return Arrays.asList(
                new ShoppingItem(1F, "25W SOLDERING IRON STARTER KIT WITH DMM", "This kit contains everything needed for basic electronics work."),
                new ShoppingItem(2F, "Standard Microphone Insert", "Replacement electret mic inserts for tape recorders, etc"),
                new ShoppingItem(1F, "11 DIGIT FLUORO DISPLAY", "Vacuum fluorescent display"),
                new ShoppingItem(1F, "LEAD FREE SOLDER 0.71MM 200G ROLL", "99.3% tin, 0.7% copper lead-free.")
                );
    }


    private ShoppingList getDefaultShoppingList() {

        ShoppingList shoppingList = new ShoppingList();
        shoppingList.setId("1");
        List<ShoppingItem> shoppingItems = getDefaultShoppingItems();
        ShoppingItemMapper.setShoppingListItems(shoppingList, shoppingItems);

        return shoppingList;

    }

    private SolrInputDocument getDefaultShoppingListSolrInputDocument() {

        SolrInputDocument solrInputDocument = new SolrInputDocument();

        solrInputDocument.addField("id", "1");
        solrInputDocument.addField("shopping_items[0].quantity_f", 1.0F);
        solrInputDocument.addField("shopping_items[0].product_s", "25W SOLDERING IRON STARTER KIT WITH DMM");
        solrInputDocument.addField("shopping_items[0].description_s", "This kit contains everything needed for basic electronics work.");
        solrInputDocument.addField("shopping_items[1].quantity_f", 2.0F);
        solrInputDocument.addField("shopping_items[1].product_s", "Standard Microphone Insert");
        solrInputDocument.addField("shopping_items[1].description_s", "Replacement electret mic inserts for tape recorders ,etc");
        solrInputDocument.addField("shopping_items[2].quantity_f", 1.0F);
        solrInputDocument.addField("shopping_items[2].product_s", "11 DIGIT FLUORO DISPLAY");
        solrInputDocument.addField("shopping_items[2].description_s", "Vacuum fluorescent display");
        solrInputDocument.addField("shopping_items[3].quantity_f", 1.0F);
        solrInputDocument.addField("shopping_items[3].product_s", "LEAD FREE SOLDER 0.71MM 200G ROLL");
        solrInputDocument.addField("shopping_items[3].description_s", "99.3% tin, 0.7% copper lead-free.");

        return solrInputDocument;

    }

    @Before
    public void setUp() throws Exception {
        solrTestClient.deleteById("1");
    }


    @After
    public void tearDown() throws Exception {
        solrTestClient.deleteById("1");
    }

    @Test
    public void testSaveAndRetrieve() throws Exception {

        ShoppingList shoppingListIn = getDefaultShoppingList();
        ShoppingList shoppingListOut = solrTestClient.saveAndRetrieve(ShoppingList.class, shoppingListIn, true);

        Assert.assertEquals(shoppingListIn.getId(), shoppingListOut.getId());

        Assert.assertEquals(
                ShoppingItemMapper.getShoppingListItems(shoppingListIn).toString(),
                ShoppingItemMapper.getShoppingListItems(shoppingListOut).toString());

        // https://issues.apache.org/jira/browse/SOLR-4422
        Assert.assertFalse(
                String.valueOf(shoppingListIn.getShoppingItemMap()).equals(
                String.valueOf(shoppingListOut.getShoppingItemMap())));

        System.out.println("shoppingListIn[" + String.valueOf(shoppingListIn.getShoppingItemMap()) + "]");
        System.out.println("shoppingListOut[" +String.valueOf(shoppingListOut.getShoppingItemMap()) + "]");

        Assert.assertFalse(
                String.valueOf(String.valueOf(shoppingListIn.getShoppingItemMap())).equals(
                String.valueOf(String.valueOf(shoppingListOut.getShoppingItemMap()))));


        Assert.assertFalse(shoppingListIn.toString().equals(shoppingListOut.toString()));
    }

    @Test
    public void testDetailedMapperOrdering() throws Exception {

        SolrInputDocument solrInputDocument = getDefaultShoppingListSolrInputDocument();
        StringBuffer solrInputDocumentString = new StringBuffer();

        {
            for (Map.Entry<String, SolrInputField> solrInputDocumentMapEntry : solrInputDocument.entrySet()) {

                if ("id".equals(solrInputDocumentMapEntry.getKey())) {
                    continue;
                }

                solrInputDocumentString.append(solrInputDocumentMapEntry.getKey())
                    .append("=\"").append(solrInputDocumentMapEntry.getValue().getValue()).append("\", ");
            }
        }


        // RELOAD
        ShoppingList shoppingListOut = solrTestClient.saveAndRetrieve(ShoppingList.class, solrInputDocument, true);

        List<ShoppingItem> shoppingItemsOut = ShoppingItemMapper.getShoppingListItems(shoppingListOut);
        StringBuffer shoppingItemsOutString = new StringBuffer();

        {
            for (int i = 0; i < shoppingItemsOut.size(); i++) {

                ShoppingItem shoppingItem = shoppingItemsOut.get(i);

                // This order is defined in ShoppingItemMapper
                // Note:  Arrays.asList("quantity", "product", "description")

                shoppingItemsOutString.append("shopping_items[" + i + "].quantity_f")
                    .append("=\"").append(shoppingItem.getQuantity()).append("\", ");

                shoppingItemsOutString.append("shopping_items[" + i + "].product_s")
                    .append("=\"").append(shoppingItem.getProduct()).append("\", ");

                shoppingItemsOutString.append("shopping_items[" + i + "].description_s")
                    .append("=\"").append(shoppingItem.getDescription()).append("\", ");
            }
        }


        Assert.assertEquals(solrInputDocumentString.toString(), shoppingItemsOutString.toString());

    }


//    private static void assertTrue(Boolean value) {
//        if (value == null || !value) {
//            throw new AssertionError();
//        }
//    }
//
//    private static void assertEquals(Object expected, Object actual) {
//        if (expected == null && actual == null) {
//            return;
//        }
//
//        if (expected == null && actual != null) {
//            throw new AssertionError();
//        }
//
//        if (!expected.equals(actual)) {
//            throw new AssertionError();
//        }
//    }


    public static class ShoppingList {

        @Field("id")
        private String id;

        @Field("shopping_items*")
        protected Map<String, Object> shoppingItemMap = new LinkedHashMap<String, Object>(16);

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public Map<String, Object> getShoppingItemMap() {
            return shoppingItemMap;
        }

        public void setShoppingItemMap(Map<String, Object> shoppingItemMap) {
            this.shoppingItemMap = shoppingItemMap;
        }

        @Override
        public String toString() {
            return "ShoppingList [id=" + id + ", shoppingItemMap=" + shoppingItemMap + "]";
        }

    }

    public static class ShoppingItem {

        private Float quantity;

        private String product;

        private String description;


        public ShoppingItem(){

        }

        public ShoppingItem(Float quantity, String product, String description) {
            super();
            this.quantity = quantity;
            this.product = product;
            this.description = description;
        }

        public Float getQuantity() {
            return quantity;
        }

        public void setQuantity(Float quantity) {
            this.quantity = quantity;
        }

        public String getProduct() {
            return product;
        }

        public void setProduct(String product) {
            this.product = product;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        @Override
        public String toString() {
            return "ShoppingItem [quantity=" + quantity + ", product=" + product + ", description=" + description + "]";
        }

    }

    public static class ShoppingItemMapper {

        public static void setShoppingListItems(ShoppingList shoppingList, List<ShoppingItem> shoppingItems) {

            Map<String, Object> solrjDynamicFieldMap = SolrMapperForSimplePojoList.convertPojoListToSolrjDynamicFieldMap(
                    shoppingItems, Arrays.asList("quantity", "product", "description"),
                    Arrays.asList("shopping_items[].quantity_f", "shopping_items[].product_s", "shopping_items[].description_s"));

            shoppingList.setShoppingItemMap(solrjDynamicFieldMap);
        }

        public static List<ShoppingItem> getShoppingListItems(ShoppingList shoppingList) {

            Map<String, Object> solrjDynamicFieldMap = shoppingList.getShoppingItemMap();
            Assert.assertTrue(solrjDynamicFieldMap != null);

            List<ShoppingItem> shoppingItems = SolrMapperForSimplePojoList.convertSolrjDynamicFieldMapToPojoList(
                solrjDynamicFieldMap, Arrays.asList("shopping_items[].quantity_f", "shopping_items[].product_s", "shopping_items[].description_s") ,
                ShoppingItem.class, Arrays.asList("quantity", "product", "description") );

            return shoppingItems;
        }
    }

    public static interface SolrTestClient {

        public void deleteById(String id) throws Exception;

        public <T> T saveAndRetrieve(Class<T> type, T beanIn, boolean shuffleSolrInputFields) throws Exception;

        public <T> T saveAndRetrieve(Class<T> type, SolrInputDocument solrInputDocument, boolean shuffleSolrInputFields) throws Exception;
    }

    public static class SolrHttpTestClient implements SolrTestClient {

        private static HttpSolrServer server = HttpSolrServerTestSupport.getInstance().getServer();

        public void deleteById(String id) throws Exception {

             UpdateResponse updateResponse = server.deleteById(id);
             Assert.assertEquals(0, updateResponse.getStatus());

             server.commit();
        }

        public <T> T saveAndRetrieve(Class<T> type, T beanIn, boolean shuffleSolrInputFields) throws Exception {

            String docId = null;

            if (ShoppingList.class.isAssignableFrom(type)) {
                docId = ((ShoppingList) beanIn).getId();
            }

            if (docId == null) {
                return null;
            }

            UpdateResponse updateResponse = server.addBean(beanIn);
            Assert.assertEquals(0, updateResponse.getStatus());
            server.commit();

            return getBeanById(type, docId);

        }

        public <T> T saveAndRetrieve(Class<T> type, SolrInputDocument solrInputDocument, boolean shuffleSolrInputFields) throws Exception {

            String docId = String.valueOf(solrInputDocument.get("id").getValue());

            UpdateResponse updateResponse = server.add(solrInputDocument);
            Assert.assertEquals(0, updateResponse.getStatus());
            server.commit();

            return getBeanById(type, docId);
        }

        private <T> T getBeanById(Class<T> type, String id) throws Exception {

            SolrQuery solrQuery = new SolrQuery();
            solrQuery.setQuery("*:*");
            solrQuery.addFilterQuery("id:" + id);
            QueryResponse queryResponse = server.query(solrQuery);
            Assert.assertEquals(0, queryResponse.getStatus());

            List<T> beanOutList = queryResponse.getBeans(type);

            if (beanOutList == null || beanOutList.size() == 0) {
                return null;
            }

            T beanOut = beanOutList.get(0);

            return beanOut;
        }

    }

    public static class SolrMockTestClient implements SolrTestClient {


        public void deleteById(String id) throws Exception {
            // Do nothing - in memory only
        }

        /**
         * Should return the same results as using a Solr instance directly.
         *
         * @param solrInputDocument
         * @return
         */
        public <T> T saveAndRetrieve(Class<T> type, T beanIn, boolean shuffleSolrInputFields) {

            DocumentObjectBinder documentObjectBinder = new DocumentObjectBinder();

            // Store Pojo

            SolrInputDocument solrInputDocument = documentObjectBinder.toSolrInputDocument(beanIn);

            /*
             * SolrInputDocument[
             *     id=1,
             *     shopping_items[0].quantity_f=1.0,
             *     shopping_items[0].product_s=25W SOLDERING IRON STARTER KIT WITH DMM,
             *     shopping_items[0].description_s=This kit contains everything needed for basic electronics work.,
             *     shopping_items[1].quantity_f=2.0,
             *     shopping_items[1].product_s=Standard Microphone Insert,
             *     shopping_items[1].description_s=Replacement electret mic inserts for tape recorders, etc,
             *     shopping_items[2].quantity_f=1.0,
             *     shopping_items[2].product_s=11 DIGIT FLUORO DISPLAY,
             *     shopping_items[2].description_s=Vacuum fluorescent display,
             *     shopping_items[3].quantity_f=1.0,
             *     shopping_items[3].product_s=LEAD FREE SOLDER 0.71MM 200G ROLL,
             *     shopping_items[3].description_s=99.3% tin, 0.7% copper lead-free.]
             *
             *
             */

            // Retrieve Pojo
//            SolrDocument solrDocument = ClientUtils.toSolrDocument(solrInputDocument); // (Slightly Mocked)
//            T beanOut = documentObjectBinder.getBean(type, solrDocument);

            T beanOut = saveAndRetrieve(type, solrInputDocument, shuffleSolrInputFields);

            return beanOut;
        }

        public <T> T saveAndRetrieve(Class<T> type, SolrInputDocument solrInputDocument, boolean shuffleSolrInputFields) {

            DocumentObjectBinder documentObjectBinder = new DocumentObjectBinder();

            SolrDocument solrDocument;

            if (shuffleSolrInputFields) {
                // Shuffle
                // Unfortunately, the DocumentObjectBinder creates a HashMap for Map fields annotated with @Field, so order is lost.
                // https://issues.apache.org/jira/browse/SOLR-4422
                // Replicate this behaviour below.

                SolrInputDocument solrInputDocumentShuffled = new SolrInputDocument();
                {
                    List<SolrInputField> solrInputFieldList = new ArrayList<SolrInputField>(solrInputDocument.values());

                    long seed = System.nanoTime();
                    Collections.shuffle(solrInputFieldList, new Random(seed));

                    for (SolrInputField solrInputField : solrInputFieldList) {
                        solrInputDocumentShuffled.addField(solrInputField.getName(), solrInputField.getValue());
                    }
                }

                solrDocument = ClientUtils.toSolrDocument(solrInputDocumentShuffled); // (Slightly Mocked)
            } else {
                solrDocument = ClientUtils.toSolrDocument(solrInputDocument); // (Slightly Mocked)
            }


            T beanOut = documentObjectBinder.getBean(type, solrDocument);

            return beanOut;

        }

    }
}

{code}

               

> Allow @Field annotations in nested classes using DocumentObjectBinder
> ---------------------------------------------------------------------
>
>                 Key: SOLR-1945
>                 URL: https://issues.apache.org/jira/browse/SOLR-1945
>             Project: Solr
>          Issue Type: Improvement
>            Reporter: Mark Miller
>            Priority: Minor
>         Attachments: SOLR-1945.patch
>
>
> see http://search.lucidimagination.com/search/document/d909d909420aeb4e/does_solrj_support_nested_annotated_beans
> Would be nice to be able to pass an object graph to solrj with @field annotations rather than just a top level class

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]