-1

I have controller and service class (Spring and Hibernate 4). The controller class contains the getTransactionsForInternalUse method as shown below :

      @RequestMapping(value = "/internal/financials/transactions", method = RequestMethod.GET)
          @ResponseBody
          public ResponseEntity<SetRESTData<FinancialTransactionDTO>> getTransactionsForInternalUse(

            @RequestParam(value = "businessId", required = true) final String businessId,
            @RequestParam(value = "status", required = false) final String statusString,
            @RequestParam(value = "transactionMethod", required = false) final String transactionMethodString,
            @RequestParam(value = "sortBy", required = false) final String orderBy,
            @RequestParam(value = "sortDirection", required = false) final String sortDirectionString) {

            final FinancialTransactionStatus status = StringUtils.isBlank(statusString) ? null : FinancialTransactionStatus.fromCode(statusString);
            final FinancialTransactionMethod method =
              StringUtils.isBlank(transactionMethodString) ? null : FinancialTransactionMethod.fromCode(transactionMethodString);

            final FinancialTransactionPaginationData paginationData = StringUtils.isBlank(orderBy) ?
              null : new FinancialTransactionPaginationData(FinancialTransactionSortableField.fromCode(orderBy), null, null, sortDirectionString);

 //call to getTransactionsForEmployeeUse method 


            final ServiceResultDetails<Set<FinancialTransactionDTO>> resultsDetails =
   financialTransactionService.getTransactionsForEmployeeUse(businessId,status, method, paginationData);// Added business Id here
            final ResponseCode errorCode = resultsDetails.getErrorCode();
            if (errorCode != null) {
              return buildNoCacheNoCorsEmptySetRESTDataWithMessage(errorCode, resultsDetails.getErrorMessage());
            } else {
              return buildNoCacheSetRESTDataResponse(
                resultsDetails.getEntity(), ResponseCode.FINANCIAL_TRANSACTION_RETRIEVED, ResponseCode.FINANCIAL_TRANSACTION_NOT_FOUND, false);
            }
          }

And, getTransactionsForEmployeeUse method of FinancialTransactionService class is called using it's object financialTransactionService as shown above. The method of getTransactionsForEmployeeUse defined in FinancialTransactionService is as follows :

     @Transactional(value = TransactionManagerName.BUSINESS, readOnly = true)
      @TransactionalSecurity(employeeAccess = true)
      public ServiceResultDetails<Set<FinancialTransactionDTO>> getTransactionsForEmployeeUse(
              @NotBlank final String businessExternalId,
              final FinancialTransactionStatus status,
              final FinancialTransactionMethod method,
              final FinancialTransactionPaginationData paginationData) {
          final Business escrowProvider = businessService.getByExternalId(businessExternalId);
          final BusinessId escrowProviderId = escrowProvider.getId();
          final BusinessPartnership businessPartnership = businessPartnershipService.getPartnership(escrowProviderId);

//The below line is line #223 from the stacktrace and in the code
          if (!Boolean.TRUE.equals(businessPartnership.getEscrowProvider())) {
              return new ServiceResultDetails<>(ResponseCode.OPERATION_NOT_ALLOWED_FOR_NON_ESCROW_PROVIDERS);
          }
          final Set<FinancialAccount> accounts = financialAccountService.getAccountsAtHoldingPartner(escrowProviderId);
          final Map<FinancialAccountId, FinancialAccount> accountIdMap = entityHelper.buildIdEntityMap(accounts);
          final Set<FinancialTransaction> financialTransactions =
                  financialTransactionDAO.getAllTransactionsForEmployeeUse(status, method, paginationData);
          final Set<FinancialTransactionDTO> resultsAll = new LinkedHashSet<>(financialTransactions.size()); 
          for (final FinancialTransaction financialTransaction : financialTransactions) {
              if(financialTransaction instanceof InvestmentTransaction){
                  final FinancialAccountId fromEscrowAccountId = ((InvestmentTransaction) financialTransaction).getFromEscrowAccountId();
                  final FinancialAccount fromEscrowAccount = fromEscrowAccountId == null ? null : accountIdMap.get(fromEscrowAccountId);
                  if(fromEscrowAccount != null){
                      resultsAll.add(new FinancialTransactionDTO(financialTransaction,fromEscrowAccount));
                  }else{
                      resultsAll.add(new FinancialTransactionDTO(financialTransaction));
                  }
              }else {
                  resultsAll.add(new FinancialTransactionDTO(financialTransaction));
              }
          }
          return new ServiceResultDetails<>(resultsAll);    
      }

