This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details

1. Accident Background

This story starts from an urgent need, the product ran, the business side of the order felt a little taste, to add a printing time, OK, there is no problem, it is a small change, but unexpected surprise happened!

Ii. Accident Scene

According to the customer service feedback, a group of people from the customer side called to say that the documents could not be printed, so they started an urgent problem investigation

  • The product has reached the battlefield
  • The project manager is 30 seconds away from the battlefield
  • The tech director will be in the field in 30 seconds
  • Heh heh heh heh heh heh

3. Positioning Problems

It was a minor change, and it went off like that. Through the log, I found such an error

Caused by: java.lang.IllegalArgumentException: argument type mismatch
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.inspireso.framework.util.Transform.copy(Transform.java:316)
        ... 2 more
Copy the code

The argument type mismatch is a reflection problem. The argument type mismatch is the transform.copy (transform.java :316)

Iv Code appreciation

private Map<String, Object> buildRuleVariables(EdiBooking booking) {
    Map<String, Object> vars = Maps.newHashMap();
    EdiBooking newBooking = new EdiBooking();
    Transform.copy(booking, newBooking);
    newBooking.setPrintedDate(new Date());
    vars.put("EIR", newBooking);
    return vars;
}
Copy the code

It’s a copy method. How do you make a bomb? What did he write in there

public static <TSource, TTarget> TTarget copy(TSource source, TTarget target, boolean ignoreNullValue, boolean ignoreCollectionProperty) { Preconditions.checkNotNull(source, "Source can not be null!" ); Preconditions.checkNotNull(target, "Target can not be null!" ); Class<? > actualEditable = target.getClass(); PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); PropertyDescriptor[] arr$ = targetPds; int len$ = targetPds.length; for(int i$ = 0; i$ < len$; ++i$) { PropertyDescriptor targetPd = arr$[i$]; if (targetPd.getWriteMethod() ! = null) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd ! = null && sourcePd.getReadMethod() ! = null && (! ignoreCollectionProperty || ! Collection.class.isAssignableFrom(sourcePd.getPropertyType())) && Sourcepd.getpropertytype ().isAssignableFrom(targetpd.getPropertyType ())) {try {// Get the Method of reading property readMethod = sourcePd.getReadMethod(); if (! Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source); if (value ! = null || ! ignoreNullValue) { readMethod = targetPd.getReadMethod(); if (! Objects.equal(value, readMethod.invoke(target))) { Method writeMethod = targetPd.getWriteMethod(); if (! Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); Invoke (target, value); // Invoke (target, value); } } } catch (Throwable var14) { throw new FatalBeanException("Could not copy properties from source to target", var14); } } } } return target; }Copy the code

Method readMethod = sourcePd.getReadMethod(); The getPrinted () method normally returns the attribute’s getPrinted () method, but isPrinted () returns a Boolean instead of an Integer, resulting in tragedy

Five culprits

public Integer getPrinted() { return printed; } public void setPrinted(Integer printed) { if (printed == null) { printed = 0; } this.printed = printed; } public boolean isPrinted() { if (this.getPrinted() == null) { return false; } else { return 1 == this.getPrinted(); }}Copy the code

Local debugging and verification

Public class TestEntity {public static void main(String[]) public static void main(String[]) args) { EdiBooking booking = new EdiBooking(); booking.setPrinted(1); booking.setAlarm(2); EdiBooking newBooking = new EdiBooking(); Transform.copy(booking, newBooking); newBooking.setPrintedDate(new Date()); System.out.println(JSON.toJSON(newBooking)); }}Copy the code

Vii Solutions

  • Beanutils.copyproperties (Booking, newBooking) does not return an error when using this method, but the printed property value is not found in the JSON serialization, so it is not acceptable

      {
          "useRule":"",
          "falsePrintFlag":0,
          "version":1,
          "printedDate":1620737758897,
          "sendCdStatus":0,
          "applyInvoiceStatus":0,
          "leak":0,
          "free":false,
          "printedType":0,
          "empty":false,
          "hold":false,
          "new":true,
          "remark":"",
          "lockStatus":0,
          "orgCode":"SUNISCO",
          "alarm":2,
          "emptyStatus":"F",
          "dangerFlag":false,
          "payStatus":0
      }
    Copy the code
  • Remove the isPrinted () method, and do not write the IS method in the power class property field

Eight epilogue

Remember, the entity class maps fields, so don’t write the IS method, or for some frameworks it might be confusing to know which method to use to get the value of the field, which is a living chestnut.