*/
public interface IServerInterceptor {
/**
- * This method is called upon any exception being thrown within the server's request processing code. This includes any exceptions thrown within resource provider methods (e.g. {@link Search} and
- * {@link Read} methods) as well as any runtime exceptions thrown by the server itself. This also includes any {@link AuthenticationException}s thrown.
+ * This method is called upon any exception being thrown within the server's request processing code. This includes
+ * any exceptions thrown within resource provider methods (e.g. {@link Search} and {@link Read} methods) as well as
+ * any runtime exceptions thrown by the server itself. This also includes any {@link AuthenticationException}s
+ * thrown.
*
- * Implementations of this method may choose to ignore/log/count/etc exceptions, and return true. In this case, processing will continue, and the server will automatically generate an
- * {@link BaseOperationOutcome OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they should return false, to indicate that
- * they have handled the request and processing should stop.
+ * Implementations of this method may choose to ignore/log/count/etc exceptions, and return true. In
+ * this case, processing will continue, and the server will automatically generate an {@link BaseOperationOutcome
+ * OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they
+ * should return false, to indicate that they have handled the request and processing should stop.
*
*
*
* @param theRequestDetails
- * 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 {@link javax.servlet.http.HttpServletRequest servlet request}. Note that the bean properties are not all guaranteed to be populated, depending
- * on how early during processing the exception occurred.
+ * 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 {@link javax.servlet.http.HttpServletRequest servlet request}. Note that the bean
+ * properties are not all guaranteed to be populated, depending on how early during processing the
+ * exception occurred.
* @param theServletRequest
* The incoming request
* @param theServletResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link javax.servlet.http.HttpServletResponse#getWriter()}) but in that case it is important to
- * return false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link javax.servlet.http.HttpServletResponse#getWriter()}) but in that case it is important to return
+ * false to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
* @throws ServletException
* If this exception is thrown, it will be re-thrown up to the container for handling.
* @throws IOException
* If this exception is thrown, it will be re-thrown up to the container for handling.
*/
- boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
- throws ServletException, IOException;
+ boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws ServletException, IOException;
/**
* This method is called just before the actual implementing server method is invoked.
@@ -84,18 +94,22 @@ public interface IServerInterceptor {
*
*
* @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
+ * 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 {@link HttpServletRequest servlet request}.
* @param theRequest
* The incoming request
* @param theResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
* @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException;
@@ -107,14 +121,14 @@ public interface IServerInterceptor {
* @param theOperation
* The type of operation that the FHIR server has determined that the client is trying to invoke
* @param theProcessedRequest
- * An object which will be populated with the details which were extracted from the raw request by the server,
- * e.g. the FHIR operation type and the parsed resource body (if any).
+ * An object which will be populated with the details which were extracted from the raw request by the
+ * server, e.g. the FHIR operation type and the parsed resource body (if any).
*/
void incomingRequestPreHandled(RestOperationTypeEnum theOperation, ActionRequestDetails theProcessedRequest);
/**
- * This method is called before any other processing takes place for each incoming request. It may be used to provide alternate handling for some requests, or to screen requests before they are
- * handled, etc.
+ * This method is called before any other processing takes place for each incoming request. It may be used to provide
+ * alternate handling for some requests, or to screen requests before they are handled, etc.
*
* Note that any exceptions thrown by this method will not be trapped by HAPI (they will be passed up to the server)
*
@@ -122,15 +136,19 @@ public interface IServerInterceptor {
* @param theRequest
* The incoming request
* @param theResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
*/
boolean incomingRequestPreProcessed(HttpServletRequest theRequest, HttpServletResponse theResponse);
/**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
*
* @param theRequestDetails
* A bean containing details about the request that is about to be processed, including
@@ -139,159 +157,198 @@ public interface IServerInterceptor {
* @param theServletRequest
* The incoming request
* @param theServletResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
* @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
-
- /**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
- *
- * @param theRequestDetails
- * A bean containing details about the request that is about to be processed, including
- * @param theResponseObject
- * The actual object which is being streamed to the client as a response
- * @param theServletRequest
- * The incoming request
- * @param theServletResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
- * @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
- */
- boolean outgoingResponse(RequestDetails theRequest, Bundle bundle);
/**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
*
* @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
+ * A bean containing details about the request that is about to be processed, including
+ * @param theResponseObject
+ * The actual object which is being streamed to the client as a response
* @param theServletRequest
* The incoming request
* @param theServletResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
* @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
+ */
+ boolean outgoingResponse(RequestDetails theRequest, Bundle bundle);
+
+ /**
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
+ *
+ * @param theRequestDetails
+ * 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 {@link HttpServletRequest servlet request}.
+ * @param theServletRequest
+ * The incoming request
+ * @param theServletResponse
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
+ * @throws AuthenticationException
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
boolean outgoingResponse(RequestDetails theRequestDetails, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
-
- /**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
- *
- * @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
- * @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
- */
- boolean outgoingResponse(RequestDetails theRequestDetails);
/**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
*
* @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
- * @param theResponseObject
- * The actual object which is being streamed to the client as a response
- * @param theServletRequest
- * The incoming request
- * @param theServletResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * 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 {@link HttpServletRequest servlet request}.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
* @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
- boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
- throws AuthenticationException;
-
- /**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
- *
- * @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
- * @param theResponseObject
- * The actual object which is being streamed to the client as a response
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
- * @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
- */
- boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject);
+ boolean outgoingResponse(RequestDetails theRequestDetails);
/**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
*
* @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
+ * 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 {@link HttpServletRequest servlet request}.
* @param theResponseObject
* The actual object which is being streamed to the client as a response
* @param theServletRequest
* The incoming request
* @param theServletResponse
- * The response. Note that interceptors may choose to provide a response (i.e. by calling {@link HttpServletResponse#getWriter()}) but in that case it is important to return
- * false to indicate that the server itself should not also provide a response.
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
* @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
+ */
+ boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
+
+ /**
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
+ *
+ * @param theRequestDetails
+ * 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 {@link HttpServletRequest servlet request}.
+ * @param theResponseObject
+ * The actual object which is being streamed to the client as a response
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
+ * @throws AuthenticationException
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
+ */
+ boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject);
+
+ /**
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
+ *
+ * @param theRequestDetails
+ * 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 {@link HttpServletRequest servlet request}.
+ * @param theResponseObject
+ * The actual object which is being streamed to the client as a response
+ * @param theServletRequest
+ * The incoming request
+ * @param theServletResponse
+ * The response. Note that interceptors may choose to provide a response (i.e. by calling
+ * {@link HttpServletResponse#getWriter()}) but in that case it is important to return false
+ * to indicate that the server itself should not also provide a response.
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
+ * @throws AuthenticationException
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
*/
boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException;
- /**
- * This method is called after the server implementation method has been called, but before any attempt to stream the response back to the client
- *
- * @param theRequestDetails
- * 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 {@link HttpServletRequest servlet request}.
- * @param theResponseObject
- * The actual object which is being streamed to the client as a response
- * @return Return true if processing should continue normally. This is generally the right thing to do. If your interceptor is providing a response rather than letting HAPI handle the
- * response normally, you must return false. In this case, no further processing will occur and no further interceptors will be called.
- * @throws AuthenticationException
- * This exception may be thrown to indicate that the interceptor has detected an unauthorized access attempt. If thrown, processing will stop and an HTTP 401 will be returned to the
- * client.
- */
- boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject);
+ /**
+ * This method is called after the server implementation method has been called, but before any attempt to stream the
+ * response back to the client
+ *
+ * @param theRequestDetails
+ * 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 {@link HttpServletRequest servlet request}.
+ * @param theResponseObject
+ * The actual object which is being streamed to the client as a response
+ * @return Return true if processing should continue normally. This is generally the right thing to do.
+ * If your interceptor is providing a response rather than letting HAPI handle the response normally, you
+ * must return false. In this case, no further processing will occur and no further interceptors
+ * will be called.
+ * @throws AuthenticationException
+ * This exception may be thrown to indicate that the interceptor has detected an unauthorized access
+ * attempt. If thrown, processing will stop and an HTTP 401 will be returned to the client.
+ */
+ boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject);
/**
- * This method is called upon any exception being thrown within the server's request processing code. This includes any exceptions thrown within resource provider methods (e.g. {@link Search} and
- * {@link Read} methods) as well as any runtime exceptions thrown by the server itself. This method is invoked for each interceptor (until one of them returns a non-null response or
- * the end of the list is reached), after which {@link #handleException(RequestDetails, BaseServerResponseException, HttpServletRequest, HttpServletResponse)} is called for each interceptor.
+ * This method is called upon any exception being thrown within the server's request processing code. This includes
+ * any exceptions thrown within resource provider methods (e.g. {@link Search} and {@link Read} methods) as well as
+ * any runtime exceptions thrown by the server itself. This method is invoked for each interceptor (until one of them
+ * returns a non-null response or the end of the list is reached), after which
+ * {@link #handleException(RequestDetails, BaseServerResponseException, HttpServletRequest, HttpServletResponse)} is
+ * called for each interceptor.
*
* This may be used to add an OperationOutcome to a response, or to convert between exception types for any reason.
*
*
- * Implementations of this method may choose to ignore/log/count/etc exceptions, and return null. In this case, processing will continue, and the server will automatically generate an
- * {@link BaseOperationOutcome OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they should return a non-null, to indicate
- * that they have handled the request and processing should stop.
+ * Implementations of this method may choose to ignore/log/count/etc exceptions, and return null. In
+ * this case, processing will continue, and the server will automatically generate an {@link BaseOperationOutcome
+ * OperationOutcome}. Implementations may also choose to provide their own response to the client. In this case, they
+ * should return a non-null, to indicate that they have handled the request and processing should stop.
*
*
- * @return Returns the new exception to use for processing, or null if this interceptor is not trying to modify the exception. For example, if this interceptor has nothing to do with
- * exception processing, it should always return null. If this interceptor adds an OperationOutcome to the exception, it should return an exception.
+ * @return Returns the new exception to use for processing, or null if this interceptor is not trying to
+ * modify the exception. For example, if this interceptor has nothing to do with exception processing, it
+ * should always return null. If this interceptor adds an OperationOutcome to the exception, it
+ * should return an exception.
*/
BaseServerResponseException preProcessOutgoingException(RequestDetails theRequestDetails, Throwable theException, HttpServletRequest theServletRequest) throws ServletException;
@@ -300,19 +357,26 @@ public interface IServerInterceptor {
private boolean myLocked = false;
private IBaseResource myResource;
private final String myResourceType;
+ private final FhirContext myContext;
- public ActionRequestDetails(IIdType theId, String theResourceType) {
+ public ActionRequestDetails(IIdType theId, String theResourceType, FhirContext theContext) {
myId = theId;
myResourceType = theResourceType;
+ myContext = theContext;
}
public ActionRequestDetails(RequestDetails theRequestDetails) {
myId = theRequestDetails.getId();
myResourceType = theRequestDetails.getResourceName();
+ myContext = theRequestDetails.getServer().getFhirContext();
}
- public ActionRequestDetails(IIdType theId, String theResourceType, IBaseResource theResource) {
- this(theId, theResourceType);
+ public FhirContext getContext() {
+ return myContext;
+ }
+
+ public ActionRequestDetails(IIdType theId, String theResourceType, IBaseResource theResource, FhirContext theContext) {
+ this(theId, theResourceType, theContext);
myResource = theResource;
}
@@ -324,10 +388,12 @@ public interface IServerInterceptor {
}
/**
- * For requests where a resource is passed from the client to the server (e.g. create, update, etc.) this method will return the resource which was provided by the client. Otherwise, this method
- * will return null.
+ * For requests where a resource is passed from the client to the server (e.g. create, update, etc.) this method
+ * will return the resource which was provided by the client. Otherwise, this method will return null
+ * .
*
- * Note that this method is currently only populated if the handling method has a parameter annotated with the {@link ResourceParam} annotation.
+ * Note that this method is currently only populated if the handling method has a parameter annotated with the
+ * {@link ResourceParam} annotation.
*
*/
public IBaseResource getResource() {
@@ -335,7 +401,8 @@ public interface IServerInterceptor {
}
/**
- * Returns the resource type this request pertains to, or null if this request is not type specific (e.g. server-history)
+ * Returns the resource type this request pertains to, or null if this request is not type specific
+ * (e.g. server-history)
*/
public String getResourceType() {
return myResourceType;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.java
new file mode 100644
index 00000000000..1906ef5f41f
--- /dev/null
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/RequestValidatingInterceptor.java
@@ -0,0 +1,71 @@
+package ca.uhn.fhir.rest.server.interceptor;
+
+import java.nio.charset.Charset;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import ca.uhn.fhir.rest.method.RequestDetails;
+import ca.uhn.fhir.rest.param.ResourceParameter;
+import ca.uhn.fhir.rest.server.EncodingEnum;
+import ca.uhn.fhir.rest.server.RestfulServerUtils;
+import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
+import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
+import ca.uhn.fhir.validation.FhirValidator;
+import ca.uhn.fhir.validation.ResultSeverityEnum;
+import ca.uhn.fhir.validation.ValidationResult;
+
+/**
+ * This interceptor intercepts each incoming request and if it contains a FHIR resource, validates that resource. The
+ * interceptor may be configured to run any validator modules, and will then add headers to the response or fail the
+ * request with an {@link UnprocessableEntityException HTTP 422 Unprocessable Entity}.
+ */
+public class RequestValidatingInterceptor extends BaseValidatingInterceptor {
+
+ /**
+ * X-HAPI-Request-Validation
+ */
+ public static final String DEFAULT_RESPONSE_HEADER_NAME = "X-HAPI-Request-Validation";
+
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(RequestValidatingInterceptor.class);
+
+ @Override
+ public boolean incomingRequestPostProcessed(RequestDetails theRequestDetails, HttpServletRequest theRequest, HttpServletResponse theResponse) throws AuthenticationException {
+ EncodingEnum encoding = RestfulServerUtils.determineRequestEncodingNoDefault(theRequestDetails);
+ if (encoding == null) {
+ ourLog.trace("Incoming request does not appear to be FHIR, not going to validate");
+ return true;
+ }
+
+ Charset charset = ResourceParameter.determineRequestCharset(theRequestDetails);
+ String requestText = new String(theRequestDetails.loadRequestContents(), charset);
+ validate(requestText, theRequestDetails);
+
+ return true;
+ }
+
+
+ /**
+ * Sets the name of the response header to add validation failures to
+ *
+ * @see #DEFAULT_RESPONSE_HEADER_NAME
+ * @see #setAddResponseHeaderOnSeverity(ResultSeverityEnum)
+ */
+ @Override
+ public void setResponseHeaderName(String theResponseHeaderName) {
+ super.setResponseHeaderName(theResponseHeaderName);
+ }
+
+
+ @Override
+ String provideDefaultResponseHeaderName() {
+ return DEFAULT_RESPONSE_HEADER_NAME;
+ }
+
+
+ @Override
+ ValidationResult doValidate(FhirValidator theValidator, String theRequest) {
+ return theValidator.validateWithResult(theRequest);
+ }
+
+}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.java
index 6234c6af83a..6fc48753f1b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/interceptor/ResponseValidatingInterceptor.java
@@ -1,5 +1,7 @@
package ca.uhn.fhir.rest.server.interceptor;
+import java.nio.charset.Charset;
+
/*
* #%L
* HAPI FHIR - Core Library
@@ -29,49 +31,54 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.rest.method.RequestDetails;
+import ca.uhn.fhir.rest.param.ResourceParameter;
+import ca.uhn.fhir.rest.server.EncodingEnum;
+import ca.uhn.fhir.rest.server.RestfulServerUtils;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
+import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.validation.FhirValidator;
+import ca.uhn.fhir.validation.ResultSeverityEnum;
+import ca.uhn.fhir.validation.ValidationResult;
/**
- * Not yet complete!
- *
- * TODO: complete this
+ * This interceptor intercepts each outgoing response and if it contains a FHIR resource, validates that resource. The
+ * interceptor may be configured to run any validator modules, and will then add headers to the response or fail the
+ * request with an {@link UnprocessableEntityException HTTP 422 Unprocessable Entity}.
*/
-class ResponseValidatingInterceptor extends InterceptorAdapter {
+public class ResponseValidatingInterceptor extends BaseValidatingInterceptor {
- private FhirValidator myValidator;
-
/**
- * Returns the validator used by this interceptor
+ * X-HAPI-Request-Validation
*/
- public FhirValidator getValidator() {
- return myValidator;
+ public static final String DEFAULT_RESPONSE_HEADER_NAME = "X-HAPI-Response-Validation";
+
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResponseValidatingInterceptor.class);
+
+ @Override
+ public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
+ validate(theResponseObject, theRequestDetails);
+ return true;
}
/**
- * Sets the validator instance to use. Must not be null.
+ * Sets the name of the response header to add validation failures to
+ *
+ * @see #DEFAULT_RESPONSE_HEADER_NAME
+ * @see #setAddResponseHeaderOnSeverity(ResultSeverityEnum)
*/
- public void setValidator(FhirValidator theValidator) {
- Validate.notNull(theValidator, "Validator must not be null");
- myValidator = theValidator;
+ @Override
+ public void setResponseHeaderName(String theResponseHeaderName) {
+ super.setResponseHeaderName(theResponseHeaderName);
}
@Override
- public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
- return true;
+ String provideDefaultResponseHeaderName() {
+ return DEFAULT_RESPONSE_HEADER_NAME;
}
@Override
- public boolean outgoingResponse(RequestDetails theRequestDetails, Bundle theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
- return true;
+ ValidationResult doValidate(FhirValidator theValidator, IBaseResource theRequest) {
+ return theValidator.validateWithResult(theRequest);
}
- @Override
- public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse) throws AuthenticationException {
-
- return true;
- }
-
-
-
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java
index c5fecb39235..02d02d0aabc 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/servlet/ServletRestfulResponse.java
@@ -38,60 +38,60 @@ import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.RestfulResponse;
public class ServletRestfulResponse extends RestfulResponse {
-
- public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) {
- super(servletRequestDetails);
- }
-
- @Override
- public Object sendAttachmentResponse(IBaseBinary bin, int stausCode, String contentType) throws IOException {
- addHeaders();
- HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
- theHttpResponse.setStatus(stausCode);
- theHttpResponse.setContentType(contentType);
- if (bin.getContent() == null || bin.getContent().length == 0) {
- return null;
- } else {
- theHttpResponse.setContentLength(bin.getContent().length);
- ServletOutputStream oos = theHttpResponse.getOutputStream();
- oos.write(bin.getContent());
- oos.close();
- return null;
- }
- }
- @Override
- public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
- addHeaders();
- HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
- theHttpResponse.setCharacterEncoding(charset);
- theHttpResponse.setStatus(statusCode);
- theHttpResponse.setContentType(contentType);
+ public ServletRestfulResponse(ServletRequestDetails servletRequestDetails) {
+ super(servletRequestDetails);
+ }
+
+ @Override
+ public Object sendAttachmentResponse(IBaseBinary bin, int stausCode, String contentType) throws IOException {
+ addHeaders();
+ HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
+ theHttpResponse.setStatus(stausCode);
+ theHttpResponse.setContentType(contentType);
+ if (bin.getContent() == null || bin.getContent().length == 0) {
+ return null;
+ } else {
+ theHttpResponse.setContentLength(bin.getContent().length);
+ ServletOutputStream oos = theHttpResponse.getOutputStream();
+ oos.write(bin.getContent());
+ oos.close();
+ return null;
+ }
+ }
+
+ @Override
+ public Writer getResponseWriter(int statusCode, String contentType, String charset, boolean theRespondGzip) throws UnsupportedEncodingException, IOException {
+ addHeaders();
+ HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
+ theHttpResponse.setCharacterEncoding(charset);
+ theHttpResponse.setStatus(statusCode);
+ theHttpResponse.setContentType(contentType);
if (theRespondGzip) {
theHttpResponse.addHeader(Constants.HEADER_CONTENT_ENCODING, Constants.ENCODING_GZIP);
return new OutputStreamWriter(new GZIPOutputStream(theHttpResponse.getOutputStream()), Constants.CHARSET_NAME_UTF8);
} else {
return theHttpResponse.getWriter();
}
- }
+ }
+ private void addHeaders() {
+ HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
+ getRequestDetails().getServer().addHeadersToResponse(theHttpResponse);
+ for (Entry header : getHeaders().entrySet()) {
+ theHttpResponse.setHeader(header.getKey(), header.getValue());
+ }
+ }
- private void addHeaders() {
- HttpServletResponse theHttpResponse = getRequestDetails().getServletResponse();
- getRequestDetails().getServer().addHeadersToResponse(theHttpResponse);
- for (Entry header : getHeaders().entrySet()) {
- theHttpResponse.setHeader(header.getKey(), header.getValue());
- }
- }
-
+ @Override
public final Object sendWriterResponse(int status, String contentType, String charset, Writer writer) throws IOException {
- writer.close();
- return null;
- }
+ writer.close();
+ return null;
+ }
- @Override
- public Object returnResponse(ParseAction> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response,
- String resourceName) throws IOException {
- return getRequestDetails().getServer().returnResponse(getRequestDetails(), outcome, operationStatus, allowPrefer, response, resourceName);
- }
+ @Override
+ public Object returnResponse(ParseAction> outcome, int operationStatus, boolean allowPrefer, MethodOutcome response, String resourceName) throws IOException {
+ addHeaders();
+ return getRequestDetails().getServer().returnResponse(getRequestDetails(), outcome, operationStatus, allowPrefer, response, resourceName);
+ }
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu21Config.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu21Config.java
index a42e53a923a..e5e568d8119 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu21Config.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseDstu21Config.java
@@ -1,5 +1,12 @@
package ca.uhn.fhir.jpa.config;
+import org.hl7.fhir.dstu21.hapi.validation.DefaultProfileValidationSupport;
+import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
+import org.hl7.fhir.dstu21.hapi.validation.FhirQuestionnaireResponseValidator;
+import org.hl7.fhir.dstu21.hapi.validation.IValidationSupport;
+import org.hl7.fhir.dstu21.hapi.validation.ValidationSupportChain;
+import org.hl7.fhir.dstu21.validation.IResourceValidator.BestPracticeWarningLevel;
+
/*
* #%L
* HAPI FHIR JPA Server
@@ -21,8 +28,11 @@ package ca.uhn.fhir.jpa.config;
*/
import org.springframework.beans.factory.annotation.Autowire;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -30,6 +40,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.FhirSearchDao;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.dao.ISearchDao;
+import ca.uhn.fhir.validation.IValidatorModule;
@Configuration
@EnableTransactionManagement
@@ -48,22 +59,48 @@ public class BaseDstu21Config extends BaseConfig {
}
@Bean(name = "mySystemProviderDstu21")
- public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21 systemProviderDstu2() {
+ public ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21 systemProviderDstu21() {
ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21 retVal = new ca.uhn.fhir.jpa.provider.JpaSystemProviderDstu21();
retVal.setDao(systemDaoDstu21());
return retVal;
}
@Bean(name = "myJpaValidationSupportDstu21", autowire = Autowire.BY_NAME)
- public ca.uhn.fhir.jpa.dao.IJpaValidationSupportDstu21 jpaValidationSupportDstu2() {
+ public ca.uhn.fhir.jpa.dao.IJpaValidationSupportDstu21 jpaValidationSupportDstu21() {
ca.uhn.fhir.jpa.dao.JpaValidationSupportDstu21 retVal = new ca.uhn.fhir.jpa.dao.JpaValidationSupportDstu21();
return retVal;
}
+ @Qualifier("myJpaValidationSupportDstu21")
+ private IValidationSupport myJpaValidationSupportDstu21;
+
@Bean(autowire = Autowire.BY_TYPE)
- public ISearchDao searchDao() {
+ public ISearchDao searchDaoDstu21() {
FhirSearchDao searchDao = new FhirSearchDao();
return searchDao;
}
+
+ @Bean(name="myInstanceValidatorDstu21")
+ @Lazy
+ public IValidatorModule instanceValidatorDstu21() {
+ FhirInstanceValidator val = new FhirInstanceValidator();
+ val.setBestPracticeWarningLevel(BestPracticeWarningLevel.Warning);
+ val.setValidationSupport(validationSupportChainDstu21());
+ return val;
+ }
+
+ @Bean(name="myQuestionnaireResponseValidatorDstu21")
+ @Lazy
+ public IValidatorModule questionnaireResponseValidatorDstu21() {
+ FhirQuestionnaireResponseValidator module = new FhirQuestionnaireResponseValidator();
+ module.setValidationSupport(validationSupportChainDstu21());
+ return module;
+ }
+
+ @Bean
+ public IValidationSupport validationSupportChainDstu21() {
+ return new ValidationSupportChain(new DefaultProfileValidationSupport(), myJpaValidationSupportDstu21);
+// return new ValidationSupportChain();
+ }
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java
index bc0b70e448d..9b41669f4ce 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java
@@ -154,26 +154,26 @@ public abstract class BaseHapiFhirResourceDao extends B
if (getContext().getVersion().getVersion().equals(FhirVersionEnum.DSTU1)) {
if (theResource.getIdElement().isIdPartValidLong()) {
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedNumericId", theResource.getIdElement().getIdPart());
- throw new InvalidRequestException(message, createErrorOperationOutcome(message));
+ throw new InvalidRequestException(message, createErrorOperationOutcome(message, "processing"));
}
} else {
String message = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "failedToCreateWithClientAssignedId", theResource.getIdElement().getIdPart());
- throw new InvalidRequestException(message, createErrorOperationOutcome(message));
+ throw new InvalidRequestException(message, createErrorOperationOutcome(message, "processing"));
}
}
return doCreate(theResource, theIfNoneExist, thePerformIndexing, new Date());
}
- public IBaseOperationOutcome createErrorOperationOutcome(String theMessage) {
- return createOperationOutcome(OO_SEVERITY_ERROR, theMessage);
+ public IBaseOperationOutcome createErrorOperationOutcome(String theMessage, String theCode) {
+ return createOperationOutcome(OO_SEVERITY_ERROR, theMessage, theCode);
}
public IBaseOperationOutcome createInfoOperationOutcome(String theMessage) {
- return createOperationOutcome(OO_SEVERITY_INFO, theMessage);
+ return createOperationOutcome(OO_SEVERITY_INFO, theMessage, "informational");
}
- protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage);
+ protected abstract IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode);
@Override
public DaoMethodOutcome delete(IIdType theId) {
@@ -201,7 +201,7 @@ public abstract class BaseHapiFhirResourceDao extends B
validateOkToDelete(deleteConflicts, entity);
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType(), getContext());
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
Date updateTime = new Date();
@@ -251,7 +251,7 @@ public abstract class BaseHapiFhirResourceDao extends B
// Notify interceptors
IdDt idToDelete = entity.getIdDt();
- ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType(), getContext());
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
// Perform delete
@@ -308,7 +308,7 @@ public abstract class BaseHapiFhirResourceDao extends B
}
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theResource.getIdElement(), toResourceName(theResource), theResource);
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theResource.getIdElement(), toResourceName(theResource), theResource, getContext());
notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails);
// Perform actual DB update
@@ -333,7 +333,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public TagList getAllResourceTags() {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
+ ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
StopWatch w = new StopWatch();
@@ -356,7 +356,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public TagList getTags(IIdType theResourceId) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, null);
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, null, getContext());
notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails);
StopWatch w = new StopWatch();
@@ -368,7 +368,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public IBundleProvider history(Date theSince) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(null, null);
+ ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext());
notifyInterceptors(RestOperationTypeEnum.HISTORY_SYSTEM, requestDetails);
StopWatch w = new StopWatch();
@@ -380,7 +380,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public IBundleProvider history(final IIdType theId, final Date theSince) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.HISTORY_INSTANCE, requestDetails);
final InstantDt end = createHistoryToTimestamp();
@@ -495,7 +495,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public IBundleProvider history(Long theId, Date theSince) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.HISTORY_TYPE, requestDetails);
StopWatch w = new StopWatch();
@@ -507,7 +507,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public MT metaAddOperation(IIdType theResourceId, MT theMetaAdd) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails);
StopWatch w = new StopWatch();
@@ -634,7 +634,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails);
StopWatch w = new StopWatch();
@@ -675,7 +675,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public MT metaGetOperation(Class theType) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)";
@@ -714,7 +714,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public MT metaGetOperation(Class theType, IIdType theId) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.META, requestDetails);
Set tagDefs = new HashSet();
@@ -771,7 +771,7 @@ public abstract class BaseHapiFhirResourceDao extends B
validateResourceTypeAndThrowIllegalArgumentException(theId);
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ;
notifyInterceptors(operationType, requestDetails);
@@ -863,7 +863,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails);
StopWatch w = new StopWatch();
@@ -904,7 +904,7 @@ public abstract class BaseHapiFhirResourceDao extends B
@Override
public IBundleProvider search(final SearchParameterMap theParams) {
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName());
+ ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext());
notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails);
SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this);
@@ -1051,7 +1051,7 @@ public abstract class BaseHapiFhirResourceDao extends B
}
// Notify interceptors
- ActionRequestDetails requestDetails = new ActionRequestDetails(resourceId, getResourceName(), theResource);
+ ActionRequestDetails requestDetails = new ActionRequestDetails(resourceId, getResourceName(), theResource, getContext());
notifyInterceptors(RestOperationTypeEnum.UPDATE, requestDetails);
// Perform update
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java
index 5edff5a8859..e8af7a17f26 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java
@@ -64,7 +64,7 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao extends BaseHapiFhirDao extends BaseHapiFhirDao extends BaseHapiFhirResou
}
@Override
- protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
+ protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
OperationOutcome oo = new OperationOutcome();
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
oo.getIssueFirstRep().getDetailsElement().setValue(theMessage);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java
index 4cc7edd3603..eaa57260079 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu2.java
@@ -89,16 +89,17 @@ public class FhirResourceDaoDstu2 extends BaseHapiFhirResou
}
@Override
- protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage) {
+ protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
OperationOutcome oo = new OperationOutcome();
oo.getIssueFirstRep().getSeverityElement().setValue(theSeverity);
oo.getIssueFirstRep().getDiagnosticsElement().setValue(theMessage);
+ oo.getIssueFirstRep().getCodeElement().setValue(theCode);
return oo;
}
@Override
public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile) {
- ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource);
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext());
notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails);
if (theMode == ValidationModeEnum.DELETE) {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu21.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu21.java
index b4bc00a5daf..a6f4f979f92 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu21.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoDstu21.java
@@ -26,13 +26,12 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import org.hl7.fhir.dstu21.hapi.validation.FhirInstanceValidator;
-import org.hl7.fhir.dstu21.hapi.validation.IValidationSupport;
+import org.hl7.fhir.dstu21.exceptions.FHIRException;
import org.hl7.fhir.dstu21.model.IdType;
import org.hl7.fhir.dstu21.model.OperationOutcome;
import org.hl7.fhir.dstu21.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.dstu21.model.OperationOutcome.OperationOutcomeIssueComponent;
-import org.hl7.fhir.dstu21.validation.IResourceValidator.BestPracticeWarningLevel;
+import org.hl7.fhir.instance.model.OperationOutcome.IssueType;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource;
@@ -63,11 +62,26 @@ import ca.uhn.fhir.validation.ValidationResult;
public class FhirResourceDaoDstu21 extends BaseHapiFhirResourceDao {
- @Autowired()
- @Qualifier("myJpaValidationSupportDstu21")
- private IValidationSupport myJpaValidationSupport;
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu21.class);
+
+ @Autowired()
+ @Qualifier("myInstanceValidatorDstu21")
+ private IValidatorModule myInstanceValidator;
+
+ @Override
+ protected IBaseOperationOutcome createOperationOutcome(String theSeverity, String theMessage, String theCode) {
+ OperationOutcome oo = new OperationOutcome();
+ OperationOutcomeIssueComponent issue = oo.addIssue();
+ issue.getSeverityElement().setValueAsString(theSeverity);
+ issue.setDiagnostics(theMessage);
+ try {
+ issue.setCode(org.hl7.fhir.dstu21.model.OperationOutcome.IssueType.fromCode(theCode));
+ } catch (FHIRException e) {
+ ourLog.error("Unknown code: {}", theCode);
+ }
+ return oo;
+ }
-
@Override
protected List