diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java index b672aca316d..1b501d9e1c8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConcept.java @@ -49,6 +49,7 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank; @Index(name = "IDX_CONCEPT_UPDATED", columnList = "CONCEPT_UPDATED") }) public class TermConcept implements Serializable { + public static final int CODE_LENGTH = 500; protected static final int MAX_DESC_LENGTH = 400; private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TermConcept.class); @@ -57,7 +58,7 @@ public class TermConcept implements Serializable { @OneToMany(fetch = FetchType.LAZY, mappedBy = "myParent", cascade = {}) private Collection myChildren; - @Column(name = "CODE", length = 100, nullable = false) + @Column(name = "CODE", length = CODE_LENGTH, nullable = false) @Fields({@Field(name = "myCode", index = org.hibernate.search.annotations.Index.YES, store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "exactAnalyzer")),}) private String myCode; @Temporal(TemporalType.TIMESTAMP) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElement.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElement.java index a8cbb9ad202..5045f21ddfe 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElement.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElement.java @@ -45,7 +45,7 @@ public class TermConceptMapGroupElement implements Serializable { @JoinColumn(name = "CONCEPT_MAP_GROUP_PID", nullable = false, referencedColumnName = "PID", foreignKey=@ForeignKey(name="FK_TCMGELEMENT_GROUP")) private TermConceptMapGroup myConceptMapGroup; - @Column(name = "SOURCE_CODE", nullable = false, length = 100) + @Column(name = "SOURCE_CODE", nullable = false, length = TermConcept.CODE_LENGTH) private String myCode; @Column(name = "SOURCE_DISPLAY", length = TermConcept.MAX_DESC_LENGTH) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElementTarget.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElementTarget.java index cf24249d835..df48504e6e8 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElementTarget.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/entity/TermConceptMapGroupElementTarget.java @@ -44,7 +44,7 @@ public class TermConceptMapGroupElementTarget implements Serializable { @JoinColumn(name = "CONCEPT_MAP_GRP_ELM_PID", nullable = false, referencedColumnName = "PID", foreignKey=@ForeignKey(name="FK_TCMGETARGET_ELEMENT")) private TermConceptMapGroupElement myConceptMapGroupElement; - @Column(name = "TARGET_CODE", nullable = false, length = 50) + @Column(name = "TARGET_CODE", nullable = false, length = TermConcept.CODE_LENGTH) private String myCode; @Column(name = "TARGET_DISPLAY", length = TermConcept.MAX_DESC_LENGTH) diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/IServerInterceptor.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/IServerInterceptor.java index e91709dc40f..0072cc0c009 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/IServerInterceptor.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/IServerInterceptor.java @@ -9,9 +9,9 @@ package ca.uhn.fhir.rest.server.interceptor; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -262,6 +262,10 @@ public interface IServerInterceptor { * This method is called after all processing is completed for a request, but only if the * request completes normally (i.e. no exception is thrown). *

+ * This method should not throw any exceptions. Any exception that is thrown by this + * method will be logged, but otherwise not acted upon. + *

+ *

* Note that this individual interceptors will have this method called in the reverse order from the order in * which the interceptors were registered with the server. *

diff --git a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/InterceptorDstu3Test.java b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/InterceptorDstu3Test.java index badc56cfe41..f5cb31acf6b 100644 --- a/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/InterceptorDstu3Test.java +++ b/hapi-fhir-structures-dstu3/src/test/java/ca/uhn/fhir/rest/server/InterceptorDstu3Test.java @@ -156,6 +156,28 @@ public class InterceptorDstu3Test { assertNotNull(arTypeCapt.getValue().getResource()); } + @Test + public void testExceptionInProcessingCompletedNormally() throws Exception { + ourServlet.setInterceptors(myInterceptor1); + + when(myInterceptor1.incomingRequestPreProcessed(nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true); + when(myInterceptor1.incomingRequestPostProcessed(nullable(ServletRequestDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true); + when(myInterceptor1.outgoingResponse(nullable(ServletRequestDetails.class), nullable(OperationOutcome.class))).thenReturn(true); + when(myInterceptor1.outgoingResponse(nullable(ServletRequestDetails.class), nullable(ResponseDetails.class), nullable(HttpServletRequest.class), nullable(HttpServletResponse.class))).thenReturn(true); + doThrow(new NullPointerException("FOO")).when(myInterceptor1).processingCompletedNormally(any()); + + String input = createInput(); + + HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient"); + httpPost.setEntity(new StringEntity(input, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8"))); + HttpResponse status = ourClient.execute(httpPost); + try { + assertEquals(201, status.getStatusLine().getStatusCode()); + } finally { + IOUtils.closeQuietly(status.getEntity().getContent()); + } + } + @Test public void testResponseWithNothing() throws Exception { ourServlet.setInterceptors(myInterceptor1); @@ -229,34 +251,6 @@ public class InterceptorDstu3Test { i.resourceUpdated(null, null, null); } - @AfterClass - public static void afterClassClearContext() throws Exception { - ourServer.stop(); - TestUtil.clearAllStaticFieldsForUnitTest(); - } - - @BeforeClass - public static void beforeClass() throws Exception { - ourPort = PortUtil.findFreePort(); - ourServer = new Server(ourPort); - - DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider(); - - ServletHandler proxyHandler = new ServletHandler(); - ourServlet = new RestfulServer(ourCtx); - ourServlet.setResourceProviders(patientProvider); - ServletHolder servletHolder = new ServletHolder(ourServlet); - proxyHandler.addServletWithMapping(servletHolder, "/*"); - ourServer.setHandler(proxyHandler); - ourServer.start(); - - PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); - HttpClientBuilder builder = HttpClientBuilder.create(); - builder.setConnectionManager(connectionManager); - ourClient = builder.build(); - - } - public static class DummyPatientResourceProvider implements IResourceProvider { @Create() @@ -285,4 +279,32 @@ public class InterceptorDstu3Test { } + @AfterClass + public static void afterClassClearContext() throws Exception { + ourServer.stop(); + TestUtil.clearAllStaticFieldsForUnitTest(); + } + + @BeforeClass + public static void beforeClass() throws Exception { + ourPort = PortUtil.findFreePort(); + ourServer = new Server(ourPort); + + DummyPatientResourceProvider patientProvider = new DummyPatientResourceProvider(); + + ServletHandler proxyHandler = new ServletHandler(); + ourServlet = new RestfulServer(ourCtx); + ourServlet.setResourceProviders(patientProvider); + ServletHolder servletHolder = new ServletHolder(ourServlet); + proxyHandler.addServletWithMapping(servletHolder, "/*"); + ourServer.setHandler(proxyHandler); + ourServer.start(); + + PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS); + HttpClientBuilder builder = HttpClientBuilder.create(); + builder.setConnectionManager(connectionManager); + ourClient = builder.build(); + + } + } diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java index c2bead79fa9..7a4870c655b 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java @@ -36,6 +36,20 @@ public class JsonParserR4Test { return b; } + @Test + public void testDontStripVersions() { + FhirContext ctx = FhirContext.forR4(); + ctx.getParserOptions().setDontStripVersionsFromReferencesAtPaths("QuestionnaireResponse.questionnaire"); + + QuestionnaireResponse qr = new QuestionnaireResponse(); + qr.getQuestionnaireElement().setValueAsString("Questionnaire/123/_history/456"); + + String output = ctx.newJsonParser().setPrettyPrint(true).encodeResourceToString(qr); + ourLog.info(output); + + assertThat(output, containsString("\"Questionnaire/123/_history/456\"")); + } + /** * See #814 */ diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 74f3a407027..93d4a1cff59 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -293,6 +293,10 @@ A crash was fixed when using the ConceptMap/$translate operation to translate a mapping where the equivalence was not specified. + + The maximum length for codes in the JPA server terminology service have been increased + to 500 in order to better accomodate code systems with very long codes. +