I have been getting this error for the past few days when I run an API Call (GET) using a REST client and before few days I wasn't getting this error.I haven't done any code changes and wondering what could be the problem. I tried debugging using Remote Java Application but couldn't see why NPE is thrown.The stacktrace is below:

1723:44.616 080-exec-3 LId:2001   PId:2001   r.SessionManagementInterceptor ERROR Uncaught exception from FinancialTransactionsController, getTransactionsForInternalUse
java.lang.NullPointerException
    at com.fp.investing.service.transaction.FinancialTransactionService.getTransactionsForEmployeeUse(FinancialTransactionService.java:223) ~[investing-api-1.0.13579.jar:13579]
    at com.fp.investing.service.transaction.FinancialTransactionService$$FastClassBySpringCGLIB$$dea301d.invoke(<generated>) ~[spring-core-4.2.0.RELEASE.jar:13579]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at com.fp.investing.service.transaction.FinancialTransactionService$$EnhancerBySpringCGLIB$$a21fc6da.getTransactionsForEmployeeUse(<generated>) ~[spring-core-4.2.0.RELEASE.jar:13579]
    at com.fp.investing.service.transaction.FinancialTransactionService$$FastClassBySpringCGLIB$$dea301d.invoke(<generated>) ~[spring-core-4.2.0.RELEASE.jar:13579]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at com.fp.core.tx.TransactionalSecurityInterceptor.invoke(TransactionalSecurityInterceptor.java:96) ~[core-api-1.0.13579.jar:13579]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) ~[spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at com.fp.investing.service.transaction.FinancialTransactionService$$EnhancerBySpringCGLIB$$9a68dac2.getTransactionsForEmployeeUse(<generated>) ~[spring-core-4.2.0.RELEASE.jar:13579]
    at com.fp.core.ws.financial.FinancialTransactionsController.getTransactionsForInternalUse(FinancialTransactionsController.java:78) ~[core-ws-1.0.13579.jar:13579]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_65]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_65]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_65]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[?:1.8.0_65]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111) ~[spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806) ~[spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729) ~[spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) [servlet-api.jar:?]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) [servlet-api.jar:?]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [catalina.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.30]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-websocket.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.30]
    at com.fp.core.ws.http.CORSFilter.doFilterInternal(CORSFilter.java:39) [core-ws-1.0.13579.jar:13579]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.30]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.30]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212) [catalina.jar:8.0.30]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.30]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.30]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) [catalina.jar:8.0.30]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.30]
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616) [catalina.jar:8.0.30]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.30]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:521) [catalina.jar:8.0.30]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1096) [tomcat-coyote.jar:8.0.30]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:674) [tomcat-coyote.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500) [tomcat-coyote.jar:8.0.30]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456) [tomcat-coyote.jar:8.0.30]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_65]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_65]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.30]
    at java.lang.Thread.run(Thread.java:745) [?:1.8.0_65]
John
  • 1,210
  • 5
  • 23
  • 51
  • Please at least mark (f.e. using a comment) where is line 223 in FinancialTransactionService (from stack trace)... – Betlista Jan 05 '16 at 05:33
  • @Betlista Done. Forgot to mention that. – John Jan 05 '16 at 05:37
  • Possible duplicate of [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it) – dimo414 Jan 05 '16 at 05:40
  • `businessPartnership` is null. – dimo414 Jan 05 '16 at 05:44
  • @dimo414 You are right, setting breakpoint on line #223 gave me businessPartnership as null. Is that the problem? – John Jan 05 '16 at 05:53

1 Answers1

1

Lets take a look at line 223:

if (!Boolean.TRUE.equals(businessPartnership.getEscrowProvider())) {

We know Boolean.TRUE cannot be null, since it's true. We also know that Boolean.equals() will return false if passed null, not raise a NullPointerException, so it wouldn't matter if businessPartnership.getEscrowProvider() returned null. The only remaining cause is businessPartnership. You cannot call methods on null, if you attempt to do so you will cause a NullPointerException. From the JLS:

A method invocation expression (§15.12) that invokes an instance method throws a NullPointerException if the target reference is null.

The canonical What is a NullPointerException, and how do I fix it? covers this in greater detail, but in essence you are missing some necessary sanity checks before this line. At line 223 you assume businessPartnership cannot be null, yet businessPartnershipService.getPartnership() returns null in some cases. Either ensure businessPartnershipService.getPartnership() never returns null, or add null-checks before calling businessPartnership.getEscrowProvider().

Community
  • 1
  • 1
dimo414
  • 47,227
  • 18
  • 148
  • 244