test in weblogic: fix interceptor + stateless on abstract

This commit is contained in:
petervanhoute 2015-10-30 11:35:11 +01:00
parent 0aafd37397
commit 63db1b646f
15 changed files with 220 additions and 179 deletions

View File

@ -36,6 +36,7 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.SummaryEnum; import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.IRestfulResponse;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.OperationOutcomeUtil; import ca.uhn.fhir.util.OperationOutcomeUtil;
@ -47,6 +48,13 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
@Override @Override
public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException { public boolean handleException(RequestDetails theRequestDetails, BaseServerResponseException theException, HttpServletRequest theRequest, HttpServletResponse theResponse) throws ServletException, IOException {
handleException(theRequestDetails, theException);
return false;
}
public Object handleException(RequestDetails theRequestDetails, BaseServerResponseException theException)
throws ServletException, IOException {
IRestfulResponse response = theRequestDetails.getResponse();
FhirContext ctx = theRequestDetails.getServer().getFhirContext(); FhirContext ctx = theRequestDetails.getServer().getFhirContext();
@ -64,22 +72,19 @@ public class ExceptionHandlingInterceptor extends InterceptorAdapter {
if (isNotBlank(next.getKey()) && next.getValue() != null) { if (isNotBlank(next.getKey()) && next.getValue() != null) {
String nextKey = next.getKey(); String nextKey = next.getKey();
for (String nextValue : next.getValue()) { for (String nextValue : next.getValue()) {
theResponse.addHeader(nextKey, nextValue); response.addHeader(nextKey, nextValue);
} }
} }
} }
} }
theRequestDetails.getResponse().streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, false, false); return response.streamResponseAsResource(oo, true, Collections.singleton(SummaryEnum.FALSE), statusCode, false, false);
// theResponse.setStatus(statusCode); // theResponse.setStatus(statusCode);
// theRequestDetails.getServer().addHeadersToResponse(theResponse); // theRequestDetails.getServer().addHeadersToResponse(theResponse);
// theResponse.setContentType("text/plain"); // theResponse.setContentType("text/plain");
// theResponse.setCharacterEncoding("UTF-8"); // theResponse.setCharacterEncoding("UTF-8");
// theResponse.getWriter().append(theException.getMessage()); // theResponse.getWriter().append(theException.getMessage());
// theResponse.getWriter().close(); // theResponse.getWriter().close();
return false;
} }
@Override @Override

View File

@ -11,8 +11,6 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.ejb.Stateless;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS; import javax.ws.rs.OPTIONS;
import javax.ws.rs.Path; import javax.ws.rs.Path;
@ -44,9 +42,6 @@ import ca.uhn.fhir.util.ReflectionUtil;
* Conformance Rest Service * Conformance Rest Service
* @author Peter Van Houte * @author Peter Van Houte
*/ */
@Local
@Path("")
@Stateless
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProvider { public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProvider {
@ -67,8 +62,7 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
} }
@PostConstruct @PostConstruct
protected void setUpPostConstruct() protected void setUpPostConstruct() {
throws Exception {
for (Entry<Class<? extends IResourceProvider>, IResourceProvider> provider : getProviders().entrySet()) { for (Entry<Class<? extends IResourceProvider>, IResourceProvider> provider : getProviders().entrySet()) {
addProvider(provider.getValue(), provider.getKey()); addProvider(provider.getValue(), provider.getKey());
} }
@ -86,7 +80,7 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
myConformance = serverConformanceProvider.getServerConformance(null); myConformance = serverConformanceProvider.getServerConformance(null);
} }
protected abstract ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() throws Exception; protected abstract ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders();
@OPTIONS @OPTIONS
@Path("/metadata") @Path("/metadata")

View File

@ -66,9 +66,6 @@ public abstract class AbstractJaxRsProvider implements IRestfulServerDefaults, I
return getBaseForServer(); return getBaseForServer();
} }
/**
* PARSING METHODS
*/
protected JaxRsRequest createRequestDetails(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation) { protected JaxRsRequest createRequestDetails(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation) {
return new JaxRsRequest(this, resourceString, requestType, restOperation); return new JaxRsRequest(this, resourceString, requestType, restOperation);
} }

View File

@ -20,6 +20,7 @@ import javax.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate; import org.apache.commons.lang3.Validate;
import ca.uhn.fhir.jaxrs.server.interceptor.BaseServerRuntimeResponseException;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor; import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest; import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
import ca.uhn.fhir.jaxrs.server.util.MethodBindings; import ca.uhn.fhir.jaxrs.server.util.MethodBindings;
@ -35,6 +36,7 @@ import ca.uhn.fhir.rest.server.IPagingProvider;
import ca.uhn.fhir.rest.server.IRestfulServer; import ca.uhn.fhir.rest.server.IRestfulServer;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
@ -45,8 +47,10 @@ import ca.uhn.fhir.util.UrlUtil;
*/ */
@Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN}) @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
@Consumes({MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML}) @Consumes({MediaType.APPLICATION_FORM_URLENCODED, MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML})
@Interceptors(JaxRsExceptionInterceptor.class)
public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends AbstractJaxRsProvider implements IRestfulServer<JaxRsRequest> { public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends AbstractJaxRsProvider implements IRestfulServer<JaxRsRequest> {
private static final ExceptionHandlingInterceptor EXCEPTION_HANDLING_INTERCEPTOR = new ExceptionHandlingInterceptor();
private final MethodBindings bindings; private final MethodBindings bindings;
protected AbstractJaxRsResourceProvider() { protected AbstractJaxRsResourceProvider() {
@ -153,8 +157,12 @@ public abstract class AbstractJaxRsResourceProvider<R extends IResource> extends
private Response executeMethod(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation, String id, private Response executeMethod(final String resourceString, RequestTypeEnum requestType, RestOperationTypeEnum restOperation, String id,
BaseMethodBinding<?> method) BaseMethodBinding<?> method)
throws IOException { throws IOException {
final RequestDetails theRequest = createRequestDetails(resourceString, requestType, restOperation, id); final JaxRsRequest theRequest = createRequestDetails(resourceString, requestType, restOperation, id);
try {
return (Response) method.invokeServer(this, theRequest); return (Response) method.invokeServer(this, theRequest);
} catch(BaseServerRuntimeResponseException theException) {
return new JaxRsExceptionInterceptor().handleException(theRequest, theException);
}
} }

View File

@ -0,0 +1,16 @@
package ca.uhn.fhir.jaxrs.server.interceptor;
import javax.ejb.ApplicationException;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
@ApplicationException(rollback=false)
public class BaseServerRuntimeResponseException extends BaseServerResponseException {
private static final long serialVersionUID = 1L;
public BaseServerRuntimeResponseException(BaseServerResponseException base) {
super(base.getStatusCode(), base.getMessage(), base.getCause(), base.getOperationOutcome());
}
}

View File

@ -1,169 +1,77 @@
package ca.uhn.fhir.jaxrs.server.interceptor; package ca.uhn.fhir.jaxrs.server.interceptor;
import static org.apache.commons.lang3.StringUtils.isNotBlank; import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import javax.interceptor.AroundInvoke; import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext; import javax.interceptor.InvocationContext;
import javax.servlet.ServletException;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.slf4j.LoggerFactory;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider; import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.OperationOutcomeUtil; import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
public class JaxRsExceptionInterceptor { public class JaxRsExceptionInterceptor {
private static final org.slf4j.Logger ourLog = LoggerFactory.getLogger(JaxRsExceptionInterceptor.class); private ExceptionHandlingInterceptor exceptionHandler;
private Class<?>[] myReturnStackTracesForExceptionTypes;
@Context @Context
private UriInfo info; private UriInfo info;
@Context @Context
private HttpHeaders headers; private HttpHeaders headers;
AbstractJaxRsProvider theServer;
FhirContext fhirContext = AbstractJaxRsProvider.CTX; FhirContext fhirContext = AbstractJaxRsProvider.CTX;
public JaxRsExceptionInterceptor() {
this.exceptionHandler = new ExceptionHandlingInterceptor();
}
public JaxRsExceptionInterceptor(ExceptionHandlingInterceptor exceptionHandler) {
this.exceptionHandler = exceptionHandler;
}
@AroundInvoke @AroundInvoke
public Object intercept(final InvocationContext ctx) throws Exception { public Object intercept(final InvocationContext ctx) throws Throwable {
try { try {
if(!ourLog.isDebugEnabled() || ctx.getMethod().getName().contains("getResourceType")) {
return ctx.proceed(); return ctx.proceed();
} else {
ourLog.debug("METHOD_CALL : " + ctx.getMethod().getName() + " [ " + Arrays.asList(ctx.getParameters()) + "] ");
Object proceed = ctx.proceed();
ourLog.debug("RESULT : " + proceed.toString());
return proceed;
}
} catch(final Exception theException) { } catch(final Exception theException) {
return handleException(theException); theServer = (AbstractJaxRsProvider) ctx.getTarget();
throw convertException(theServer, theException);
} }
} }
public Response handleException(final Throwable theException) public BaseServerRuntimeResponseException convertException(final AbstractJaxRsProvider theServer, final Exception theException) {
{ JaxRsRequest requestDetails = new JaxRsRequest(theServer, null, null, null);
IBaseOperationOutcome oo = null; BaseServerResponseException convertedException = preprocessException(theException, requestDetails);
int statusCode = Constants.STATUS_HTTP_500_INTERNAL_ERROR; return new BaseServerRuntimeResponseException(convertedException);
if (theException instanceof BaseServerResponseException) {
oo = ((BaseServerResponseException) theException).getOperationOutcome();
statusCode = ((BaseServerResponseException) theException).getStatusCode();
} }
/* public Response handleException(JaxRsRequest theRequest, BaseServerRuntimeResponseException theException)
* Generate an OperationOutcome to return, unless the exception throw by the resource provider had one throws IOException {
*/ return handleExceptionWithoutServletError(theRequest, theException);
if (oo == null) { }
private BaseServerResponseException preprocessException(final Exception theException, JaxRsRequest requestDetails) {
try { try {
final RuntimeResourceDefinition ooDef = fhirContext.getResourceDefinition("OperationOutcome"); return exceptionHandler.preProcessOutgoingException(requestDetails, theException, null);
oo = (IBaseOperationOutcome) ooDef.getImplementingClass().newInstance(); } catch(ServletException e) {
return new InternalErrorException(e);
if (theException instanceof InternalErrorException) {
ourLog.error("Failure during REST processing", theException);
populateDetails(fhirContext, theException, oo);
} else if (theException instanceof BaseServerResponseException) {
ourLog.warn("Failure during REST processing: {}", theException);
final BaseServerResponseException baseServerResponseException = (BaseServerResponseException) theException;
statusCode = baseServerResponseException.getStatusCode();
populateDetails(fhirContext, theException, oo);
if (baseServerResponseException.getAdditionalMessages() != null) {
for (final String next : baseServerResponseException.getAdditionalMessages()) {
OperationOutcomeUtil.addIssue(fhirContext, oo, "error", next);
}
}
} else {
ourLog.error("Failure during REST processing: " + theException.toString(), theException);
populateDetails(fhirContext, theException, oo);
statusCode = Constants.STATUS_HTTP_500_INTERNAL_ERROR;
}
} catch (final Exception e1) {
ourLog.error("Failed to instantiate OperationOutcome resource instance", e1);
final ResponseBuilder result = Response.status(Constants.STATUS_HTTP_500_INTERNAL_ERROR);
result.header(Constants.HEADER_CONTENT_TYPE, Constants.CT_TEXT_WITH_UTF8);
result.header(Constants.HEADER_CONTENT_ENCODING, Constants.CHARSET_NAME_UTF8);
result.entity(theException.getMessage());
return result.build();
}
} else {
ourLog.error("Unknown error during processing", theException);
}
// Add headers associated with the specific error code
if (theException instanceof BaseServerResponseException) {
final Map<String, String[]> additional = ((BaseServerResponseException) theException).getAssociatedHeaders();
if (additional != null) {
for (final Entry<String, String[]> next : additional.entrySet()) {
if (isNotBlank(next.getKey()) && next.getValue() != null) {
final String nextKey = next.getKey();
for (final String nextValue : next.getValue()) {
addHeader(nextKey, nextValue);
}
}
}
} }
} }
final boolean requestIsBrowser = false; // RestfulServer.requestIsBrowser(theRequest); private Response handleExceptionWithoutServletError(JaxRsRequest theRequest, BaseServerResponseException theException) throws IOException {
final String fhirServerBase = ""; // theRequestDetails.getFhirServerBase(); try {
return (Response) exceptionHandler.handleException(theRequest, theException);
// theResponse.setStatus(statusCode); } catch (ServletException e) {
// theRequestDetails.getServer().addHeadersToResponse(theResponse); BaseServerResponseException newException = preprocessException(new InternalErrorException(e), theRequest);
// theResponse.setContentType("text/plain"); return handleExceptionWithoutServletError(theRequest, newException);
// theResponse.setCharacterEncoding("UTF-8");
// theResponse.getWriter().append(theException.getMessage());
// theResponse.getWriter().close();
final ResponseBuilder result = Response.status(statusCode);
//final String resName = ctx.getResourceDefinition(oo).getName();
result.header(Constants.HEADER_CONTENT_TYPE, Constants.CT_TEXT_WITH_UTF8);
result.entity(theException.getMessage());
return result.build();
}
private void addHeader(final String nextKey, final String nextValue) {
throw new UnsupportedOperationException();
}
private void populateDetails(final FhirContext theCtx, final Throwable theException, final IBaseOperationOutcome theOo) {
if (myReturnStackTracesForExceptionTypes != null) {
for (final Class<?> next : myReturnStackTracesForExceptionTypes) {
if (next.isAssignableFrom(theException.getClass())) {
final String detailsValue = theException.getMessage() + "\n\n" + ExceptionUtils.getStackTrace(theException);
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", detailsValue);
return;
} }
} }
} }
OperationOutcomeUtil.addIssue(theCtx, theOo, "error", theException.getMessage());
}
/**
* If any server methods throw an exception which extends any of the given exception types, the exception stack trace
* will be returned to the user. This can be useful for helping to diagnose issues, but may not be desirable for
* production situations.
*
* @param theExceptionTypes
* The exception types for which to return the stack trace to the user.
* @return Returns an instance of this interceptor, to allow for easy method chaining.
*/
public JaxRsExceptionInterceptor setReturnStackTracesForExceptionTypes(final Class<?>... theExceptionTypes) {
myReturnStackTracesForExceptionTypes = theExceptionTypes;
return this;
}
}

View File

@ -11,6 +11,7 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.method.BaseMethodBinding; import ca.uhn.fhir.rest.method.BaseMethodBinding;
import ca.uhn.fhir.rest.method.OperationMethodBinding; import ca.uhn.fhir.rest.method.OperationMethodBinding;
import ca.uhn.fhir.rest.method.SearchMethodBinding; import ca.uhn.fhir.rest.method.SearchMethodBinding;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import ca.uhn.fhir.util.ReflectionUtil; import ca.uhn.fhir.util.ReflectionUtil;
/** /**
@ -63,7 +64,7 @@ public class MethodBindings {
String nonEmptyQualifier = StringUtils.defaultIfBlank(qualifier, ""); String nonEmptyQualifier = StringUtils.defaultIfBlank(qualifier, "");
ConcurrentHashMap<String, BaseMethodBinding<?>> map = operationBindings.get(operationType); ConcurrentHashMap<String, BaseMethodBinding<?>> map = operationBindings.get(operationType);
if(map == null || !map.containsKey(nonEmptyQualifier)) { if(map == null || !map.containsKey(nonEmptyQualifier)) {
throw new UnsupportedOperationException(); throw new NotImplementedOperationException("Operation not implemented");
} else { } else {
return map.get(nonEmptyQualifier); return map.get(nonEmptyQualifier);
} }

View File

@ -2,6 +2,7 @@ package ca.uhn.fhir.jaxrs.server;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.argThat;
@ -35,6 +36,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jaxrs.server.example.RandomServerPortProvider; import ca.uhn.fhir.jaxrs.server.example.RandomServerPortProvider;
import ca.uhn.fhir.jaxrs.server.example.TestJaxRsConformanceRestProvider; import ca.uhn.fhir.jaxrs.server.example.TestJaxRsConformanceRestProvider;
import ca.uhn.fhir.jaxrs.server.example.TestJaxRsMockPatientRestProvider; import ca.uhn.fhir.jaxrs.server.example.TestJaxRsMockPatientRestProvider;
import ca.uhn.fhir.jaxrs.server.interceptor.BaseServerRuntimeResponseException;
import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor; import ca.uhn.fhir.jaxrs.server.interceptor.JaxRsExceptionInterceptor;
import ca.uhn.fhir.model.api.BundleEntry; import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.IResource;
@ -351,12 +353,13 @@ public class AbstractJaxRsResourceProviderTest {
@Test @Test
public void testXFindUnknownPatient() { public void testXFindUnknownPatient() {
try { try {
when(mock.find(idCaptor.capture())).thenThrow(new ResourceNotFoundException(new IdDt("999955541264"))); BaseServerRuntimeResponseException notFoundException = new BaseServerRuntimeResponseException(new ResourceNotFoundException(new IdDt("999955541264")));
final Patient existing = client.read(Patient.class, "999955541264"); when(mock.find(idCaptor.capture())).thenThrow(notFoundException);
client.read(Patient.class, "999955541264");
fail(); fail();
} catch (final Exception e) { } catch (final ResourceNotFoundException e) {
e.printStackTrace(); assertEquals(ResourceNotFoundException.STATUS_CODE, e.getStatusCode());
// assertEquals(e.getStatusCode(), 404); assertTrue(e.getMessage().contains("999955541264"));
} }
} }

View File

@ -27,7 +27,7 @@ public class TestJaxRsConformanceRestProvider extends AbstractJaxRsConformancePr
} }
@Override @Override
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() throws Exception { protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>(); ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
map.put(TestJaxRsMockPatientRestProvider.class, new TestJaxRsMockPatientRestProvider()); map.put(TestJaxRsMockPatientRestProvider.class, new TestJaxRsMockPatientRestProvider());
map.put(TestJaxRsConformanceRestProvider.class, new TestJaxRsConformanceRestProvider()); map.put(TestJaxRsConformanceRestProvider.class, new TestJaxRsConformanceRestProvider());

View File

@ -0,0 +1,105 @@
package ca.uhn.fhir.jaxrs.server.interceptor;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import java.util.HashMap;
import javax.interceptor.InvocationContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import org.junit.Before;
import org.junit.Test;
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsProvider;
import ca.uhn.fhir.jaxrs.server.example.TestDummyPatientProvider;
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest;
import ca.uhn.fhir.rest.method.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
import ca.uhn.fhir.rest.server.interceptor.ExceptionHandlingInterceptor;
public class JaxRsExceptionInterceptorTest {
JaxRsExceptionInterceptor interceptor = new JaxRsExceptionInterceptor();
private InvocationContext context;
@Before
public void setUp() {
interceptor = new JaxRsExceptionInterceptor();
context = mock(InvocationContext.class);
TestDummyPatientProvider provider = spy(TestDummyPatientProvider.class);
when(context.getTarget()).thenReturn(provider);
doReturn("http://baseUri").when(provider).getBaseForServer();
doReturn(new HashMap<String, String[]>()).when(provider).getQueryMap();
doReturn(mock(HttpHeaders.class)).when(provider).getHeaders();
}
@Test
public void testInterceptWithBaseServerError() throws Throwable {
NotImplementedOperationException thrownException = new NotImplementedOperationException("not implemented");
when(context.proceed()).thenThrow(thrownException);
try {
interceptor.intercept(context);
fail();
} catch (BaseServerResponseException e) {
assertEquals(e.getMessage(), thrownException.getMessage());
}
}
@Test
public void testIntercepWithServletError() throws Throwable {
ExceptionHandlingInterceptor exceptionHandler = mock(ExceptionHandlingInterceptor.class);
when(exceptionHandler.preProcessOutgoingException(any(RequestDetails.class), any(Throwable.class),
isNull(HttpServletRequest.class))).thenThrow(new ServletException("someMessage"));
interceptor = new JaxRsExceptionInterceptor(exceptionHandler);
when(context.proceed()).thenThrow(new ServletException());
try {
interceptor.intercept(context);
fail();
} catch (BaseServerResponseException e) {
assertTrue(e.getMessage().contains("someMessage"));
}
}
@Test
public void testInterceptServletWithoutError() throws Throwable {
Object expected = new Object();
when(context.proceed()).thenReturn(expected);
Object result = interceptor.intercept(context);
assertSame(expected, result);
}
@Test
public void testHandleExceptionWithServletError() throws Throwable {
JaxRsRequest request = new JaxRsRequest((AbstractJaxRsProvider) context.getTarget(), null, null, null);
ExceptionHandlingInterceptor exceptionHandler = spy(ExceptionHandlingInterceptor.class);
doThrow(new ServletException("someMessage")).when(exceptionHandler).preProcessOutgoingException(any(RequestDetails.class), any(Throwable.class),
isNull(HttpServletRequest.class));
interceptor = new JaxRsExceptionInterceptor(exceptionHandler);
when(context.proceed()).thenThrow(new ServletException());
BaseServerRuntimeResponseException thrownException = new BaseServerRuntimeResponseException(new NotImplementedOperationException("not implemented"));
doThrow(new javax.servlet.ServletException("someMessage")).when(exceptionHandler).handleException(request, thrownException);
BaseServerRuntimeResponseException internalException = thrownException;
Response result = interceptor.handleException(request, internalException);
assertEquals(InternalErrorException.STATUS_CODE, result.getStatus());
}
}

View File

@ -26,6 +26,7 @@ import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.NotImplementedOperationException;
@FixMethodOrder(MethodSorters.DEFAULT) @FixMethodOrder(MethodSorters.DEFAULT)
public class MethodBindingsTest { public class MethodBindingsTest {
@ -35,7 +36,7 @@ public class MethodBindingsTest {
MethodBindings.getClassBindings().clear(); MethodBindings.getClassBindings().clear();
} }
@Test(expected = UnsupportedOperationException.class) @Test(expected = NotImplementedOperationException.class)
public void testFindMethodsForProviderNotDefinedMappingMethods() { public void testFindMethodsForProviderNotDefinedMappingMethods() {
new TestDummyPatientProvider().getBindings().getBinding(RestOperationTypeEnum.UPDATE, ""); new TestDummyPatientProvider().getBindings().getBinding(RestOperationTypeEnum.UPDATE, "");
} }
@ -120,7 +121,7 @@ public class MethodBindingsTest {
try { try {
bindings.getBinding(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, "$thirdMethod"); bindings.getBinding(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, "$thirdMethod");
fail(); fail();
} catch(UnsupportedOperationException e){ } catch(NotImplementedOperationException e){
} }
} }

View File

@ -29,7 +29,7 @@ public class JaxRsConformanceProvider extends AbstractJaxRsConformanceProvider {
} }
@Override @Override
protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() throws Exception { protected ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> getProviders() {
ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>(); ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> map = new ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider>();
map.put(JaxRsConformanceProvider.class, new JaxRsConformanceProvider()); map.put(JaxRsConformanceProvider.class, new JaxRsConformanceProvider());
map.put(JaxRsPatientRestProvider.class, new JaxRsPatientRestProvider()); map.put(JaxRsPatientRestProvider.class, new JaxRsPatientRestProvider());

View File

@ -1,5 +1,6 @@
package ca.uhn.fhir.jaxrs.server.example; package ca.uhn.fhir.jaxrs.server.example;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
@ -66,7 +67,7 @@ public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Pati
private static Long counter = 1L; private static Long counter = 1L;
private static final ConcurrentHashMap<String, List<Patient>> patients = new ConcurrentHashMap<String, List<Patient>>(); private static final ConcurrentHashMap<String, List<Patient>> patients = new ConcurrentHashMap<String, List<Patient>>();
public JaxRsPatientRestProvider() throws Exception { public JaxRsPatientRestProvider() {
super(JaxRsPatientRestProvider.class); super(JaxRsPatientRestProvider.class);
} }
@ -132,7 +133,8 @@ public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Pati
} }
@Read @Read
public Patient find(@IdParam final IdDt theId) { @Interceptors(JaxRsExceptionInterceptor.class)
public Patient find(@IdParam final IdDt theId) throws InvocationTargetException {
if (patients.containsKey(theId.getIdPart())) { if (patients.containsKey(theId.getIdPart())) {
return getLast(patients.get(theId.getIdPart())); return getLast(patients.get(theId.getIdPart()));
} else { } else {
@ -168,7 +170,7 @@ public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Pati
} }
@Delete @Delete
public MethodOutcome delete(@IdParam final IdDt theId) { public MethodOutcome delete(@IdParam final IdDt theId) throws InvocationTargetException {
final Patient deletedPatient = find(theId); final Patient deletedPatient = find(theId);
patients.remove(deletedPatient.getId().getIdPart()); patients.remove(deletedPatient.getId().getIdPart());
final MethodOutcome result = new MethodOutcome().setCreated(true); final MethodOutcome result = new MethodOutcome().setCreated(true);
@ -203,7 +205,7 @@ public class JaxRsPatientRestProvider extends AbstractJaxRsResourceProvider<Pati
@Operation(name = "last", idempotent = true, returnParameters = { @Operation(name = "last", idempotent = true, returnParameters = {
@OperationParam(name = "return", type = StringDt.class) }) @OperationParam(name = "return", type = StringDt.class) })
public Parameters last(@OperationParam(name = "dummy") StringDt dummyInput) { public Parameters last(@OperationParam(name = "dummy") StringDt dummyInput) throws InvocationTargetException {
System.out.println("inputparameter"); System.out.println("inputparameter");
Parameters parameters = new Parameters(); Parameters parameters = new Parameters();
Patient patient = find(new IdDt(counter.intValue() - 1)); Patient patient = find(new IdDt(counter.intValue() - 1));

View File

@ -63,7 +63,8 @@ public class JaxRsPatientProviderTest {
ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER); ourCtx.getRestfulClientFactory().setServerValidationMode(ServerValidationModeEnum.NEVER);
ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000); ourCtx.getRestfulClientFactory().setSocketTimeout(1200 * 1000);
client = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort + "/"); //client = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort + "/");
client = ourCtx.newRestfulGenericClient("http://localhost:8580/hapi-fhir-jaxrsserver-example/jaxrs-demo/");
client.setEncoding(EncodingEnum.JSON); client.setEncoding(EncodingEnum.JSON);
client.registerInterceptor(new LoggingInterceptor(true)); client.registerInterceptor(new LoggingInterceptor(true));
} }