diff --git a/.github/workflows/smoke-tests.yml b/.github/workflows/smoke-tests.yml index eda72e854d3..6e76e829d58 100644 --- a/.github/workflows/smoke-tests.yml +++ b/.github/workflows/smoke-tests.yml @@ -33,7 +33,7 @@ jobs: run: docker pull jetbrains/intellij-http-client - name: Start server with jetty run: | - mvn -Pjetty jetty:run & export JPA_PROCESS=$! + mvn -P jetty spring-boot:run & export JPA_PROCESS=$! sleep 80 - name: Execute smoke tests run: docker run --rm -v $PWD:/workdir --add-host host.docker.internal:host-gateway jetbrains/intellij-http-client -D src/test/smoketest/plain_server.http --env-file src/test/smoketest/http-client.env.json --env default diff --git a/pom.xml b/pom.xml index 1b8fee45e9a..06092a3c039 100644 --- a/pom.xml +++ b/pom.xml @@ -14,7 +14,7 @@ ca.uhn.hapi.fhir hapi-fhir - 6.10.0 + 7.0.0 hapi-fhir-jpaserver-starter @@ -22,8 +22,6 @@ 11 - 1.2.11 - 1.7.25 @@ -53,16 +51,7 @@ - - org.eclipse.jetty.websocket - websocket-jetty-api - ${jetty_version} - - - org.eclipse.jetty.websocket - websocket-jetty-client - ${jetty_version} - + org.postgresql postgresql @@ -180,11 +169,15 @@ ch.qos.logback logback-classic + + ch.qos.logback + logback-core + - javax.servlet - javax.servlet-api + jakarta.servlet + jakarta.servlet-api provided @@ -201,6 +194,14 @@ spring-web + + + commons-logging + commons-logging + 1.2 + provided + + org.apache.commons @@ -251,6 +252,12 @@ + + co.elastic.clients + elasticsearch-java + test + + ca.uhn.hapi.fhir hapi-fhir-jpaserver-test-utilities @@ -263,36 +270,7 @@ - - org.eclipse.jetty - jetty-servlets - test - - - org.eclipse.jetty - jetty-servlet - test - - - org.eclipse.jetty.websocket - websocket-jetty-server - test - - - org.eclipse.jetty - jetty-server - test - - - org.eclipse.jetty - jetty-util - test - - - org.eclipse.jetty - jetty-webapp - test - + org.testcontainers testcontainers @@ -314,8 +292,8 @@ For some reason JavaDoc crashed during site generation unless we have this dependency --> - javax.interceptor - javax.interceptor-api + jakarta.interceptor + jakarta.interceptor-api provided @@ -324,6 +302,24 @@ hapi-fhir-test-utilities ${project.version} test + + + org.eclipse.jetty.ee10 + * + + + org.eclipse.jetty.ee10.websocket + * + + + org.eclipse.jetty + * + + + org.eclipse.jetty.websocket + * + + @@ -369,40 +365,20 @@ org.junit.jupiter junit-jupiter-api - 5.7.2 test org.junit.jupiter junit-jupiter-engine - 5.7.2 test org.springframework.boot spring-boot-starter-test - ${spring_boot_version} test - - org.slf4j - slf4j-api - ${slf4j-api.version} - - - - ch.qos.logback - logback-classic - ${logback-classic.version} - - - ch.qos.logback - logback-core - ${logback-classic.version} - - @@ -429,6 +405,14 @@ org.springframework.boot spring-boot-maven-plugin + + + CLASSIC + @@ -629,6 +613,11 @@ + + org.springframework.boot + spring-boot-starter-jetty + ${spring_boot_version} + diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java index 4f72c4a976d..bec7871ea50 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/Application.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/Application.java @@ -4,7 +4,6 @@ import ca.uhn.fhir.jpa.batch2.JpaBatch2Config; import ca.uhn.fhir.jpa.starter.annotations.OnEitherVersion; import ca.uhn.fhir.jpa.starter.cdshooks.StarterCdsHooksConfig; -import ca.uhn.fhir.jpa.starter.common.FhirTesterConfig; import ca.uhn.fhir.jpa.starter.cr.StarterCrDstu3Config; import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config; import ca.uhn.fhir.jpa.starter.mdm.MdmConfig; @@ -19,15 +18,12 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; -import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Import; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; @ServletComponentScan(basePackageClasses = {RestfulServer.class}) @SpringBootApplication(exclude = {ElasticsearchRestClientAutoConfiguration.class, ThymeleafAutoConfiguration.class}) diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java index 5849ec528e6..9b3bf42fbff 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/CdsHooksServlet.java @@ -19,10 +19,10 @@ import java.io.IOException; import java.util.stream.Collectors; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import static ca.uhn.hapi.fhir.cdshooks.config.CdsHooksConfig.CDS_HOOKS_OBJECT_MAPPER_FACTORY; diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java index 38e8d7b4760..bbdaa43470c 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/cdshooks/ErrorHandling.java @@ -7,7 +7,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponse; public class ErrorHandling { diff --git a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java index 2a2de60f0a5..01ff15b74d1 100644 --- a/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java +++ b/src/main/java/ca/uhn/fhir/jpa/starter/common/StarterJpaConfig.java @@ -62,6 +62,7 @@ import ca.uhn.fhir.validation.IValidatorModule; import ca.uhn.fhir.validation.ResultSeverityEnum; import com.google.common.base.Strings; +import jakarta.persistence.EntityManagerFactory; import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; @@ -76,7 +77,6 @@ import org.springframework.web.cors.CorsConfiguration; import java.util.*; -import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import static ca.uhn.fhir.jpa.starter.common.validation.IRepositoryValidationInterceptorFactory.ENABLE_REPOSITORY_VALIDATING_INTERCEPTOR; @@ -133,11 +133,11 @@ public ResourceCountCache resourceCountsCache(IFhirSystemDao theSystemDao) @Primary @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory( - DataSource myDataSource, - ConfigurableListableBeanFactory myConfigurableListableBeanFactory, - FhirContext theFhirContext) { + DataSource myDataSource, + ConfigurableListableBeanFactory myConfigurableListableBeanFactory, + FhirContext theFhirContext, JpaStorageSettings theStorageSettings) { LocalContainerEntityManagerFactoryBean retVal = - HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext); + HapiEntityManagerFactoryUtil.newEntityManagerFactory(myConfigurableListableBeanFactory, theFhirContext, theStorageSettings); retVal.setPersistenceUnitName("HAPI_PU"); try { diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java index d5a3d18af5e..3a7dee54843 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomBeanTest.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class}, properties = { "hapi.fhir.custom-bean-packages=some.custom.pkg1,some.custom.pkg2", "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.enable_repository_validating_interceptor=true", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java index 859752a25d9..daf64384c73 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/CustomInterceptorTest.java @@ -13,7 +13,7 @@ import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = { +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class}, properties = { "hapi.fhir.custom-bean-packages=some.custom.pkg1", "hapi.fhir.custom-interceptor-classes=some.custom.pkg1.CustomInterceptorBean,some.custom.pkg1.CustomInterceptorPojo", "spring.datasource.url=jdbc:h2:mem:dbr4", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java index 7ab7989f052..9d4c033c436 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ElasticsearchLastNR4IT.java @@ -14,12 +14,11 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.List; -import javax.annotation.PreDestroy; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.json.JsonData; +import jakarta.annotation.PreDestroy; import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.indices.PutIndexTemplateRequest; -import org.elasticsearch.common.settings.Settings; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.DateTimeType; @@ -30,13 +29,11 @@ import org.hl7.fhir.r4.model.StringType; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.test.context.ContextConfiguration; @@ -47,7 +44,7 @@ @ExtendWith(SpringExtension.class) @Testcontainers -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4", "hapi.fhir.fhir_version=r4", @@ -83,19 +80,20 @@ public class ElasticsearchLastNR4IT { @BeforeAll public static void beforeClass() throws IOException { //Given - RestHighLevelClient elasticsearchHighLevelRestClient = ElasticsearchRestClientFactory.createElasticsearchHighLevelRestClient( + ElasticsearchClient elasticsearchHighLevelRestClient = ElasticsearchRestClientFactory.createElasticsearchHighLevelRestClient( "http", embeddedElastic.getHost() + ":" + embeddedElastic.getMappedPort(9200), "", ""); /* As of 2023-08-10, HAPI FHIR sets SubscriptionConstants.MAX_SUBSCRIPTION_RESULTS to 50000 which is in excess of elastic's default max_result_window. If MAX_SUBSCRIPTION_RESULTS is changed to a value <= 10000, the following will no longer be necessary. - dotasek */ - PutIndexTemplateRequest putIndexTemplateRequest = new PutIndexTemplateRequest("hapi_fhir_template"); - putIndexTemplateRequest.patterns(List.of("*")); - Settings settings = Settings.builder().put("index.max_result_window", 50000).build(); - putIndexTemplateRequest.settings(settings); - elasticsearchHighLevelRestClient.indices().putTemplate(putIndexTemplateRequest, RequestOptions.DEFAULT); + elasticsearchHighLevelRestClient.indices().putTemplate(t->{ + t.name("hapi_fhir_template"); + t.indexPatterns("*"); + t.settings("index.max_result_window", JsonData.of(50000)); + return t; + }); } diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java index bc88d47ce98..e8fd9ade47b 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu2IT.java @@ -10,14 +10,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; -import org.springframework.test.annotation.DirtiesContext; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class}, properties = { "hapi.fhir.fhir_version=dstu2", "spring.datasource.url=jdbc:h2:mem:dbr2", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java index 086b7993281..2aadf2ebcfc 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerDstu3IT.java @@ -10,10 +10,10 @@ import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; +import jakarta.websocket.ContainerProvider; +import jakarta.websocket.Session; +import jakarta.websocket.WebSocketContainer; import org.apache.commons.io.FileUtils; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; -import org.eclipse.jetty.websocket.client.WebSocketClient; import org.hl7.fhir.dstu3.model.*; import org.hl7.fhir.instance.model.api.IIdType; import org.junit.jupiter.api.BeforeEach; @@ -21,9 +21,8 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.core.io.ClassPathResource; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.File; @@ -31,8 +30,6 @@ import java.net.URI; import java.util.Collection; import java.util.List; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; import static ca.uhn.fhir.util.TestUtil.waitForSize; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -43,7 +40,6 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { Application.class, - JpaStarterWebsocketDispatcherConfig.class, RepositoryConfig.class }, properties = { @@ -188,17 +184,16 @@ void testWebsocketSubscription() throws Exception { * Attach websocket */ - WebSocketClient myWebSocketClient = new WebSocketClient(); - SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); + SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), + EncodingEnum.JSON); - myWebSocketClient.start(); - URI echoUri = new URI("ws://localhost:" + port + "/websocket"); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - ourLog.info("Connecting to : {}", echoUri); - Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); - Session session = connection.get(2, TimeUnit.SECONDS); + URI echoUri = new URI("ws://localhost:" + port + "/websocket"); - ourLog.info("Connected to WS: {}", session.isOpen()); + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + + ourLog.info("Connecting to : {}", echoUri); + Session session = container.connectToServer(mySocketImplementation, echoUri); + ourLog.info("Connected to WS: {}", session.isOpen()); /* * Create a matching resource diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java index 82e48a36487..46acecd3975 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4BIT.java @@ -10,12 +10,12 @@ import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import static org.junit.jupiter.api.Assertions.assertEquals; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, + classes = {Application.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4b", "hapi.fhir.enable_repository_validating_interceptor=true", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java index b41eed59e58..9c0f85d0c9d 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR4IT.java @@ -1,39 +1,50 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.cr.config.RepositoryConfig; import ca.uhn.fhir.jpa.searchparam.config.NicknameServiceConfig; import ca.uhn.fhir.jpa.starter.cr.CrProperties; +import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.EncodingEnum; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; -import org.eclipse.jetty.websocket.client.WebSocketClient; +import jakarta.websocket.ContainerProvider; +import jakarta.websocket.Session; +import jakarta.websocket.WebSocketContainer; import org.hl7.fhir.instance.model.api.IBaseResource; -import org.hl7.fhir.r4.model.*; import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.DateType; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Measure; +import org.hl7.fhir.r4.model.MeasureReport; +import org.hl7.fhir.r4.model.Observation; +import org.hl7.fhir.r4.model.Parameters; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Period; +import org.hl7.fhir.r4.model.StringType; +import org.hl7.fhir.r4.model.Subscription; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; - +import org.springframework.boot.test.web.server.LocalServerPort; import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import static ca.uhn.fhir.util.TestUtil.waitForSize; import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.*; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.opencds.cqf.fhir.utility.r4.Parameters.parameters; import static org.opencds.cqf.fhir.utility.r4.Parameters.stringPart; @@ -41,32 +52,32 @@ @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = { Application.class, - JpaStarterWebsocketDispatcherConfig.class, NicknameServiceConfig.class, RepositoryConfig.class }, properties = { "spring.profiles.include=storageSettingsTest", - "spring.datasource.url=jdbc:h2:mem:dbr4", - "hapi.fhir.enable_repository_validating_interceptor=true", - "hapi.fhir.fhir_version=r4", - //"hapi.fhir.subscription.websocket_enabled=true", - //"hapi.fhir.mdm_enabled=true", - "hapi.fhir.cr.enabled=true", - "hapi.fhir.cr.caregaps_section_author=Organization/alphora-author", - "hapi.fhir.cr.caregaps_reporter=Organization/alphora", - "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", - "hapi.fhir.implementationguides.dk-core.version=1.1.0", - "hapi.fhir.auto_create_placeholder_reference_targets=true", - // Override is currently required when using MDM as the construction of the MDM - // beans are ambiguous as they are constructed multiple places. This is evident - // when running in a spring boot environment - "spring.main.allow-bean-definition-overriding=true" }) -class ExampleServerR4IT implements IServerSupport{ + "spring.datasource.url=jdbc:h2:mem:dbr4", + "hapi.fhir.enable_repository_validating_interceptor=true", + "hapi.fhir.fhir_version=r4", + //"hapi.fhir.subscription.websocket_enabled=true", + //"hapi.fhir.mdm_enabled=true", + "hapi.fhir.cr.enabled=true", + "hapi.fhir.cr.caregaps_section_author=Organization/alphora-author", + "hapi.fhir.cr.caregaps_reporter=Organization/alphora", + "hapi.fhir.implementationguides.dk-core.name=hl7.fhir.dk.core", + "hapi.fhir.implementationguides.dk-core.version=1.1.0", + "hapi.fhir.auto_create_placeholder_reference_targets=true", + // Override is currently required when using MDM as the construction of the MDM + // beans are ambiguous as they are constructed multiple places. This is evident + // when running in a spring boot environment + "spring.main.allow-bean-definition-overriding=true"}) +class ExampleServerR4IT implements IServerSupport { private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ExampleServerR4IT.class); private IGenericClient ourClient; private FhirContext ourCtx; - @Autowired private CrProperties crProperties; + @Autowired + private CrProperties crProperties; @LocalServerPort private int port; @@ -127,7 +138,7 @@ private org.hl7.fhir.r4.model.Bundle loadBundle(String theLocation, FhirContext return result; } - public Parameters runCqlExecution(Parameters parameters){ + public Parameters runCqlExecution(Parameters parameters) { var results = ourClient.operation().onServer() .named("$cql") @@ -135,6 +146,7 @@ public Parameters runCqlExecution(Parameters parameters){ .execute(); return results; } + @Test void testSimpleDateCqlExecutionProvider() { Parameters params = parameters(stringPart("expression", "Interval[Today() - 2 years, Today())")); @@ -148,61 +160,62 @@ private IBaseResource loadRec(String theLocation, FhirContext theCtx, IGenericCl IBaseResource resource = (IBaseResource) theCtx.newJsonParser().parseResource(json); resList.add(resource); var result = theClient.transaction().withResources(resList).execute(); - //.withResources(resource).execute(); + //.withResources(resource).execute(); return result.get(0); } + @Test void testBatchPutWithIdenticalTags() { String batchPuts = "{\n" + - "\t\"resourceType\": \"Bundle\",\n" + - "\t\"id\": \"patients\",\n" + - "\t\"type\": \"batch\",\n" + - "\t\"entry\": [\n" + - "\t\t{\n" + - "\t\t\t\"request\": {\n" + - "\t\t\t\t\"method\": \"PUT\",\n" + - "\t\t\t\t\"url\": \"Patient/pat-1\"\n" + - "\t\t\t},\n" + - "\t\t\t\"resource\": {\n" + - "\t\t\t\t\"resourceType\": \"Patient\",\n" + - "\t\t\t\t\"id\": \"pat-1\",\n" + - "\t\t\t\t\"meta\": {\n" + - "\t\t\t\t\t\"tag\": [\n" + - "\t\t\t\t\t\t{\n" + - "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + - "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + - "\t\t\t\t\t\t}\n" + - "\t\t\t\t\t]\n" + - "\t\t\t\t}\n" + - "\t\t\t},\n" + - "\t\t\t\"fullUrl\": \"/Patient/pat-1\"\n" + - "\t\t},\n" + - "\t\t{\n" + - "\t\t\t\"request\": {\n" + - "\t\t\t\t\"method\": \"PUT\",\n" + - "\t\t\t\t\"url\": \"Patient/pat-2\"\n" + - "\t\t\t},\n" + - "\t\t\t\"resource\": {\n" + - "\t\t\t\t\"resourceType\": \"Patient\",\n" + - "\t\t\t\t\"id\": \"pat-2\",\n" + - "\t\t\t\t\"meta\": {\n" + - "\t\t\t\t\t\"tag\": [\n" + - "\t\t\t\t\t\t{\n" + - "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + - "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + - "\t\t\t\t\t\t}\n" + - "\t\t\t\t\t]\n" + - "\t\t\t\t}\n" + - "\t\t\t},\n" + - "\t\t\t\"fullUrl\": \"/Patient/pat-2\"\n" + - "\t\t}\n" + - "\t]\n" + - "}"; + "\t\"resourceType\": \"Bundle\",\n" + + "\t\"id\": \"patients\",\n" + + "\t\"type\": \"batch\",\n" + + "\t\"entry\": [\n" + + "\t\t{\n" + + "\t\t\t\"request\": {\n" + + "\t\t\t\t\"method\": \"PUT\",\n" + + "\t\t\t\t\"url\": \"Patient/pat-1\"\n" + + "\t\t\t},\n" + + "\t\t\t\"resource\": {\n" + + "\t\t\t\t\"resourceType\": \"Patient\",\n" + + "\t\t\t\t\"id\": \"pat-1\",\n" + + "\t\t\t\t\"meta\": {\n" + + "\t\t\t\t\t\"tag\": [\n" + + "\t\t\t\t\t\t{\n" + + "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + + "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + + "\t\t\t\t\t\t}\n" + + "\t\t\t\t\t]\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t\"fullUrl\": \"/Patient/pat-1\"\n" + + "\t\t},\n" + + "\t\t{\n" + + "\t\t\t\"request\": {\n" + + "\t\t\t\t\"method\": \"PUT\",\n" + + "\t\t\t\t\"url\": \"Patient/pat-2\"\n" + + "\t\t\t},\n" + + "\t\t\t\"resource\": {\n" + + "\t\t\t\t\"resourceType\": \"Patient\",\n" + + "\t\t\t\t\"id\": \"pat-2\",\n" + + "\t\t\t\t\"meta\": {\n" + + "\t\t\t\t\t\"tag\": [\n" + + "\t\t\t\t\t\t{\n" + + "\t\t\t\t\t\t\t\"system\": \"http://mysystem.org\",\n" + + "\t\t\t\t\t\t\t\"code\": \"value2\"\n" + + "\t\t\t\t\t\t}\n" + + "\t\t\t\t\t]\n" + + "\t\t\t\t}\n" + + "\t\t\t},\n" + + "\t\t\t\"fullUrl\": \"/Patient/pat-2\"\n" + + "\t\t}\n" + + "\t]\n" + + "}"; Bundle bundle = FhirContext.forR4().newJsonParser().parseResource(Bundle.class, batchPuts); ourClient.transaction().withBundle(bundle).execute(); } - //@Test + @Test @Order(1) void testWebsocketSubscription() throws Exception { /* @@ -218,27 +231,27 @@ void testWebsocketSubscription() throws Exception { channel.setPayload("application/json"); subscription.setChannel(channel); + int initialActiveSubscriptionCount = activeSubscriptionCount(); + MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute(); IIdType mySubscriptionId = methodOutcome.getId(); // Wait for the subscription to be activated - await().atMost(1, TimeUnit.MINUTES).until(() -> activeSubscriptionCount() == 3); + await().atMost(1, TimeUnit.MINUTES).until(()->activeSubscriptionCount(), equalTo(initialActiveSubscriptionCount + 1)); /* * Attach websocket */ - WebSocketClient myWebSocketClient = new WebSocketClient(); SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); - myWebSocketClient.start(); URI echoUri = new URI("ws://localhost:" + port + "/websocket"); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - ourLog.info("Connecting to : {}", echoUri); - Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); - Session session = connection.get(2, TimeUnit.SECONDS); + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); + + ourLog.info("Connecting to : {}", echoUri); + Session session = container.connectToServer(mySocketImplementation, echoUri); ourLog.info("Connected to WS: {}", session.isOpen()); /* @@ -268,11 +281,11 @@ void testCareGaps() throws IOException { assertTrue(reporter.equals("Organization/alphora")); assertTrue(author.equals("Organization/alphora-author")); - String periodStartValid = "2019-01-01"; - String periodEndValid = "2019-12-31"; - String subjectPatientValid = "Patient/numer-EXM125"; - String statusValid = "open-gap"; - String measureIdValid = "BreastCancerScreeningFHIR"; + String periodStartValid = "2019-01-01"; + String periodEndValid = "2019-12-31"; + String subjectPatientValid = "Patient/numer-EXM125"; + String statusValid = "open-gap"; + String measureIdValid = "BreastCancerScreeningFHIR"; loadBundle("r4/CareGaps/authreporter-bundle.json", ourCtx, ourClient); loadBundle("r4/CareGaps/BreastCancerScreeningFHIR-bundle.json", ourCtx, ourClient); diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java index 76d90e0ce79..e26ad37a5e1 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/ExampleServerR5IT.java @@ -1,9 +1,5 @@ package ca.uhn.fhir.jpa.starter; -import static ca.uhn.fhir.util.TestUtil.waitForSize; -import static org.awaitility.Awaitility.await; -import static org.junit.jupiter.api.Assertions.assertEquals; - import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.EncodingEnum; @@ -11,12 +7,9 @@ import ca.uhn.fhir.rest.client.api.IGenericClient; import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum; import ca.uhn.fhir.rest.client.interceptor.LoggingInterceptor; -import java.net.URI; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; -import org.eclipse.jetty.websocket.client.WebSocketClient; +import jakarta.websocket.ContainerProvider; +import jakarta.websocket.Session; +import jakarta.websocket.WebSocketContainer; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Enumerations; @@ -28,11 +21,17 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.junit.jupiter.SpringExtension; +import java.net.URI; + +import static ca.uhn.fhir.util.TestUtil.waitForSize; +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertEquals; + @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr5", "hapi.fhir.fhir_version=r5", @@ -128,18 +127,16 @@ void testWebsocketSubscription() throws Exception { * Attach websocket */ - WebSocketClient myWebSocketClient = new WebSocketClient(); - SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), EncodingEnum.JSON); + SocketImplementation mySocketImplementation = new SocketImplementation(mySubscriptionId.getIdPart(), + EncodingEnum.JSON); - myWebSocketClient.start(); + URI echoUri = new URI(endpoint); - URI echoUri = new URI(endpoint); - ClientUpgradeRequest request = new ClientUpgradeRequest(); - ourLog.info("Connecting to : {}", echoUri); - Future connection = myWebSocketClient.connect(mySocketImplementation, echoUri, request); - Session session = connection.get(2, TimeUnit.SECONDS); + WebSocketContainer container = ContainerProvider.getWebSocketContainer(); - ourLog.info("Connected to WS: {}", session.isOpen()); + ourLog.info("Connecting to : {}", echoUri); + Session session = container.connectToServer(mySocketImplementation, echoUri); + ourLog.info("Connected to WS: {}", session.isOpen()); /* * Create a matching resource diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java b/src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java deleted file mode 100644 index 3503338fc79..00000000000 --- a/src/test/java/ca/uhn/fhir/jpa/starter/JpaStarterWebsocketDispatcherConfig.java +++ /dev/null @@ -1,34 +0,0 @@ -package ca.uhn.fhir.jpa.starter; - -import org.eclipse.jetty.webapp.WebAppContext; -import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer; -import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory; -import org.springframework.boot.web.server.WebServerFactoryCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * This class ensures that websockets work with - * Spring + Spring Boot + Jetty - */ -@Configuration -public class JpaStarterWebsocketDispatcherConfig { - - @Bean - public Jetty10WebSocketServletWebServerCustomizer jetty10WebSocketServletWebServerCustomizer() { - return new Jetty10WebSocketServletWebServerCustomizer(); - } - - static class Jetty10WebSocketServletWebServerCustomizer implements WebServerFactoryCustomizer { - - @Override - public void customize(JettyServletWebServerFactory factory) { - - factory.addServerCustomizers(server -> { - WebAppContext ctx = (WebAppContext) server.getHandler(); - JettyWebSocketServletContainerInitializer.configure(ctx, null); - }); - - } - } -} diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java index 6729fa623cb..bbe1348b7f8 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/MultitenantServerR4IT.java @@ -12,13 +12,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.test.context.junit.jupiter.SpringExtension; import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(SpringExtension.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class, JpaStarterWebsocketDispatcherConfig.class}, properties = +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = {Application.class}, properties = { "spring.datasource.url=jdbc:h2:mem:dbr4-mt", "hapi.fhir.fhir_version=r4", diff --git a/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java b/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java index 4a536f0f2a1..43667086942 100644 --- a/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java +++ b/src/test/java/ca/uhn/fhir/jpa/starter/SocketImplementation.java @@ -2,16 +2,16 @@ package ca.uhn.fhir.jpa.starter; import ca.uhn.fhir.rest.api.EncodingEnum; -import org.eclipse.jetty.websocket.api.Session; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect; -import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; -import org.eclipse.jetty.websocket.api.annotations.WebSocket; +import jakarta.websocket.ClientEndpoint; +import jakarta.websocket.OnMessage; +import jakarta.websocket.OnOpen; +import jakarta.websocket.Session; import org.slf4j.Logger; import java.util.ArrayList; import java.util.List; -@WebSocket +@ClientEndpoint public class SocketImplementation { private static final Logger ourLog = org.slf4j.LoggerFactory.getLogger(SocketImplementation.class); @@ -34,7 +34,7 @@ public List getMessages() { public void keepAlive() { if (this.session != null) { try { - session.getRemote().sendString("keep alive"); + session.getBasicRemote().sendText("keep alive"); } catch (Throwable t) { ourLog.error("Failure", t); } @@ -47,14 +47,14 @@ public void keepAlive() { * * @param session */ - @OnWebSocketConnect + @OnOpen public void onConnect(Session session) { ourLog.info("Got connect: {}", session); this.session = session; try { String sending = "bind " + myCriteria; ourLog.info("Sending: {}", sending); - session.getRemote().sendString(sending); + session.getBasicRemote().sendText(sending); ourLog.info("Connection: DONE"); } catch (Throwable t) { @@ -68,7 +68,7 @@ public void onConnect(Session session) { * * @param theMsg */ - @OnWebSocketMessage + @OnMessage public void onMessage(String theMsg) { ourLog.info("Got msg: " + theMsg); myMessages.add(theMsg); diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml index 9f473c574d8..911d9709034 100644 --- a/src/test/resources/application.yaml +++ b/src/test/resources/application.yaml @@ -1,7 +1,7 @@ spring: main: allow-circular-references: true - #allow-bean-definition-overriding: true + allow-bean-definition-overriding: true flyway: enabled: false check-location: false @@ -20,11 +20,20 @@ spring: properties: hibernate.format_sql: false hibernate.show_sql: false - #Hibernate dialect is automatically detected except Postgres and H2. - #If using H2, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect - #If using postgres, then supply the value of ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect + ######################################### + # Hibernate Dialect Setting + ######################################### + # Use one of the following values: + # ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect + # ca.uhn.fhir.jpa.model.dialect.HapiFhirDerbyDialect + # ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgresDialect + # ca.uhn.fhir.jpa.model.dialect.HapiFhirOracleDialect + # ca.uhn.fhir.jpa.model.dialect.HapiFhirSQLServerDialect + # ca.uhn.fhir.jpa.model.dialect.HapiFhirMySQLDialect (Deprecated!) + ######################################### hibernate.dialect: ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect + ######################################### # hibernate.hbm2ddl.auto: update # hibernate.jdbc.batch_size: 20 # hibernate.cache.use_query_cache: false