SOLRJ-6.0.0: Insertion of a bean object which associate list of bean object is giving null pointer exception

爱⌒轻易说出口 提交于 2019-11-29 05:09:33

Insertion of a bean object which associates list of bean is working as expected now.

Finally after looking the solrj6.0.0 source code, I found the way to resolve it. Actually there is a bug in solrj6.0.0. That is: If we are giving @Field annotation at set method in Employee2 bean as below:

/**
     * @param technologies2 the technologies2 to set
     */
    @Field (child = true)
    public void setTechnologies2(Collection<Technology2> technologies2) {
        this.technologies2 = technologies2;
    }

Then it is causing exception for our Employee2 bean insertion which aggregates list of technologies. It seems to be a bug from sorlj code as:

Nested DocField class of DocumentObjectBinder has below implemention:

public DocField(AccessibleObject member) {
      if (member instanceof java.lang.reflect.Field) {
        field = (java.lang.reflect.Field) member;
      } else {
        setter = (Method) member;
      }
      annotation = member.getAnnotation(Field.class);
      storeName(annotation);
      storeType();

      // Look for a matching getter
      if (setter != null) {
        String gname = setter.getName();
        if (gname.startsWith("set")) {
          gname = "get" + gname.substring(3);
          try {
            getter = setter.getDeclaringClass().getMethod(gname, (Class[]) null);
          } catch (Exception ex) {
            // no getter -- don't worry about it...
            if (type == Boolean.class) {
              gname = "is" + setter.getName().substring(3);
              try {
                getter = setter.getDeclaringClass().getMethod(gname, (Class[]) null);
              } catch(Exception ex2) {
                // no getter -- don't worry about it...
              }
            }
          }
        }
      }
    }

As we annotated @Field (child = true) at the setter hence here in this case field is null which is causing null pointer exception by storeType() method

private void storeType() {
      if (field != null) {
        type = field.getType();
      } else {
        Class[] params = setter.getParameterTypes();
        if (params.length != 1) {
          throw new BindingException("Invalid setter method. Must have one and only one parameter");
        }
        type = params[0];
      }

      if (type == Collection.class || type == List.class || type == ArrayList.class) {
        isList = true;
        if (annotation.child()) {
          populateChild(field.getGenericType());
        } else {
          type = Object.class;
        }
      } else if (type == byte[].class) {
        //no op
      } else if (type.isArray()) {
        isArray = true;
        if (annotation.child()) {
          populateChild(type.getComponentType());
        } else {
          type = type.getComponentType();
        }
      } else if (type == Map.class || type == HashMap.class) { //corresponding to the support for dynamicFields
        if (annotation.child()) throw new BindingException("Map should is not a valid type for a child document");
        isContainedInMap = true;
        //assigned a default type
        type = Object.class;
        if (field != null) {
          if (field.getGenericType() instanceof ParameterizedType) {
            //check what are the generic values
            ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
            Type[] types = parameterizedType.getActualTypeArguments();
            if (types != null && types.length == 2 && types[0] == String.class) {
              //the key should always be String
              //Raw and primitive types
              if (types[1] instanceof Class) {
                //the value could be multivalued then it is a List, Collection, ArrayList
                if (types[1] == Collection.class || types[1] == List.class || types[1] == ArrayList.class) {
                  type = Object.class;
                  isList = true;
                } else {
                  //else assume it is a primitive and put in the source type itself
                  type = (Class) types[1];
                }
              } else if (types[1] instanceof ParameterizedType) { //Of all the Parameterized types, only List is supported
                Type rawType = ((ParameterizedType) types[1]).getRawType();
                if (rawType == Collection.class || rawType == List.class || rawType == ArrayList.class) {
                  type = Object.class;
                  isList = true;
                }
              } else if (types[1] instanceof GenericArrayType) { //Array types
                type = (Class) ((GenericArrayType) types[1]).getGenericComponentType();
                isArray = true;
              } else { //Throw an Exception if types are not known
                throw new BindingException("Allowed type for values of mapping a dynamicField are : " +
                    "Object, Object[] and List");
              }
            }
          }
        }
      } else {
        if (annotation.child()) {
          populateChild(type);
        }
      }
    }

So as of now I am annotating @Field annotation at field level rather than at setter:

 @Field (child = true)
    private Collection<Technology2> technologies2;

So now insertion of such bean is successful, on retrieving I am getting below result as expected:

