Add new pointcut: PROCESSING_COMPLETED

This commit is contained in:
James Agnew 2019-07-09 14:32:11 -04:00
parent e50caaa899
commit 0fb8db11a2
4 changed files with 62 additions and 3 deletions

View File

@ -448,6 +448,45 @@ public enum Pointcut {
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails" "ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"
), ),
/**
* <b>Server Hook:</b>
* This method is called after all processing is completed for a request, regardless of whether
* the request completed successfully or not. It is called after {@link #SERVER_PROCESSING_COMPLETED_NORMALLY}
* in the case of successful operations.
* <p>
* Hooks may accept the following parameters:
* <ul>
* <li>
* ca.uhn.fhir.rest.api.server.RequestDetails - A bean containing details about the request that is about to be processed, including details such as the
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
* pulled out of the servlet request.
* </li>
* <li>
* ca.uhn.fhir.rest.server.servlet.ServletRequestDetails - A bean containing details about the request that is about to be processed, including details such as the
* resource type and logical ID (if any) and other FHIR-specific aspects of the request which have been
* pulled out of the request. This will be null if the server is not deployed to a RestfulServer environment.
* </li>
* </ul>
* </p>
* <p>
* This method must return <code>void</code>
* </p>
* <p>
* This method should not throw any exceptions. Any exception that is thrown by this
* method will be logged, but otherwise not acted upon (i.e. even if a hook method
* throws an exception, processing will continue and other interceptors will be
* called). Therefore it is considered a bug to throw an exception from hook methods using this
* pointcut.
* </p>
*/
SERVER_PROCESSING_COMPLETED(
void.class,
new ExceptionHandlingSpec()
.addLogAndSwallow(Throwable.class),
"ca.uhn.fhir.rest.api.server.RequestDetails",
"ca.uhn.fhir.rest.server.servlet.ServletRequestDetails"
),
/** /**
* Invoked whenever a persisted resource has been modified and is being submitted to the * Invoked whenever a persisted resource has been modified and is being submitted to the
* subscription processing pipeline. This method is called before the resource is placed * subscription processing pipeline. This method is called before the resource is placed
@ -1442,7 +1481,9 @@ public enum Pointcut {
* This pointcut is used only for unit tests. Do not use in production code as it may be changed or * This pointcut is used only for unit tests. Do not use in production code as it may be changed or
* removed at any time. * removed at any time.
*/ */
TEST_RO(BaseServerResponseException.class, String.class.getName(), String.class.getName()); TEST_RO(BaseServerResponseException.class, String.class.getName(), String.class.getName())
;
private final List<String> myParameterTypes; private final List<String> myParameterTypes;
private final Class<?> myReturnType; private final Class<?> myReturnType;

View File

@ -58,6 +58,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.servlet.Servlet;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.UnavailableException; import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
@ -1085,6 +1086,13 @@ public class RestfulServer extends HttpServlet implements IRestfulServer<Servlet
*/ */
DEFAULT_EXCEPTION_HANDLER.handleException(requestDetails, exception, theRequest, theResponse); DEFAULT_EXCEPTION_HANDLER.handleException(requestDetails, exception, theRequest, theResponse);
} finally {
HookParams params = new HookParams();
params.add(RequestDetails.class, requestDetails);
params.addIfMatchesType(ServletRequestDetails.class, requestDetails);
myInterceptorService.callHooks(Pointcut.SERVER_PROCESSING_COMPLETED, params);
} }
} }

View File

@ -78,7 +78,7 @@ public class InterceptorUserDataMapDstu2Test {
IOUtils.closeQuietly(status.getEntity().getContent()); IOUtils.closeQuietly(status.getEntity().getContent());
ourLog.info(myMapCheckMethods.toString()); ourLog.info(myMapCheckMethods.toString());
assertThat(myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "preProcessOutgoingException", "handleException")); assertThat(myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "preProcessOutgoingException", "handleException", "processingCompleted"));
} }
@Test @Test
@ -96,7 +96,7 @@ public class InterceptorUserDataMapDstu2Test {
} }
ourLog.info(myMapCheckMethods.toString()); ourLog.info(myMapCheckMethods.toString());
assertThat(myMapCheckMethods.toString(), myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "outgoingResponse", "processingCompletedNormally")); assertThat(myMapCheckMethods.toString(), myMapCheckMethods, contains("incomingRequestPostProcessed", "incomingRequestPreHandled", "outgoingResponse", "processingCompletedNormally", "processingCompleted"));
} }
private void updateMapUsing(Map<Object, Object> theUserData, String theMethod) { private void updateMapUsing(Map<Object, Object> theUserData, String theMethod) {
@ -256,6 +256,12 @@ public class InterceptorUserDataMapDstu2Test {
updateMapUsing(theServletRequestDetails.getUserData(), "processingCompletedNormally"); updateMapUsing(theServletRequestDetails.getUserData(), "processingCompletedNormally");
} }
@Hook(Pointcut.SERVER_PROCESSING_COMPLETED)
public void processingCompleted(RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
updateMapUsing(theRequestDetails.getUserData(), "processingCompleted");
updateMapUsing(theServletRequestDetails.getUserData(), "processingCompleted");
}
@Hook(Pointcut.SERVER_PRE_PROCESS_OUTGOING_EXCEPTION) @Hook(Pointcut.SERVER_PRE_PROCESS_OUTGOING_EXCEPTION)
public void preProcessOutgoingException(RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) { public void preProcessOutgoingException(RequestDetails theRequestDetails, ServletRequestDetails theServletRequestDetails) {
updateMapUsing(theRequestDetails.getUserData(), "preProcessOutgoingException"); updateMapUsing(theRequestDetails.getUserData(), "preProcessOutgoingException");

View File

@ -262,6 +262,10 @@
socket timeout settings to client requests. Thanks to Petro Mykhailyshyn socket timeout settings to client requests. Thanks to Petro Mykhailyshyn
for the pull request! for the pull request!
</action> </action>
<action type="add">
A new server interceptor hook called PROCESSING_COMPLETED has been added. This
hook is called by the server at the end of processing every request (success and failure).
</action>
</release> </release>
<release version="3.8.0" date="2019-05-30" description="Hippo"> <release version="3.8.0" date="2019-05-30" description="Hippo">
<action type="fix"> <action type="fix">