Bump RestEasy to 5.0.2 (#3329)

* Bump deps

* Test fix

* Add test logging

* Add test logging

* Add logging
This commit is contained in:
James Agnew 2022-01-24 20:15:41 -05:00 committed by GitHub
parent a11d72ba51
commit 31bb1d9e9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 407 additions and 304 deletions

View File

@ -79,11 +79,6 @@
<artifactId>jetty-servlet</artifactId> <artifactId>jetty-servlet</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId> <artifactId>resteasy-client</artifactId>

View File

@ -25,6 +25,7 @@
<li>Jetty Server (CLI): 9.4.43.v20210629 -> 9.4.44.v20210927</li> <li>Jetty Server (CLI): 9.4.43.v20210629 -> 9.4.44.v20210927</li>
<li>Spring Boot (Boot): 2.5.0 -> 2.6.2</li> <li>Spring Boot (Boot): 2.5.0 -> 2.6.2</li>
<li>Swagger UI (OpenAPI): 3.46.0 -> 4.1.3</li> <li>Swagger UI (OpenAPI): 3.46.0 -> 4.1.3</li>
<li>Resteasy (JAX-RS): 4.0.0.Beta3 -> 5.0.2.Final</li>
</ul> </ul>
" "

View File

@ -72,11 +72,6 @@
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>javax.ejb</groupId> <groupId>javax.ejb</groupId>
<artifactId>ejb-api</artifactId> <artifactId>ejb-api</artifactId>
@ -87,6 +82,11 @@
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.spec.javax.ws.rs</groupId>
<artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>javax.annotation</groupId> <groupId>javax.annotation</groupId>
@ -122,11 +122,6 @@
</dependency> </dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId> <artifactId>resteasy-client</artifactId>

View File

@ -20,22 +20,26 @@ package ca.uhn.fhir.jaxrs.client;
* #L% * #L%
*/ */
import java.util.List; import ca.uhn.fhir.context.FhirContext;
import java.util.Map; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.Header;
import ca.uhn.fhir.rest.client.api.HttpClientUtil;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.method.MethodUtil;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
import javax.ws.rs.client.Entity; import javax.ws.rs.client.Entity;
import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.core.*; import javax.ws.rs.core.Form;
import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import org.hl7.fhir.instance.model.api.IBaseBinary; import org.hl7.fhir.instance.model.api.IBaseBinary;
import ca.uhn.fhir.context.FhirContext; import java.util.List;
import ca.uhn.fhir.rest.api.*; import java.util.Map;
import ca.uhn.fhir.rest.client.api.*;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.rest.client.method.MethodUtil;
import ca.uhn.fhir.rest.server.RestfulServerUtils;
/** /**
* A Http Request based on JaxRs. This is an adapter around the class * A Http Request based on JaxRs. This is an adapter around the class

View File

@ -26,6 +26,8 @@ import java.util.List;
import javax.interceptor.Interceptors; import javax.interceptor.Interceptors;
import javax.ws.rs.*; import javax.ws.rs.*;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;

View File

@ -20,54 +20,77 @@ package ca.uhn.fhir.jaxrs.server;
* #L% * #L%
*/ */
import java.io.IOException; import ca.uhn.fhir.context.ConfigurationException;
import java.lang.annotation.Annotation; import ca.uhn.fhir.context.FhirContext;
import java.lang.reflect.Method; import ca.uhn.fhir.context.FhirVersionEnum;
import java.lang.reflect.Modifier; import ca.uhn.fhir.context.RuntimeResourceDefinition;
import java.util.*; import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder;
import java.util.Map.Entry; import ca.uhn.fhir.rest.annotation.IdParam;
import java.util.concurrent.ConcurrentHashMap; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import javax.annotation.PostConstruct; import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import javax.ws.rs.*; import ca.uhn.fhir.rest.api.SummaryEnum;
import javax.ws.rs.core.MediaType; import ca.uhn.fhir.rest.api.server.IRestfulResponse;
import javax.ws.rs.core.Response; import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.ResourceBinding;
import ca.uhn.fhir.rest.server.RestfulServerConfiguration;
import ca.uhn.fhir.rest.server.method.BaseMethodBinding;
import ca.uhn.fhir.rest.server.provider.ServerCapabilityStatementProvider; import ca.uhn.fhir.rest.server.provider.ServerCapabilityStatementProvider;
import ca.uhn.fhir.util.ReflectionUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu2.hapi.rest.server.ServerConformanceProvider; import org.hl7.fhir.dstu2.hapi.rest.server.ServerConformanceProvider;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.CapabilityStatement; import org.hl7.fhir.r4.model.CapabilityStatement;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import ca.uhn.fhir.context.*; import javax.annotation.PostConstruct;
import ca.uhn.fhir.jaxrs.server.util.JaxRsRequest.Builder; import javax.ws.rs.GET;
import ca.uhn.fhir.rest.annotation.IdParam; import javax.ws.rs.OPTIONS;
import ca.uhn.fhir.rest.api.*; import javax.ws.rs.Path;
import ca.uhn.fhir.rest.api.server.IRestfulResponse; import javax.ws.rs.Produces;
import ca.uhn.fhir.rest.server.*; import javax.ws.rs.core.MediaType;
import ca.uhn.fhir.rest.server.method.BaseMethodBinding; import javax.ws.rs.core.Response;
import ca.uhn.fhir.util.ReflectionUtil; import java.io.IOException;
import java.util.stream.Collectors; import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* This is the conformance provider for the jax rs servers. It requires all providers to be registered during startup because the conformance profile is generated during the postconstruct phase. * This is the conformance provider for the jax rs servers. It requires all providers to be registered during startup because the conformance profile is generated during the postconstruct phase.
* *
* @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare * @author Peter Van Houte | peter.vanhoute@agfa.com | Agfa Healthcare
*/ */
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProvider implements IResourceProvider { public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProvider implements IResourceProvider {
/** the logger */ /**
* the logger
*/
private static final org.slf4j.Logger ourLog = LoggerFactory.getLogger(AbstractJaxRsConformanceProvider.class); private static final org.slf4j.Logger ourLog = LoggerFactory.getLogger(AbstractJaxRsConformanceProvider.class);
/** the server bindings */ /**
* the server bindings
*/
private ResourceBinding myServerBinding = new ResourceBinding(); private ResourceBinding myServerBinding = new ResourceBinding();
/** the resource bindings */ /**
* the resource bindings
*/
private ConcurrentHashMap<String, ResourceBinding> myResourceNameToBinding = new ConcurrentHashMap<String, ResourceBinding>(); private ConcurrentHashMap<String, ResourceBinding> myResourceNameToBinding = new ConcurrentHashMap<String, ResourceBinding>();
/** the server configuration */ /**
* the server configuration
*/
private RestfulServerConfiguration serverConfiguration = new RestfulServerConfiguration(); private RestfulServerConfiguration serverConfiguration = new RestfulServerConfiguration();
/** the conformance. It is created once during startup */ /**
* the conformance. It is created once during startup
*/
private org.hl7.fhir.r4.model.CapabilityStatement myR4CapabilityStatement; private org.hl7.fhir.r4.model.CapabilityStatement myR4CapabilityStatement;
private org.hl7.fhir.dstu3.model.CapabilityStatement myDstu3CapabilityStatement; private org.hl7.fhir.dstu3.model.CapabilityStatement myDstu3CapabilityStatement;
private org.hl7.fhir.dstu2016may.model.Conformance myDstu2_1Conformance; private org.hl7.fhir.dstu2016may.model.Conformance myDstu2_1Conformance;
@ -78,12 +101,9 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
/** /**
* Constructor allowing the description, servername and server to be set * Constructor allowing the description, servername and server to be set
* *
* @param implementationDescription * @param implementationDescription the implementation description. If null, "" is used
* the implementation description. If null, "" is used * @param serverName the server name. If null, "" is used
* @param serverName * @param serverVersion the server version. If null, "" is used
* the server name. If null, "" is used
* @param serverVersion
* the server version. If null, "" is used
*/ */
protected AbstractJaxRsConformanceProvider(String implementationDescription, String serverName, String serverVersion) { protected AbstractJaxRsConformanceProvider(String implementationDescription, String serverName, String serverVersion) {
serverConfiguration.setFhirContext(getFhirContext()); serverConfiguration.setFhirContext(getFhirContext());
@ -95,14 +115,10 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
/** /**
* Constructor allowing the description, servername and server to be set * Constructor allowing the description, servername and server to be set
* *
* @param ctx * @param ctx the {@link FhirContext} instance.
* the {@link FhirContext} instance. * @param implementationDescription the implementation description. If null, "" is used
* @param implementationDescription * @param serverName the server name. If null, "" is used
* the implementation description. If null, "" is used * @param serverVersion the server version. If null, "" is used
* @param serverName
* the server name. If null, "" is used
* @param serverVersion
* the server version. If null, "" is used
*/ */
protected AbstractJaxRsConformanceProvider(FhirContext ctx, String implementationDescription, String serverName, String serverVersion) { protected AbstractJaxRsConformanceProvider(FhirContext ctx, String implementationDescription, String serverName, String serverVersion) {
super(ctx); super(ctx);
@ -230,10 +246,8 @@ public abstract class AbstractJaxRsConformanceProvider extends AbstractJaxRsProv
/** /**
* This method will add a provider to the conformance. This method is almost an exact copy of {@link ca.uhn.fhir.rest.server.RestfulServer#findResourceMethods(Object)} * This method will add a provider to the conformance. This method is almost an exact copy of {@link ca.uhn.fhir.rest.server.RestfulServer#findResourceMethods(Object)}
* *
* @param theProvider * @param theProvider an instance of the provider interface
* an instance of the provider interface * @param theProviderInterface the class describing the providers interface
* @param theProviderInterface
* the class describing the providers interface
* @return the numbers of basemethodbindings added * @return the numbers of basemethodbindings added
* @see ca.uhn.fhir.rest.server.RestfulServer#findResourceMethods(Object) * @see ca.uhn.fhir.rest.server.RestfulServer#findResourceMethods(Object)
*/ */

View File

@ -23,7 +23,10 @@ package ca.uhn.fhir.jaxrs.server;
import java.io.IOException; import java.io.IOException;
import javax.interceptor.Interceptors; import javax.interceptor.Interceptors;
import javax.ws.rs.*;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;

View File

@ -23,9 +23,13 @@ import java.io.IOException;
import java.util.*; import java.util.*;
import java.util.Map.Entry; import java.util.Map.Entry;
import javax.ws.rs.core.*; import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import ca.uhn.fhir.interceptor.api.IInterceptorService; import ca.uhn.fhir.interceptor.api.IInterceptorService;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.context.FhirContext;

View File

@ -5,6 +5,7 @@ import ca.uhn.fhir.jaxrs.server.test.TestJaxRsDummyPatientProviderDstu2_1;
import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderDstu2_1; import ca.uhn.fhir.jaxrs.server.test.TestJaxRsMockPatientRestProviderDstu2_1;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.IResourceProvider;
import javax.ws.rs.core.MultivaluedMap;
import org.jboss.resteasy.specimpl.ResteasyHttpHeaders; import org.jboss.resteasy.specimpl.ResteasyHttpHeaders;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -16,7 +17,8 @@ import java.net.URI;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -27,7 +29,7 @@ public class AbstractJaxRsConformanceProviderDstu2_1Test {
AbstractJaxRsConformanceProvider provider; AbstractJaxRsConformanceProvider provider;
private ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers; private ConcurrentHashMap<Class<? extends IResourceProvider>, IResourceProvider> providers;
private ResteasyHttpHeaders headers; private ResteasyHttpHeaders headers;
private MultivaluedHashMap<String, String> queryParameters; private MultivaluedMap<String, String> queryParameters;
@BeforeEach @BeforeEach
public void setUp() throws Exception { public void setUp() throws Exception {

View File

@ -14,7 +14,6 @@ import ca.uhn.fhir.rest.api.SearchStyleEnum;
import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor;
import ca.uhn.fhir.rest.param.StringAndListParam;
import ca.uhn.fhir.rest.param.StringParam; import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.test.utilities.JettyUtil; import ca.uhn.fhir.test.utilities.JettyUtil;
@ -36,6 +35,7 @@ import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.dstu3.model.StringType; import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IBaseResource;
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -68,12 +68,9 @@ import static org.mockito.Mockito.when;
public class AbstractJaxRsResourceProviderDstu3Test { public class AbstractJaxRsResourceProviderDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AbstractJaxRsResourceProviderDstu3Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AbstractJaxRsResourceProviderDstu3Test.class);
private static IGenericClient client;
private static FhirContext ourCtx = FhirContext.forDstu3();
private static final String PATIENT_NAME = "Van Houte"; private static final String PATIENT_NAME = "Van Houte";
private static IGenericClient client;
private static FhirContext ourCtx = FhirContext.forDstu3();
private static int ourPort; private static int ourPort;
private static String serverBase; private static String serverBase;
private static Server jettyServer; private static Server jettyServer;
@ -86,12 +83,6 @@ public class AbstractJaxRsResourceProviderDstu3Test {
assertEquals(id, Integer.parseInt(resource.getIdElement().getIdPart())); assertEquals(id, Integer.parseInt(resource.getIdElement().getIdPart()));
} }
@AfterAll
public static void afterClassClearContext() throws Exception {
JettyUtil.closeServer(jettyServer);
TestUtil.randomizeLocaleAndTimezone();
}
private void compareResultUrl(String url, IBaseResource resource) { private void compareResultUrl(String url, IBaseResource resource) {
assertEquals(url, resource.getIdElement().getValueAsString().substring(serverBase.length() - 1)); assertEquals(url, resource.getIdElement().getValueAsString().substring(serverBase.length() - 1));
} }
@ -110,7 +101,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
return result; return result;
} }
/** Find By Id */ /**
* Find By Id
*/
@Test @Test
public void findUsingGenericClientById() { public void findUsingGenericClientById() {
when(mock.find(any(IdType.class))).thenReturn(createPatient(1)); when(mock.find(any(IdType.class))).thenReturn(createPatient(1));
@ -144,7 +137,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
reset(mock); reset(mock);
} }
/** Conditional Creates */ /**
* Conditional Creates
*/
@Test @Test
public void testConditionalCreate() throws Exception { public void testConditionalCreate() throws Exception {
Patient toCreate = createPatient(1); Patient toCreate = createPatient(1);
@ -163,7 +158,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
compareResultId(1, resource); compareResultId(1, resource);
} }
/** Conformance - Server */ /**
* Conformance - Server
*/
@Test @Test
public void testConformance() { public void testConformance() {
final CapabilityStatement conf = client.fetchConformance().ofType(CapabilityStatement.class).execute(); final CapabilityStatement conf = client.fetchConformance().ofType(CapabilityStatement.class).execute();
@ -200,7 +197,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
assertEquals("Patient?identifier=2&_format=json", conditionalCaptor.getValue()); assertEquals("Patient?identifier=2&_format=json", conditionalCaptor.getValue());
} }
/** Extended Operations */ /**
* Extended Operations
*/
@Test @Test
public void testExtendedOperations() { public void testExtendedOperations() {
// prepare mock // prepare mock
@ -216,21 +215,7 @@ public class AbstractJaxRsResourceProviderDstu3Test {
Parameters outParams = client.operation().onInstance(new IdType("Patient", "1")).named("$someCustomOperation") Parameters outParams = client.operation().onInstance(new IdType("Patient", "1")).named("$someCustomOperation")
.withParameters(inParams).execute(); .withParameters(inParams).execute();
//verify //verify
assertEquals("outputValue", ((StringType)outParams.getParameter().get(0).getValue()).getValueAsString()); assertEquals("outputValue", ((StringType) outParams.getParameter().get(0).getValue()).getValueAsString());
}
class StringTypeMatcher implements ArgumentMatcher<StringType> {
private StringType myStringType;
public StringTypeMatcher(StringType stringType) {
myStringType = stringType;
}
@Override
public boolean matches(StringType argument) {
return myStringType.getValue().equals(argument.getValue());
}
} }
@Test @Test
@ -255,7 +240,7 @@ public class AbstractJaxRsResourceProviderDstu3Test {
.execute(); .execute();
// verify // verify
assertEquals("outputValue", ((StringType)outParams.getParameter().get(0).getValue()).getValueAsString()); assertEquals("outputValue", ((StringType) outParams.getParameter().get(0).getValue()).getValueAsString());
} }
@Test @Test
@ -267,7 +252,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
assertEquals("1", idCaptor.getValue().getIdPart()); assertEquals("1", idCaptor.getValue().getIdPart());
} }
/** Search - Compartments */ /**
* Search - Compartments
*/
@Test @Test
public void testSearchCompartments() { public void testSearchCompartments() {
when(mock.searchCompartment(any(IdType.class))).thenReturn(Arrays.asList((IBaseResource) createPatient(1))); when(mock.searchCompartment(any(IdType.class))).thenReturn(Arrays.asList((IBaseResource) createPatient(1)));
@ -278,7 +265,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
compareResultUrl("/Patient/1", resource); compareResultUrl("/Patient/1", resource);
} }
/** */ /**
*
*/
@Test @Test
public void testSearchPost() { public void testSearchPost() {
when(mock.search(ArgumentMatchers.isNull(), ArgumentMatchers.isNull())) when(mock.search(ArgumentMatchers.isNull(), ArgumentMatchers.isNull()))
@ -290,7 +279,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
compareResultUrl("/Patient/1", resource); compareResultUrl("/Patient/1", resource);
} }
/** Search/Query - Type */ /**
* Search/Query - Type
*/
@Test @Test
public void testSearchUsingGenericClientBySearch() { public void testSearchUsingGenericClientBySearch() {
// Perform a search // Perform a search
@ -305,7 +296,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
compareResultUrl("/Patient/1", resource); compareResultUrl("/Patient/1", resource);
} }
/** Search - Multi-valued Parameters (ANY/OR) */ /**
* Search - Multi-valued Parameters (ANY/OR)
*/
@Test @Test
public void testSearchUsingGenericClientBySearchWithMultiValues() { public void testSearchUsingGenericClientBySearchWithMultiValues() {
when(mock.search(any(StringParam.class), ArgumentMatchers.notNull())) when(mock.search(any(StringParam.class), ArgumentMatchers.notNull()))
@ -320,7 +313,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
compareResultUrl("/Patient/1", resource); compareResultUrl("/Patient/1", resource);
} }
/** Search - Paging */ /**
* Search - Paging
*/
@Test @Test
public void testSearchWithPaging() { public void testSearchWithPaging() {
// Perform a search // Perform a search
@ -348,7 +343,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
assertNull(nextPage.getLink(org.hl7.fhir.dstu3.model.Bundle.LINK_NEXT)); assertNull(nextPage.getLink(org.hl7.fhir.dstu3.model.Bundle.LINK_NEXT));
} }
/** Search - Subsetting (_summary and _elements) */ /**
* Search - Subsetting (_summary and _elements)
*/
@Test @Test
@Disabled @Disabled
public void testSummary() { public void testSummary() {
@ -356,7 +353,9 @@ public class AbstractJaxRsResourceProviderDstu3Test {
.returnBundle(org.hl7.fhir.dstu3.model.Bundle.class).execute(); .returnBundle(org.hl7.fhir.dstu3.model.Bundle.class).execute();
} }
/** Transaction - Server */ /**
* Transaction - Server
*/
// @Disabled // @Disabled
// @Test // @Test
// public void testTransaction() { // public void testTransaction() {
@ -371,7 +370,6 @@ public class AbstractJaxRsResourceProviderDstu3Test {
// entry.setTransactionMethod(theTransactionOperation); // entry.setTransactionMethod(theTransactionOperation);
// ca.uhn.fhir.model.api.Bundle response = client.transaction().withBundle(bundle).execute(); // ca.uhn.fhir.model.api.Bundle response = client.transaction().withBundle(bundle).execute();
// } // }
@Test @Test
public void testUpdateById() throws Exception { public void testUpdateById() throws Exception {
when(mock.update(idCaptor.capture(), patientCaptor.capture(), conditionalCaptor.capture())).thenReturn(new MethodOutcome()); when(mock.update(idCaptor.capture(), patientCaptor.capture(), conditionalCaptor.capture())).thenReturn(new MethodOutcome());
@ -441,13 +439,33 @@ public class AbstractJaxRsResourceProviderDstu3Test {
assertNotNull(mO.getOperationOutcome()); assertNotNull(mO.getOperationOutcome());
} }
class StringTypeMatcher implements ArgumentMatcher<StringType> {
private StringType myStringType;
public StringTypeMatcher(StringType stringType) {
myStringType = stringType;
}
@Override
public boolean matches(StringType argument) {
return myStringType.getValue().equals(argument.getValue());
}
}
@AfterAll
public static void afterClassClearContext() throws Exception {
JettyUtil.closeServer(jettyServer);
TestUtil.randomizeLocaleAndTimezone();
}
@BeforeAll @BeforeAll
public static void setUpClass() throws Exception { public static void setUpClass() throws Exception {
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/"); context.setContextPath("/");
jettyServer = new Server(0); jettyServer = new Server(0);
jettyServer.setHandler(context); jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.class, "/*"); ServletHolder jerseyServlet = context.addServlet(HttpServletDispatcher.class, "/*");
jerseyServlet.setInitOrder(0); jerseyServlet.setInitOrder(0);
//@formatter:off //@formatter:off

View File

@ -439,7 +439,7 @@ public class AbstractJaxRsResourceProviderTest {
context.setContextPath("/"); context.setContextPath("/");
jettyServer = new Server(0); jettyServer = new Server(0);
jettyServer.setHandler(context); jettyServer.setHandler(context);
ServletHolder jerseyServlet = context.addServlet(org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.class, "/*"); ServletHolder jerseyServlet = context.addServlet(org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher.class, "/*");
jerseyServlet.setInitOrder(0); jerseyServlet.setInitOrder(0);
//@formatter:off //@formatter:off

View File

@ -1,22 +1,21 @@
package ca.uhn.fhir.jaxrs.server.test; package ca.uhn.fhir.jaxrs.server.test;
import java.util.concurrent.ConcurrentHashMap;
import javax.ejb.Stateless;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import ca.uhn.fhir.jaxrs.server.AbstractJaxRsConformanceProvider; import ca.uhn.fhir.jaxrs.server.AbstractJaxRsConformanceProvider;
import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.IResourceProvider;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ejb.Stateless;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* A conformance provider exposes the mock patient and this provider * A conformance provider exposes the mock patient and this provider
*/ */
@Path("") @Path("")
@Stateless @Stateless
@Produces({ MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML }) @Produces({MediaType.APPLICATION_JSON, Constants.CT_FHIR_JSON, Constants.CT_FHIR_XML})
public class TestJaxRsConformanceRestProvider extends AbstractJaxRsConformanceProvider { public class TestJaxRsConformanceRestProvider extends AbstractJaxRsConformanceProvider {
public TestJaxRsConformanceRestProvider() { public TestJaxRsConformanceRestProvider() {

View File

@ -3,6 +3,7 @@ package ca.uhn.fhir.jaxrs.server.test;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import javax.ejb.Stateless; import javax.ejb.Stateless;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;

View File

@ -50,6 +50,7 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry; import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.test.BaseTest; import ca.uhn.fhir.test.BaseTest;
import ca.uhn.fhir.test.utilities.BatchJobHelper;
import ca.uhn.fhir.test.utilities.LoggingExtension; import ca.uhn.fhir.test.utilities.LoggingExtension;
import ca.uhn.fhir.test.utilities.ProxyUtil; import ca.uhn.fhir.test.utilities.ProxyUtil;
import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor; import ca.uhn.fhir.test.utilities.UnregisterScheduledProcessor;
@ -81,6 +82,10 @@ import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.Answers; import org.mockito.Answers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import org.springframework.batch.core.repository.dao.JobExecutionDao;
import org.springframework.batch.core.repository.dao.JobInstanceDao;
import org.springframework.batch.core.repository.dao.MapJobExecutionDao;
import org.springframework.batch.core.repository.dao.MapJobInstanceDao;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager;
@ -195,6 +200,21 @@ public abstract class BaseJpaTest extends BaseTest {
private IForcedIdDao myForcedIdDao; private IForcedIdDao myForcedIdDao;
@Autowired(required = false) @Autowired(required = false)
protected IFulltextSearchSvc myFulltestSearchSvc; protected IFulltextSearchSvc myFulltestSearchSvc;
@Autowired(required = false)
protected BatchJobHelper myBatchJobHelper;
@Autowired(required = false)
private JobExecutionDao myMapJobExecutionDao;
@Autowired(required = false)
private JobInstanceDao myMapJobInstanceDao;
@AfterEach
public void afterEnsureNoStaleBatchJobs() {
if (myMapJobInstanceDao != null) {
myBatchJobHelper.ensureNoRunningJobs();
ProxyUtil.getSingletonTarget(myMapJobExecutionDao, MapJobExecutionDao.class).clear();
ProxyUtil.getSingletonTarget(myMapJobInstanceDao, MapJobInstanceDao.class).clear();
}
}
@AfterEach @AfterEach
public void afterPerformCleanup() { public void afterPerformCleanup() {

View File

@ -87,7 +87,9 @@ import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.server.BasePagingProvider; import ca.uhn.fhir.rest.server.BasePagingProvider;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory; import ca.uhn.fhir.rest.server.provider.ResourceProviderFactory;
import ca.uhn.fhir.test.utilities.BatchJobHelper;
import ca.uhn.fhir.test.utilities.ITestDataBuilder; import ca.uhn.fhir.test.utilities.ITestDataBuilder;
import ca.uhn.fhir.test.utilities.ProxyUtil;
import ca.uhn.fhir.util.ClasspathUtil; import ca.uhn.fhir.util.ClasspathUtil;
import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.validation.FhirValidator; import ca.uhn.fhir.validation.FhirValidator;
@ -171,6 +173,10 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.event.Level; import org.slf4j.event.Level;
import org.springframework.batch.core.repository.dao.JobExecutionDao;
import org.springframework.batch.core.repository.dao.JobInstanceDao;
import org.springframework.batch.core.repository.dao.MapJobExecutionDao;
import org.springframework.batch.core.repository.dao.MapJobInstanceDao;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
@ -492,11 +498,6 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
@Autowired @Autowired
protected DaoRegistry myDaoRegistry; protected DaoRegistry myDaoRegistry;
@Autowired @Autowired
private IValidationSupport myJpaValidationSupportChainR4;
private PerformanceTracingLoggingInterceptor myPerformanceTracingLoggingInterceptor;
@Autowired
private IBulkDataExportSvc myBulkDataExportSvc;
@Autowired
protected IdHelperService myIdHelperService; protected IdHelperService myIdHelperService;
@Autowired @Autowired
protected IBatchJobSubmitter myBatchJobSubmitter; protected IBatchJobSubmitter myBatchJobSubmitter;
@ -504,6 +505,11 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
protected ValidationSettings myValidationSettings; protected ValidationSettings myValidationSettings;
@Autowired @Autowired
protected IMdmLinkDao myMdmLinkDao; protected IMdmLinkDao myMdmLinkDao;
@Autowired
private IValidationSupport myJpaValidationSupportChainR4;
private PerformanceTracingLoggingInterceptor myPerformanceTracingLoggingInterceptor;
@Autowired
private IBulkDataExportSvc myBulkDataExportSvc;
@AfterEach() @AfterEach()
public void afterCleanupDao() { public void afterCleanupDao() {
@ -564,7 +570,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
@AfterEach @AfterEach
public void afterPurgeDatabase() { public void afterPurgeDatabase() {
runInTransaction(()->{ runInTransaction(() -> {
myMdmLinkDao.deleteAll(); myMdmLinkDao.deleteAll();
}); });
purgeDatabase(myDaoConfig, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegistry, myBulkDataExportSvc); purgeDatabase(myDaoConfig, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegistry, myBulkDataExportSvc);
@ -623,23 +629,6 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
} }
} }
public class ValidationPolicyAdvisor implements IValidationPolicyAdvisor {
@Override
public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) {
return ReferenceValidationPolicy.CHECK_VALID;
}
@Override
public CodedContentValidationPolicy policyForCodedContent(IResourceValidator iResourceValidator, Object o, String s, ElementDefinition elementDefinition, org.hl7.fhir.r5.model.StructureDefinition structureDefinition, BindingKind bindingKind, org.hl7.fhir.r5.model.ValueSet valueSet, List<String> list) {
return CodedContentValidationPolicy.CODE;
}
@Override
public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext, String containerType, String containerId, Element.SpecialElement containingResourceType, String path, String url) {
return ContainedReferenceValidationPolicy.CHECK_VALID;
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected void upload(String theClasspath) throws IOException { protected void upload(String theClasspath) throws IOException {
String resource = loadResource(theClasspath); String resource = loadResource(theClasspath);
@ -649,7 +638,6 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
dao.update(resourceParsed); dao.update(resourceParsed);
} }
protected void assertHierarchyContains(String... theStrings) { protected void assertHierarchyContains(String... theStrings) {
List<String> hierarchy = runInTransaction(() -> { List<String> hierarchy = runInTransaction(() -> {
List<String> hierarchyHolder = new ArrayList<>(); List<String> hierarchyHolder = new ArrayList<>();
@ -667,6 +655,72 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
} }
} }
protected ValueSet.ConceptReferenceDesignationComponent assertConceptContainsDesignation(ValueSet.ValueSetExpansionContainsComponent theConcept, String theLanguage, String theUseSystem, String theUseCode, String theUseDisplay, String theDesignationValue) {
Stream<ValueSet.ConceptReferenceDesignationComponent> stream = theConcept.getDesignation().stream();
if (theLanguage != null) {
stream = stream.filter(designation -> theLanguage.equalsIgnoreCase(designation.getLanguage()));
}
if (theUseSystem != null) {
stream = stream.filter(designation -> theUseSystem.equalsIgnoreCase(designation.getUse().getSystem()));
}
if (theUseCode != null) {
stream = stream.filter(designation -> theUseCode.equalsIgnoreCase(designation.getUse().getCode()));
}
if (theUseDisplay != null) {
stream = stream.filter(designation -> theUseDisplay.equalsIgnoreCase(designation.getUse().getDisplay()));
}
if (theDesignationValue != null) {
stream = stream.filter(designation -> theDesignationValue.equalsIgnoreCase(designation.getValue()));
}
Optional<ValueSet.ConceptReferenceDesignationComponent> first = stream.findFirst();
if (!first.isPresent()) {
String failureMessage = String.format("Concept %s did not contain designation [%s|%s|%s|%s|%s] ", theConcept, theLanguage, theUseSystem, theUseCode, theUseDisplay, theDesignationValue);
fail(failureMessage);
return null;
} else {
return first.get();
}
}
protected ValueSet.ValueSetExpansionContainsComponent assertExpandedValueSetContainsConcept(ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Integer theDesignationCount) {
List<ValueSet.ValueSetExpansionContainsComponent> contains = theValueSet.getExpansion().getContains();
Stream<ValueSet.ValueSetExpansionContainsComponent> stream = contains.stream();
if (theSystem != null) {
stream = stream.filter(concept -> theSystem.equalsIgnoreCase(concept.getSystem()));
}
if (theCode != null) {
stream = stream.filter(concept -> theCode.equalsIgnoreCase(concept.getCode()));
}
if (theDisplay != null) {
stream = stream.filter(concept -> theDisplay.equalsIgnoreCase(concept.getDisplay()));
}
if (theDesignationCount != null) {
stream = stream.filter(concept -> concept.getDesignation().size() == theDesignationCount);
}
Optional<ValueSet.ValueSetExpansionContainsComponent> first = stream.findFirst();
if (!first.isPresent()) {
String expandedValueSetString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(theValueSet);
String failureMessage = String.format("Expanded ValueSet %s did not contain concept [%s|%s|%s] with [%d] designations. Outcome:\n%s", theValueSet.getId(), theSystem, theCode, theDisplay, theDesignationCount, expandedValueSetString);
fail(failureMessage);
return null;
} else {
return first.get();
}
}
public List<String> getExpandedConceptsByValueSetUrl(String theValuesetUrl) {
return runInTransaction(() -> {
List<TermValueSet> valueSets = myTermValueSetDao.findTermValueSetByUrl(Pageable.unpaged(), theValuesetUrl);
assertEquals(1, valueSets.size());
TermValueSet valueSet = valueSets.get(0);
List<TermValueSetConcept> concepts = valueSet.getConcepts();
return concepts.stream().map(concept -> concept.getCode()).collect(Collectors.toList());
});
}
private static void flattenExpansionHierarchy(List<String> theFlattenedHierarchy, List<TermConcept> theCodes, String thePrefix) { private static void flattenExpansionHierarchy(List<String> theFlattenedHierarchy, List<TermConcept> theCodes, String thePrefix) {
theCodes.sort((o1, o2) -> { theCodes.sort((o1, o2) -> {
int s1 = o1.getSequence() != null ? o1.getSequence() : o1.getCode().hashCode(); int s1 = o1.getSequence() != null ? o1.getSequence() : o1.getCode().hashCode();
@ -796,70 +850,20 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
return uuid; return uuid;
} }
public class ValidationPolicyAdvisor implements IValidationPolicyAdvisor {
protected ValueSet.ConceptReferenceDesignationComponent assertConceptContainsDesignation(ValueSet.ValueSetExpansionContainsComponent theConcept, String theLanguage, String theUseSystem, String theUseCode, String theUseDisplay, String theDesignationValue) { @Override
Stream<ValueSet.ConceptReferenceDesignationComponent> stream = theConcept.getDesignation().stream(); public ReferenceValidationPolicy policyForReference(IResourceValidator validator, Object appContext, String path, String url) {
if (theLanguage != null) { return ReferenceValidationPolicy.CHECK_VALID;
stream = stream.filter(designation -> theLanguage.equalsIgnoreCase(designation.getLanguage()));
}
if (theUseSystem != null) {
stream = stream.filter(designation -> theUseSystem.equalsIgnoreCase(designation.getUse().getSystem()));
}
if (theUseCode != null) {
stream = stream.filter(designation -> theUseCode.equalsIgnoreCase(designation.getUse().getCode()));
}
if (theUseDisplay != null) {
stream = stream.filter(designation -> theUseDisplay.equalsIgnoreCase(designation.getUse().getDisplay()));
}
if (theDesignationValue != null) {
stream = stream.filter(designation -> theDesignationValue.equalsIgnoreCase(designation.getValue()));
} }
Optional<ValueSet.ConceptReferenceDesignationComponent> first = stream.findFirst(); @Override
if (!first.isPresent()) { public CodedContentValidationPolicy policyForCodedContent(IResourceValidator iResourceValidator, Object o, String s, ElementDefinition elementDefinition, org.hl7.fhir.r5.model.StructureDefinition structureDefinition, BindingKind bindingKind, org.hl7.fhir.r5.model.ValueSet valueSet, List<String> list) {
String failureMessage = String.format("Concept %s did not contain designation [%s|%s|%s|%s|%s] ", theConcept, theLanguage, theUseSystem, theUseCode, theUseDisplay, theDesignationValue); return CodedContentValidationPolicy.CODE;
fail(failureMessage);
return null;
} else {
return first.get();
}
} }
protected ValueSet.ValueSetExpansionContainsComponent assertExpandedValueSetContainsConcept(ValueSet theValueSet, String theSystem, String theCode, String theDisplay, Integer theDesignationCount) { @Override
List<ValueSet.ValueSetExpansionContainsComponent> contains = theValueSet.getExpansion().getContains(); public ContainedReferenceValidationPolicy policyForContained(IResourceValidator validator, Object appContext, String containerType, String containerId, Element.SpecialElement containingResourceType, String path, String url) {
return ContainedReferenceValidationPolicy.CHECK_VALID;
Stream<ValueSet.ValueSetExpansionContainsComponent> stream = contains.stream();
if (theSystem != null) {
stream = stream.filter(concept -> theSystem.equalsIgnoreCase(concept.getSystem()));
} }
if (theCode != null) {
stream = stream.filter(concept -> theCode.equalsIgnoreCase(concept.getCode()));
}
if (theDisplay != null) {
stream = stream.filter(concept -> theDisplay.equalsIgnoreCase(concept.getDisplay()));
}
if (theDesignationCount != null) {
stream = stream.filter(concept -> concept.getDesignation().size() == theDesignationCount);
}
Optional<ValueSet.ValueSetExpansionContainsComponent> first = stream.findFirst();
if (!first.isPresent()) {
String expandedValueSetString = myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(theValueSet);
String failureMessage = String.format("Expanded ValueSet %s did not contain concept [%s|%s|%s] with [%d] designations. Outcome:\n%s", theValueSet.getId(), theSystem, theCode, theDisplay, theDesignationCount, expandedValueSetString);
fail(failureMessage);
return null;
} else {
return first.get();
}
}
public List<String> getExpandedConceptsByValueSetUrl(String theValuesetUrl) {
return runInTransaction(() -> {
List<TermValueSet> valueSets = myTermValueSetDao.findTermValueSetByUrl(Pageable.unpaged(), theValuesetUrl);
assertEquals(1, valueSets.size());
TermValueSet valueSet = valueSets.get(0);
List<TermValueSetConcept> concepts = valueSet.getConcepts();
return concepts.stream().map(concept -> concept.getCode()).collect(Collectors.toList());
});
} }
} }

View File

@ -158,9 +158,6 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4Test.class); private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4Test.class);
@Autowired
private BatchJobHelper myBatchJobHelper;
@AfterEach @AfterEach
public final void after() { public final void after() {
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences()); myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());

View File

@ -20,6 +20,9 @@ package ca.uhn.fhir.test.utilities;
* #L% * #L%
*/ */
import ca.uhn.fhir.util.StopWatch;
import org.awaitility.core.ConditionTimeoutException;
import org.hamcrest.Matchers;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.BatchStatus;
@ -37,7 +40,11 @@ import java.util.stream.Collectors;
import static org.awaitility.Awaitility.await; import static org.awaitility.Awaitility.await;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.oneOf;
import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.fail;
public class BatchJobHelper { public class BatchJobHelper {
@ -55,6 +62,7 @@ public class BatchJobHelper {
/** /**
* Await and report for job completions * Await and report for job completions
*
* @param theFailIfNotJobsFound indicate if must fail in case no matching jobs are found * @param theFailIfNotJobsFound indicate if must fail in case no matching jobs are found
* @param theJobNames The job names to match * @param theJobNames The job names to match
* @return the matched JobExecution(s) * @return the matched JobExecution(s)
@ -63,7 +71,9 @@ public class BatchJobHelper {
assert theJobNames.length > 0; assert theJobNames.length > 0;
if (theFailIfNotJobsFound) { if (theFailIfNotJobsFound) {
await().until(() -> !getJobInstances(theJobNames).isEmpty()); await()
.alias("Wait for jobs to exist named: " + Arrays.asList(theJobNames))
.until(() -> getJobInstances(theJobNames), not(empty()));
} }
List<JobInstance> matchingJobInstances = getJobInstances(theJobNames); List<JobInstance> matchingJobInstances = getJobInstances(theJobNames);
@ -97,19 +107,43 @@ public class BatchJobHelper {
} }
protected void awaitJobCompletions(Collection<JobExecution> theJobs) { protected void awaitJobCompletions(Collection<JobExecution> theJobs) {
theJobs.forEach(jobExecution -> awaitJobCompletion(jobExecution)); // This intermittently fails for unknown reasons, so I've added a bunch
// of extra junk here to improve what we output when it fails
for (JobExecution jobExecution : theJobs) {
try {
awaitJobCompletion(jobExecution);
} catch (ConditionTimeoutException e) {
StringBuilder msg = new StringBuilder();
msg.append("Failed waiting for job to complete.\n");
msg.append("Error: ").append(e).append("\n");
msg.append("Statuses:");
for (JobExecution next : theJobs) {
JobExecution execution = myJobExplorer.getJobExecution(next.getId());
msg.append("\n * Execution ")
.append(execution.getId())
.append(" has status ")
.append(execution.getStatus());
}
fail(msg.toString());
}
}
} }
public void awaitJobCompletion(JobExecution theJobExecution) { public void awaitJobCompletion(JobExecution theJobExecution) {
await().atMost(120, TimeUnit.SECONDS).until(() -> { await()
.atMost(120, TimeUnit.SECONDS).until(() -> {
JobExecution jobExecution = myJobExplorer.getJobExecution(theJobExecution.getId()); JobExecution jobExecution = myJobExplorer.getJobExecution(theJobExecution.getId());
ourLog.info("JobExecution {} currently has status: {}- Failures if any: {}", theJobExecution.getId(), jobExecution.getStatus(), jobExecution.getFailureExceptions()); ourLog.info("JobExecution {} currently has status: {}- Failures if any: {}", theJobExecution.getId(), jobExecution.getStatus(), jobExecution.getFailureExceptions());
return jobExecution.getStatus();
}, Matchers.oneOf(
// JM: Adding ABANDONED status because given the description, it s similar to FAILURE, and we need to avoid tests failing because // JM: Adding ABANDONED status because given the description, it s similar to FAILURE, and we need to avoid tests failing because
// of wait timeouts caused by unmatched statuses. Also adding STOPPED because tests were found where this wait timed out // of wait timeouts caused by unmatched statuses. Also adding STOPPED because tests were found where this wait timed out
// with jobs keeping that status during the whole wait // with jobs keeping that status during the whole wait
return jobExecution.getStatus() == BatchStatus.COMPLETED || jobExecution.getStatus() == BatchStatus.FAILED BatchStatus.COMPLETED,
|| jobExecution.getStatus() == BatchStatus.ABANDONED || jobExecution.getStatus() == BatchStatus.STOPPED; BatchStatus.FAILED,
}); BatchStatus.ABANDONED,
BatchStatus.STOPPED
));
} }
public int getReadCount(Long theJobExecutionId) { public int getReadCount(Long theJobExecutionId) {
@ -129,4 +163,24 @@ public class BatchJobHelper {
return stepExecutions.iterator().next(); return stepExecutions.iterator().next();
} }
public void ensureNoRunningJobs() {
for (String nextJobName : myJobExplorer.getJobNames()) {
List<JobInstance> instances = myJobExplorer.getJobInstances(nextJobName, 0, 10000);
for (JobInstance nextInstance : instances) {
List<JobExecution> executions = myJobExplorer.getJobExecutions(nextInstance);
for (JobExecution nextExecution : executions) {
ourLog.info("Have job execution {} in status: {}", nextExecution.getId(), nextExecution.getStatus());
try {
await().until(() -> myJobExplorer.getJobExecution(nextExecution.getId()).getStatus(), oneOf(BatchStatus.STOPPED, BatchStatus.ABANDONED, BatchStatus.FAILED, BatchStatus.COMPLETED));
} catch (ConditionTimeoutException e) {
JobExecution execution = myJobExplorer.getJobExecution(nextExecution.getId());
fail("Execution " + execution + "\n" +
"Instance: " + nextInstance + "\n" +
"Job: " + nextJobName);
}
}
}
}
}
} }

13
pom.xml
View File

@ -825,7 +825,7 @@
<okhttp_version>3.8.1</okhttp_version> <okhttp_version>3.8.1</okhttp_version>
<poi_version>4.1.2</poi_version> <poi_version>4.1.2</poi_version>
<poi_ooxml_schemas_version>1.4</poi_ooxml_schemas_version> <poi_ooxml_schemas_version>1.4</poi_ooxml_schemas_version>
<resteasy_version>4.0.0.Beta3</resteasy_version> <resteasy_version>5.0.2.Final</resteasy_version>
<ph_schematron_version>5.6.5</ph_schematron_version> <ph_schematron_version>5.6.5</ph_schematron_version>
<ph_commons_version>9.5.4</ph_commons_version> <ph_commons_version>9.5.4</ph_commons_version>
<plexus_compiler_api_version>2.9.0</plexus_compiler_api_version> <plexus_compiler_api_version>2.9.0</plexus_compiler_api_version>
@ -1156,11 +1156,6 @@
<artifactId>validation-api</artifactId> <artifactId>validation-api</artifactId>
<version>2.0.1.Final</version> <version>2.0.1.Final</version>
</dependency> </dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0.1</version>
</dependency>
<dependency> <dependency>
<!-- <!--
We use JUnit 5 in HAPI FHIR, but some libraries still pull in / require JUnit 4 We use JUnit 5 in HAPI FHIR, but some libraries still pull in / require JUnit 4
@ -1531,9 +1526,9 @@
<version>${jersey_version}</version> <version>${jersey_version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.spec.javax.ws.rs</groupId>
<artifactId>resteasy-jaxrs</artifactId> <artifactId>jboss-jaxrs-api_2.1_spec</artifactId>
<version>${resteasy_version}</version> <version>2.0.1.Final</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>

View File

@ -71,10 +71,6 @@
<artifactId>jetty-servlet</artifactId> <artifactId>jetty-servlet</artifactId>
<version>${jetty_version}</version> <version>${jetty_version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId> <artifactId>resteasy-client</artifactId>

View File

@ -8,7 +8,6 @@ import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.ServletContextHandler import org.eclipse.jetty.servlet.ServletContextHandler
import org.hamcrest.CoreMatchers.`is` import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.MatcherAssert.assertThat
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder
import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.BeforeAll
@ -19,7 +18,7 @@ class ExtendedOrganizationResourceTest {
@Test @Test
fun makeSureSearchDoesNotThrowOnIncludeParam() { fun makeSureSearchDoesNotThrowOnIncludeParam() {
val response = ResteasyClientBuilder() val response = org.jboss.resteasy.client.jaxrs.internal.ResteasyClientBuilderImpl()
.build() .build()
.target("http://localhost:$ourPort/Organization?_id=1") .target("http://localhost:$ourPort/Organization?_id=1")
.request() .request()