Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NPE caused by requests immediately following DELETE requests #91

Open
jpgorzny opened this issue Feb 15, 2024 · 0 comments
Open

NPE caused by requests immediately following DELETE requests #91

jpgorzny opened this issue Feb 15, 2024 · 0 comments
Labels
bug Something isn't working

Comments

@jpgorzny
Copy link
Contributor

jpgorzny commented Feb 15, 2024

Affected version
7.1.0 (according to #44 at least since 4.4.0)

Actual behavior
Using the generated ApiClient a request immediately following a DELETE request can result in jakarta.ws.rs.ProcessingException caused by a NPE to be thrown.

Whether the exception is thrown seems to depend on the elapsed time between requests, as a sleep between them reduces the probability. As a workaround (other than sleep) one could also use separate instances of the corresponding ServiceHandler for the DELETE request and its follow-up.

Expected behavior
Requests following a DELETE request should be processed successfully regardless of the time elapsed between requests or the use of the same or separate ServiceHandler instance.

To Reproduce
Steps to reproduce the behavior:

  1. Create an order (in order to create a customer)
  2. Delete the customer: OMSGDPRServiceHandler#deleteCustomer
  3. Get the customer: OMSGDPRServiceHandler#getCustomer (expecting ApiException with status code 404, but jakarta.ws.rs.ProcessingException caused by the NPE below could be thrown)

Note that the bug also affects other APIs providing endpoints with the DELETE option (e.g. Reservation Service).

Additional context

java.lang.NullPointerException: Cannot invoke "org.glassfish.grizzly.http.HttpRequestPacket.getProcessingState()" because the return value of "org.glassfish.grizzly.http.HttpClientFilter$ClientHttpResponseImpl.getRequest()" is null
	at org.glassfish.grizzly.http.HttpClientFilter$ClientHttpResponseImpl.getProcessingState(HttpClientFilter.java:644)
	at com.ning.http.client.providers.grizzly.HttpTransactionContext.currentTransaction(HttpTransactionContext.java:136)
	at com.ning.http.client.providers.grizzly.AhcEventFilter.onHttpHeaderError(AhcEventFilter.java:263)
	at org.glassfish.grizzly.http.HttpCodecFilter.handleRead(HttpCodecFilter.java:524)
	at org.glassfish.grizzly.http.HttpClientFilter.handleRead(HttpClientFilter.java:144)
	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:88)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:246)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:178)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:118)
	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:96)
	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:51)
	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:510)
	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:82)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:83)
	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:101)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)

Investigations
The payload of the DELETE request being null, as it should always be, appears to be the cause for this exception.
The generated ApiClient contains the following code snippet in sendRequest:

    } else if ("DELETE".equals(method)) {
      response = invocationBuilder.method("DELETE", entity);
    }

If SyncInvoker#method(String) instead of SyncInvoker#method(String, Entity<?>) was called, the exception would not be thrown.

Because the probability of the exception being thrown decreases with increasing time elapsed between requests, it seems that the erroneous state caused by the (intentionally) missing payload would be resolved asynchronously.

AB#93890

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant