paymill/paymill-java

Null pointer exception when Serializing Transaction with a Refund

vladaspasic opened this issue · 7 comments

While trying to list all Transactions for a certain Client I got this NullPointerException.

This occurs when Jackson tries to serialize the Transaction that contains a Refund, that again contains a Transaction which does not have a responseCode property set.

When Jackson tries to access the getResponseCodeDetail method, from the Refunded transaction, this null value is compared and Java throws an Exception when unboxing the Integer value.

There should be a null check before these if checks to fix this issue.

Hi @vladaspasic

If I understand you correctly, the null pointer is thrown from getResponseCodeDetail(). Is that the case?

cheers

Hi @nikoloff

yes, that is the method.

Hi @vladaspasic
can you give me the stack trace. I can't see where the null pointer comes from.
If the method getResponseCode() returns null, the getResponseCodeDetail() will also returns null.

cheers

Hi @nikoloff

here is the stacktrace of the Exception:

java.lang.NullPointerException: null
    at com.paymill.models.Transaction.getResponseCodeDetail(Transaction.java:179) ~[paymill-java-5.1.0.jar:na]
    at gymcarry.de.api.controllers.PaymillController.findTransactions(PaymillController.java:73) ~[bin/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
    at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:776) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:858) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.0.23.jar:8.0.23]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843) ~[spring-webmvc-4.1.7.RELEASE.jar:4.1.7.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.0.23.jar:8.0.23]

As you can see the exception occurs on the first line in this method :

/**
   * Returns the response code as detailed message.
   * @return the message or <code>null</code> if no message is available.
   */
  public String getResponseCodeDetail() {
    if( getResponseCode() == 10001 ) {
      return "General undefined response";
    } else if( getResponseCode() == 10002 ) {...

Because the getResponseCode returns an Integer, which is not a primitive type, it's value needs to be unboxed to perform the comparison. When Java tries to unbox that value, it throws an Exception.

You can check the explanation here: http://stackoverflow.com/questions/3352791/why-comparing-integer-with-int-can-throw-nullpointerexception-in-java

fixed in v5.1.1.

thx @vladaspasic for the clarification about the java unboxing :)

Thank you @nikoloff

I have just updated the dependency, the error is gone, but I found a new one :(

Caused by: java.lang.NullPointerException: null
    at com.paymill.models.Transaction.isSuccessful(Transaction.java:269) ~[paymill-java-5.1.1.jar:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
    at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:466) ~[jackson-databind-2.4.6.jar:2.4.6]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:639) ~[jackson-databind-2.4.6.jar:2.4.6]
    ... 89 common frames omitted

It is the same problem like before, but in a different method, this one happens here:

  /**
   * Checks if the transaction was successful. Utility method, checks if the response_code is 20000.
   * @return true if successful, false otherwise
   */
  public boolean isSuccessful() {
    return getResponseCode() == 20000;
  }

Hi @vladaspasic

10x again for the report will deploy new fix today