@ Override public synchronized void complete ( ) { if ( com . ibm . ejs . ras . TraceComponent . isAnyTracingEnabled ( ) && logger . isLoggable ( Level . FINEST ) ) { logger . entering ( CLASS_NAME , "complete" , this ) ; } if ( ! lockHeldByDifferentThread ( ) ) { //We can't call this or WebContainer won't know to run the complete runnable which kicks off the async listeners // WebContainerRequestState.getInstance(true).setAsyncMode(false); if ( ! completePending ) { //Move this inside of if block because it complete is called //after a previous complete, you can get a NPE because the //request may have already been cleaned up. If complete is not //pending, then it shouldn't have been cleaned up. if ( com . ibm . ws . webcontainer . osgi . WebContainer . getServletContainerSpecLevel ( ) > 31 ) { //setAsyncStarted(false) upon exit service() WebContainerRequestState reqState = WebContainerRequestState . getInstance ( true ) ; reqState . setAttribute ( "webcontainer.resetAsyncStartedOnExit" , "true" ) ; } else { iExtendedRequest . setAsyncStarted ( false ) ; } createNewAsyncServletReeentrantLock ( ) ; cancelAsyncTimer ( ) ; completeRunnable = new CompleteRunnable ( iExtendedRequest , this ) ; completePending = true ; if ( ! dispatching ) { executeNextRunnable ( ) ; } } } else { if ( WCCustomProperties . THROW_EXCEPTION_WHEN_UNABLE_TO_COMPLETE_OR_DISPATCH ) { throw new IllegalStateException ( nls . getString ( "AsyncContext.lock.already.held" , "Unable to obtain the lock. Error processing has already been invoked by another thread." ) ) ; } } dispatchURI = null ; if ( com . ibm . ejs . ras . TraceComponent . isAnyTracingEnabled ( ) && logger . isLoggable ( Level . FINEST ) ) { logger . exiting ( CLASS_NAME , "complete" , this ) ; } }
we re okay to sync on the scheduling of the complete