Employee2 [id=E3, name=KzWhg, designation=aTDiu, salary=190374.70126209356, totalExperience=2.0293696897450584, technologies2=[Technology2 [id=0T3, name=nxTdufv, experience=46, certified=false, content_type=technology2]Technology2 [id=1T3, name=waSMXpf, experience=26, certified=false, content_type=technology2]Technology2 [id=2T3, name=jqNbZZr, experience=30, certified=true, content_type=technology2]Technology2 [id=3T3, name=VnidjyI, experience=21, certified=true, content_type=technology2]Technology2 [id=4T3, name=ulGnHFm, experience=33, certified=false, content_type=technology2]Technology2 [id=5T3, name=cpUfgrY, experience=21, certified=false, content_type=technology2]], content_type=employee2] Employee2 [id=E4, name=xeKOY, designation=WfPSm, salary=169700.53869292728, totalExperience=22.047282596410284, technologies2=[Technology2 [id=0T4, name=rleygcW, experience=30, certified=true, content_type=technology2]Technology2 [id=1T4, name=yxjHrxV, experience=27, certified=false, content_type=technology2]Technology2 [id=2T4, name=czjHAEE, experience=31, certified=false, content_type=technology2]Technology2 [id=3T4, name=RDhoIJw, experience=22, certified=false, content_type=technology2]Technology2 [id=4T4, name=UkbldDN, experience=19, certified=false, content_type=technology2]], content_type=employee2] Employee2 [id=E5, name=tIWuY, designation=WikuL, salary=41462.47225086359, totalExperience=13.407976384902403, technologies2=[Technology2 [id=0T5, name=CDCMunq, experience=6, certified=false, content_type=technology2]Technology2 [id=1T5, name=NmkADyB, experience=31, certified=false, content_type=technology2]Technology2 [id=2T5, name=IhXnLfc, experience=9, certified=true, content_type=technology2]], content_type=employee2] Employee2 [id=E6, name=YluDp, designation=EtFqG, salary=159724.66206009954, totalExperience=26.26819742766281, technologies2=[Technology2 [id=0T6, name=mFvKDIK, experience=33, certified=false, content_type=technology2]Technology2 [id=1T6, name=arTNoHj, experience=44, certified=true, content_type=technology2]Technology2 [id=2T6, name=KYMseTW, experience=34, certified=false, content_type=technology2]Technology2 [id=3T6, name=ZTphSVn, experience=13, certified=true, content_type=technology2]], content_type=employee2] Employee2 [id=E7, name=qMkKG, designation=SQHCo, salary=111861.53447042785, totalExperience=13.29234679211927, technologies2=[Technology2 [id=0T7, name=PTKxjFl, experience=23, certified=false, content_type=technology2]Technology2 [id=1T7, name=gJfxbto, experience=17, certified=true, content_type=technology2]Technology2 [id=2T7, name=eekPYPN, experience=40, certified=true, content_type=technology2]Technology2 [id=3T7, name=aRdsEag, experience=40, certified=true, content_type=technology2]Technology2 [id=4T7, name=loDFVyM, experience=40, certified=true, content_type=technology2]Technology2 [id=5T7, name=xPXNaDV, experience=0, certified=false, content_type=technology2]], content_type=employee2] Employee2 [id=E8, name=WyNsf, designation=TtanH, salary=107942.13641940584, totalExperience=47.036469485140984, technologies2=[Technology2 [id=0T8, name=kakGXqh, experience=14, certified=true, content_type=technology2]Technology2 [id=1T8, name=ugwgdHy, experience=9, certified=true, content_type=technology2]Technology2 [id=2T8, name=rNzwcdQ, experience=31, certified=false, content_type=technology2]Technology2 [id=3T8, name=ZBXUhuB, experience=6, certified=true, content_type=technology2]], content_type=employee2] Employee2 [id=E9, name=EzuLC, designation=IXYGj, salary=133064.4485190016, totalExperience=16.075378097234232, technologies2=[Technology2 [id=0T9, name=GmvOUWp, experience=5, certified=true, content_type=technology2]Technology2 [id=1T9, name=ZWyvRxk, experience=24, certified=false, content_type=technology2]Technology2 [id=2T9, name=uWkTrfB, experience=5, certified=false, content_type=technology2]Technology2 [id=3T9, name=NFknqJj, experience=29, certified=true, content_type=technology2]], content_type=employee2] Employee2 [id=E10, name=quFKB, designation=eUoBJ, salary=198332.3270496455, totalExperience=14.035578311712438, technologies2=[Technology2 [id=0T10, name=MOXduwi, experience=49, certified=false, content_type=technology2]Technology2 [id=1T10, name=LpXGRvn, experience=28, certified=false, content_type=technology2]Technology2 [id=2T10, name=QeAOjIp, experience=3, certified=true, content_type=technology2]Technology2 [id=3T10, name=aVxGhOV, experience=34, certified=true, content_type=technology2]Technology2 [id=4T10, name=fbSaBUm, experience=42, certified=true, content_type=technology2]], content_type=employee2]

I have raised the code defect in JIRA: https://issues.apache.org/jira/browse/SOLR-9112

Even Solrj Code does not support insertion of multiple children as a bean. It gives the Exception: multiple child not supported. However by other way, insertion of a Bean which aggregates multiple bean can be inserted/indexed by SolrInput class.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!