protected void streamOperationOutcome( BaseServerResponseException theE, RestfulServer theServer, EncodingEnum theEncodingNotNull, HttpServletResponse theResponse, RequestDetails theRequest) throws IOException { theResponse.setStatus(theE.getStatusCode()); theServer.addHeadersToResponse(theResponse); if (theE.getOperationOutcome() != null) { theResponse.setContentType(theEncodingNotNull.getResourceContentType()); IParser parser = theEncodingNotNull.newParser(theServer.getFhirContext()); parser.setPrettyPrint(RestfulServerUtils.prettyPrintResponse(theServer, theRequest)); Writer writer = theResponse.getWriter(); try { parser.encodeResourceToWriter(theE.getOperationOutcome(), writer); } finally { writer.close(); } } else { theResponse.setContentType(Constants.CT_TEXT); Writer writer = theResponse.getWriter(); try { writer.append(theE.getMessage()); } finally { writer.close(); } } }
@Override public Bundle invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException { EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType); if (respType == null) { throw NonFhirResponseException.newInstance( theResponseStatusCode, theResponseMimeType, theResponseReader); } IParser parser = respType.newParser(myContext); return parser.parseBundle(myType, theResponseReader); }
@Test public void testView() { ExtPatient src = new ExtPatient(); src.addIdentifier("urn:sys", "id1"); src.addIdentifier("urn:sys", "id2"); src.getExt().setValue(100); src.getModExt().setValue(200); String enc = ourCtx.newXmlParser().encodeResourceToString(src); IParser parser = ourCtx.newXmlParser(); Patient nonExt = parser.parseResource(Patient.class, enc); assertEquals(Patient.class, nonExt.getClass()); assertEquals("urn:sys", nonExt.getIdentifier().get(0).getSystem().getValueAsString()); assertEquals("id1", nonExt.getIdentifier().get(0).getValue().getValue()); assertEquals("urn:sys", nonExt.getIdentifier().get(1).getSystem().getValueAsString()); assertEquals("id2", nonExt.getIdentifier().get(1).getValue().getValueAsString()); List<ExtensionDt> ext = nonExt.getUndeclaredExtensionsByUrl("urn:ext"); assertEquals(1, ext.size()); assertEquals("urn:ext", ext.get(0).getUrlAsString()); assertEquals(IntegerDt.class, ext.get(0).getValueAsPrimitive().getClass()); assertEquals("100", ext.get(0).getValueAsPrimitive().getValueAsString()); List<ExtensionDt> modExt = nonExt.getUndeclaredExtensionsByUrl("urn:modExt"); assertEquals(1, modExt.size()); assertEquals("urn:modExt", modExt.get(0).getUrlAsString()); assertEquals(IntegerDt.class, modExt.get(0).getValueAsPrimitive().getClass()); assertEquals("200", modExt.get(0).getValueAsPrimitive().getValueAsString()); ExtPatient va = ourCtx.newViewGenerator().newView(nonExt, ExtPatient.class); assertEquals("urn:sys", va.getIdentifier().get(0).getSystem().getValueAsString()); assertEquals("id1", va.getIdentifier().get(0).getValue().getValue()); assertEquals("urn:sys", va.getIdentifier().get(1).getSystem().getValueAsString()); assertEquals("id2", va.getIdentifier().get(1).getValue().getValueAsString()); assertEquals(100, va.getExt().getValue().intValue()); assertEquals(200, va.getModExt().getValue().intValue()); assertEquals(0, va.getAllUndeclaredExtensions().size()); }
@Test public void testModelExtension() throws DataFormatException { MyOrganization org = new MyOrganization(); org.getName().setValue("org0"); MyPatient patient = new MyPatient(); patient.addIdentifier("foo", "bar"); patient.getManagingOrganization().setResource(org); IParser p = ourCtx.newXmlParser().setPrettyPrint(true); String str = p.encodeResourceToString(patient); ourLog.info(str); MyPatient parsed = ourCtx.newXmlParser().parseResource(MyPatient.class, str); assertEquals("foo", parsed.getIdentifierFirstRep().getSystem().getValueAsString()); // assertEquals(MyOrganization.class, // parsed.getManagingOrganization().getResource().getClass()); // MyOrganization parsedOrg = (MyOrganization) parsed.getManagingOrganization().getResource(); // assertEquals("arg0", parsedOrg.getName().getValue()); }
@Override public T invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException { EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType); if (respType == null) { throw NonFhirResponseException.newInstance( theResponseStatusCode, theResponseMimeType, theResponseReader); } IParser parser = respType.newParser(myContext); T retVal = parser.parseResource(myType, theResponseReader); if (myId != null) { retVal.setId(myId); } MethodUtil.parseClientRequestResourceHeaders(theHeaders, retVal); return retVal; }
@Override public OperationOutcome invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException, BaseServerResponseException { EncodingEnum respType = EncodingEnum.forContentType(theResponseMimeType); if (respType == null) { return null; } IParser parser = respType.newParser(myContext); OperationOutcome retVal; try { retVal = parser.parseResource(OperationOutcome.class, theResponseReader); } catch (DataFormatException e) { ourLog.warn("Failed to parse OperationOutcome response", e); return null; } MethodUtil.parseClientRequestResourceHeaders(theHeaders, retVal); return retVal; }
/** * This method is called for nested bundles (e.g. if we received a transaction with an entry that * was a GET search, this method is called on the bundle for the search result, that will be * placed in the outer bundle). This method applies the _summary and _content parameters to the * output of that bundle. * * <p>TODO: This isn't the most efficient way of doing this.. hopefully we can come up with * something better in the future. */ private IBaseResource filterNestedBundle( RequestDetails theRequestDetails, IBaseResource theResource) { IParser p = getContext().newJsonParser(); RestfulServerUtils.configureResponseParser(theRequestDetails, p); return p.parseResource(theResource.getClass(), p.encodeResourceToString(theResource)); }
@Override public Object invokeClient( String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map<String, List<String>> theHeaders) throws IOException { IParser parser = createAppropriateParserForParsingResponse( theResponseMimeType, theResponseReader, theResponseStatusCode); switch (getReturnType()) { case BUNDLE: { Bundle bundle; if (myResourceType != null) { bundle = parser.parseBundle(myResourceType, theResponseReader); } else { bundle = parser.parseBundle(theResponseReader); } switch (getMethodReturnType()) { case BUNDLE: return bundle; case LIST_OF_RESOURCES: List<IResource> listOfResources; if (myResourceListCollectionType != null) { listOfResources = new ArrayList<IResource>(); for (IResource next : bundle.toListOfResources()) { if (!myResourceListCollectionType.isAssignableFrom(next.getClass())) { ourLog.debug( "Not returning resource of type {} because it is not a subclass or instance of {}", next.getClass(), myResourceListCollectionType); continue; } listOfResources.add(next); } } else { listOfResources = bundle.toListOfResources(); } return listOfResources; case RESOURCE: List<IResource> list = bundle.toListOfResources(); if (list.size() == 0) { return null; } else if (list.size() == 1) { return list.get(0); } else { throw new InvalidResponseException( theResponseStatusCode, "FHIR server call returned a bundle with multiple resources, but this method is only able to returns one."); } case BUNDLE_PROVIDER: throw new IllegalStateException( "Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients"); } break; } case RESOURCE: { IResource resource; if (myResourceType != null) { resource = parser.parseResource(myResourceType, theResponseReader); } else { resource = parser.parseResource(theResponseReader); } MethodUtil.parseClientRequestResourceHeaders(null, theHeaders, resource); switch (getMethodReturnType()) { case BUNDLE: return Bundle.withSingleResource(resource); case LIST_OF_RESOURCES: return Collections.singletonList(resource); case RESOURCE: return resource; case BUNDLE_PROVIDER: throw new IllegalStateException( "Return type of " + IBundleProvider.class.getSimpleName() + " is not supported in clients"); } break; } } throw new IllegalStateException("Should not get here!"); }
<T> T invokeClient( FhirContext theContext, IClientResponseHandler<T> binding, BaseHttpClientInvocation clientInvocation, EncodingEnum theEncoding, Boolean thePrettyPrint, boolean theLogRequestAndResponse) { if (!myDontValidateConformance) { myFactory.validateServerBaseIfConfiguredToDoSo(myUrlBase, myClient, this); } // TODO: handle non 2xx status codes by throwing the correct exception, // and ensure it's passed upwards HttpRequestBase httpRequest; HttpResponse response; try { Map<String, List<String>> params = createExtraParams(); if (theEncoding == EncodingEnum.XML) { params.put(Constants.PARAM_FORMAT, Collections.singletonList("xml")); } else if (theEncoding == EncodingEnum.JSON) { params.put(Constants.PARAM_FORMAT, Collections.singletonList("json")); } if (thePrettyPrint == Boolean.TRUE) { params.put( Constants.PARAM_PRETTY, Collections.singletonList(Constants.PARAM_PRETTY_VALUE_TRUE)); } EncodingEnum encoding = getEncoding(); if (theEncoding != null) { encoding = theEncoding; } httpRequest = clientInvocation.asHttpRequest(myUrlBase, params, encoding, thePrettyPrint); if (theLogRequestAndResponse) { ourLog.info("Client invoking: {}", httpRequest); if (httpRequest instanceof HttpEntityEnclosingRequest) { HttpEntity entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity(); if (entity.isRepeatable()) { String content = IOUtils.toString(entity.getContent()); ourLog.info("Client request body: {}", content); } } } for (IClientInterceptor nextInterceptor : myInterceptors) { nextInterceptor.interceptRequest(httpRequest); } response = myClient.execute(httpRequest); for (IClientInterceptor nextInterceptor : myInterceptors) { nextInterceptor.interceptResponse(response); } } catch (DataFormatException e) { throw new FhirClientConnectionException(e); } catch (IOException e) { throw new FhirClientConnectionException(e); } try { String mimeType; if (Constants.STATUS_HTTP_204_NO_CONTENT == response.getStatusLine().getStatusCode()) { mimeType = null; } else { ContentType ct = ContentType.get(response.getEntity()); mimeType = ct != null ? ct.getMimeType() : null; } Map<String, List<String>> headers = new HashMap<String, List<String>>(); if (response.getAllHeaders() != null) { for (Header next : response.getAllHeaders()) { String name = next.getName().toLowerCase(); List<String> list = headers.get(name); if (list == null) { list = new ArrayList<String>(); headers.put(name, list); } list.add(next.getValue()); } } if (response.getStatusLine().getStatusCode() < 200 || response.getStatusLine().getStatusCode() > 299) { String body = null; Reader reader = null; try { reader = createReaderFromResponse(response); body = IOUtils.toString(reader); } catch (Exception e) { ourLog.debug("Failed to read input stream", e); } finally { IOUtils.closeQuietly(reader); } String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase(); BaseOperationOutcome oo = null; if (Constants.CT_TEXT.equals(mimeType)) { message = message + ": " + body; } else { EncodingEnum enc = EncodingEnum.forContentType(mimeType); if (enc != null) { IParser p = enc.newParser(theContext); try { // TODO: handle if something other than OO comes back oo = (BaseOperationOutcome) p.parseResource(body); if (oo.getIssueFirstRep().getDetailsElement().isEmpty() == false) { message = message + ": " + oo.getIssueFirstRep().getDetailsElement().getValue(); } } catch (Exception e) { ourLog.debug("Failed to process OperationOutcome response"); } } } keepResponseAndLogIt(theLogRequestAndResponse, response, body); BaseServerResponseException exception = BaseServerResponseException.newInstance( response.getStatusLine().getStatusCode(), message); exception.setOperationOutcome(oo); if (body != null) { exception.setResponseBody(body); } throw exception; } if (binding instanceof IClientResponseHandlerHandlesBinary) { IClientResponseHandlerHandlesBinary<T> handlesBinary = (IClientResponseHandlerHandlesBinary<T>) binding; if (handlesBinary.isBinary()) { InputStream reader = response.getEntity().getContent(); try { if (ourLog.isTraceEnabled() || myKeepResponses || theLogRequestAndResponse) { byte[] responseBytes = IOUtils.toByteArray(reader); if (myKeepResponses) { myLastResponse = response; myLastResponseBody = null; } String message = "HTTP " + response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase(); if (theLogRequestAndResponse) { ourLog.info("Client response: {} - {} bytes", message, responseBytes.length); } else { ourLog.trace("Client response: {} - {} bytes", message, responseBytes.length); } reader = new ByteArrayInputStream(responseBytes); } return handlesBinary.invokeClient( mimeType, reader, response.getStatusLine().getStatusCode(), headers); } finally { IOUtils.closeQuietly(reader); } } } Reader reader = createReaderFromResponse(response); if (ourLog.isTraceEnabled() || myKeepResponses || theLogRequestAndResponse) { String responseString = IOUtils.toString(reader); keepResponseAndLogIt(theLogRequestAndResponse, response, responseString); reader = new StringReader(responseString); } try { return binding.invokeClient( mimeType, reader, response.getStatusLine().getStatusCode(), headers); } finally { IOUtils.closeQuietly(reader); } } catch (IllegalStateException e) { throw new FhirClientConnectionException(e); } catch (IOException e) { throw new FhirClientConnectionException(e); } finally { if (response instanceof CloseableHttpResponse) { try { ((CloseableHttpResponse) response).close(); } catch (IOException e) { ourLog.debug("Failed to close response", e); } } } }