Websockets working once more on the public server

This commit is contained in:
James 2017-01-12 08:59:51 -05:00
parent a8eb4a1967
commit af32c4b7e9
16 changed files with 139 additions and 177 deletions

View File

@ -36,38 +36,13 @@ import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu2;
@Configuration
@EnableWebSocket()
public class WebsocketDstu2Config implements WebSocketConfigurer {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(WebsocketDstu2Config.class);
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry theRegistry) {
theRegistry.addHandler(subscriptionWebSocketHandler(), "/websocket/dstu2").setAllowedOrigins("*");
}
// @Override
// public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// configurer.enable();
// }
//
// @Bean
// public String containerInit() {
// try {
// Class.forName("javax.websocket.WebSocketContainer");
// createWebSocketContainer();
// } catch (ClassNotFoundException e) {
// // ok
// }
//
// return "";
// }
//
// @Bean
// @Lazy
// public ServletServerContainerFactoryBean createWebSocketContainer() {
// ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
// container.setMaxTextMessageBufferSize(8192);
// container.setMaxBinaryMessageBufferSize(8192);
// return container;
// }
@Bean(autowire = Autowire.BY_TYPE)
public WebSocketHandler subscriptionWebSocketHandler() {
return new PerConnectionWebSocketHandler(SubscriptionWebsocketHandlerDstu2.class);

View File

@ -0,0 +1,29 @@
package ca.uhn.fhir.jpa.config;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu2;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
@Configuration
public class WebsocketDstu2DispatcherConfig {
@Autowired
private FhirContext myCtx;
@Autowired
private IFhirResourceDao<Subscription> mySubscriptionDao;
@PostConstruct
public void postConstruct() {
SubscriptionWebsocketHandlerDstu2.setCtx(myCtx);
SubscriptionWebsocketHandlerDstu2.setSubscriptionDao((IFhirResourceDaoSubscription<Subscription>) mySubscriptionDao);
}
}

View File

@ -1,78 +0,0 @@
package ca.uhn.fhir.jpa.config;
/*
* #%L
* HAPI FHIR JPA Server
* %%
* Copyright (C) 2014 - 2016 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.PerConnectionWebSocketHandler;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu2;
@Configuration
@EnableWebSocket()
@Controller
@EnableWebMvc
public class WebsocketDstu2TomcatConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry theRegistry) {
theRegistry.addHandler(subscriptionWebSocketHandler(), "/websocket/dstu2");
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(8192);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
@Bean(autowire = Autowire.BY_TYPE)
public WebSocketHandler subscriptionWebSocketHandler() {
return new PerConnectionWebSocketHandler(SubscriptionWebsocketHandlerDstu2.class);
}
@Bean
public TaskScheduler websocketTaskScheduler() {
ThreadPoolTaskScheduler retVal = new ThreadPoolTaskScheduler();
retVal.setPoolSize(5);
return retVal;
}
}

View File

@ -51,7 +51,7 @@ public class WebsocketDstu3Config implements WebSocketConfigurer {
}
@Bean(destroyMethod="destroy")
public TaskScheduler websocketTaskScheduler() {
public TaskScheduler websocketTaskSchedulerDstu3() {
final ThreadPoolTaskScheduler retVal = new ThreadPoolTaskScheduler() {
private static final long serialVersionUID = 1L;

View File

@ -0,0 +1,29 @@
package ca.uhn.fhir.jpa.config.dstu3;
import javax.annotation.PostConstruct;
import org.hl7.fhir.dstu3.model.Subscription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.jpa.subscription.SubscriptionWebsocketHandlerDstu3;
@Configuration
public class WebsocketDstu3DispatcherConfig {
@Autowired
private FhirContext myCtx;
@Autowired
private IFhirResourceDao<org.hl7.fhir.dstu3.model.Subscription> mySubscriptionDao;
@PostConstruct
public void postConstruct() {
SubscriptionWebsocketHandlerDstu3.setCtx(myCtx);
SubscriptionWebsocketHandlerDstu3.setSubscriptionDao((IFhirResourceDaoSubscription<Subscription>) mySubscriptionDao);
}
}

View File

@ -40,6 +40,7 @@ import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSubscription;
import ca.uhn.fhir.model.dstu2.resource.Subscription;
import ca.uhn.fhir.model.dstu2.valueset.SubscriptionChannelTypeEnum;
@ -51,19 +52,13 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler implements ISubscriptionWebsocketHandler, Runnable {
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionWebsocketHandlerDstu2.class);
@Autowired
@Qualifier("myFhirContextDstu2")
private FhirContext myCtx;
private static IFhirResourceDaoSubscription<Subscription> ourSubscriptionDao;
private ScheduledFuture<?> myScheduleFuture;
private IState myState = new InitialState();
@Autowired
private IFhirResourceDaoSubscription<Subscription> mySubscriptionDao;
private IIdType mySubscriptionId;
private Long mySubscriptionPid;
@ -125,12 +120,20 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
ourLog.debug("Subscription {} websocket handler polling", subscriptionPid);
List<IBaseResource> results = mySubscriptionDao.getUndeliveredResourcesAndPurge(subscriptionPid);
List<IBaseResource> results = ourSubscriptionDao.getUndeliveredResourcesAndPurge(subscriptionPid);
if (results.isEmpty() == false) {
myState.deliver(results);
}
}
public static void setCtx(FhirContext theCtx) {
ourCtx = theCtx;
}
public static void setSubscriptionDao(IFhirResourceDaoSubscription<Subscription> theSubscriptionDao) {
ourSubscriptionDao = theSubscriptionDao;
}
private class BoundDynamicSubscriptionState implements IState {
private EncodingEnum myEncoding;
@ -145,7 +148,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
public void closing() {
ourLog.info("Deleting subscription {}", mySubscriptionId);
try {
mySubscriptionDao.delete(mySubscriptionId, null);
ourSubscriptionDao.delete(mySubscriptionId, null);
} catch (Exception e) {
handleFailure(e);
}
@ -156,7 +159,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
try {
for (IBaseResource nextResource : theResults) {
ourLog.info("Sending WebSocket message for resource: {}", nextResource.getIdElement());
String encoded = myEncoding.newParser(myCtx).encodeResourceToString(nextResource);
String encoded = myEncoding.newParser(ourCtx).encodeResourceToString(nextResource);
String payload = "add " + mySubscriptionId.getIdPart() + '\n' + encoded;
mySession.sendMessage(new TextMessage(payload));
}
@ -232,8 +235,8 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
}
try {
Subscription subscription = mySubscriptionDao.read(id, null);
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
Subscription subscription = ourSubscriptionDao.read(id, null);
mySubscriptionPid = ourSubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement();
myState = new BoundStaticSubscipriptionState(theSession);
} catch (ResourceNotFoundException e) {
@ -257,7 +260,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
subscription.setCriteria(theRemaining);
try {
String params = theRemaining.substring(theRemaining.indexOf('?')+1);
String params = theRemaining.substring(theRemaining.indexOf('?') + 1);
List<NameValuePair> paramValues = URLEncodedUtils.parse(params, Constants.CHARSET_UTF8, '&');
EncodingEnum encoding = EncodingEnum.JSON;
for (NameValuePair nameValuePair : paramValues) {
@ -269,9 +272,9 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl
}
}
IIdType id = mySubscriptionDao.create(subscription).getId();
IIdType id = ourSubscriptionDao.create(subscription).getId();
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionPid = ourSubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement();
myState = new BoundDynamicSubscriptionState(theSession, encoding);

View File

@ -51,25 +51,23 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler implements ISubscriptionWebsocketHandler, Runnable {
private static FhirContext ourCtx;
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SubscriptionWebsocketHandlerDstu3.class);
@Autowired
private FhirContext myCtx;
private static IFhirResourceDaoSubscription<Subscription> ourSubscriptionDao;
private ScheduledFuture<?> myScheduleFuture;
private IState myState = new InitialState();
@Autowired
private IFhirResourceDaoSubscription<Subscription> mySubscriptionDao;
private IIdType mySubscriptionId;
private Long mySubscriptionPid;
@Autowired
@Qualifier("websocketTaskScheduler")
@Qualifier("websocketTaskSchedulerDstu3")
private TaskScheduler myTaskScheduler;
@Override
public void afterConnectionClosed(WebSocketSession theSession, CloseStatus theStatus) throws Exception {
super.afterConnectionClosed(theSession, theStatus);
@ -124,12 +122,20 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
ourLog.debug("Subscription {} websocket handler polling", subscriptionPid);
List<IBaseResource> results = mySubscriptionDao.getUndeliveredResourcesAndPurge(subscriptionPid);
List<IBaseResource> results = ourSubscriptionDao.getUndeliveredResourcesAndPurge(subscriptionPid);
if (results.isEmpty() == false) {
myState.deliver(results);
}
}
public static void setCtx(FhirContext theCtx) {
ourCtx = theCtx;
}
public static void setSubscriptionDao(IFhirResourceDaoSubscription<Subscription> theSubscriptionDao) {
ourSubscriptionDao = theSubscriptionDao;
}
private class BoundDynamicSubscriptionState implements IState {
private EncodingEnum myEncoding;
@ -144,7 +150,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
public void closing() {
ourLog.info("Deleting subscription {}", mySubscriptionId);
try {
mySubscriptionDao.delete(mySubscriptionId, null);
ourSubscriptionDao.delete(mySubscriptionId, null);
} catch (Exception e) {
handleFailure(e);
}
@ -155,7 +161,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
try {
for (IBaseResource nextResource : theResults) {
ourLog.info("Sending WebSocket message for resource: {}", nextResource.getIdElement());
String encoded = myEncoding.newParser(myCtx).encodeResourceToString(nextResource);
String encoded = myEncoding.newParser(ourCtx).encodeResourceToString(nextResource);
String payload = "add " + mySubscriptionId.getIdPart() + '\n' + encoded;
mySession.sendMessage(new TextMessage(payload));
}
@ -231,8 +237,8 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
}
try {
Subscription subscription = mySubscriptionDao.read(id, null);
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
Subscription subscription = ourSubscriptionDao.read(id, null);
mySubscriptionPid = ourSubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement();
myState = new BoundStaticSubscipriptionState(theSession);
} catch (ResourceNotFoundException e) {
@ -268,9 +274,9 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl
}
}
IIdType id = mySubscriptionDao.create(subscription).getId();
IIdType id = ourSubscriptionDao.create(subscription).getId();
mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionPid = ourSubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id);
mySubscriptionId = subscription.getIdElement();
myState = new BoundDynamicSubscriptionState(theSession, encoding);

View File

@ -48,7 +48,7 @@ import ca.uhn.fhir.util.TestUtil;
//@formatter:off
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= {TestDstu2Config.class/*, ca.uhn.fhir.jpa.config.WebsocketDstu2Config.class*/ })
@ContextConfiguration(classes= {TestDstu2Config.class, ca.uhn.fhir.jpa.config.WebsocketDstu2DispatcherConfig.class})
//@formatter:on
public abstract class BaseJpaDstu2Test extends BaseJpaTest {

View File

@ -22,6 +22,7 @@ import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import ca.uhn.fhir.jpa.config.WebsocketDstu2Config;
import ca.uhn.fhir.jpa.config.WebsocketDstu2DispatcherConfig;
import ca.uhn.fhir.jpa.dao.dstu2.BaseJpaDstu2Test;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
import ca.uhn.fhir.model.api.Bundle;
@ -135,7 +136,7 @@ public abstract class BaseResourceProviderDstu2Test extends BaseJpaDstu2Test {
dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
ServletHolder subsServletHolder = new ServletHolder();
subsServletHolder.setServlet(dispatcherServlet);
subsServletHolder.setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, WebsocketDstu2Config.class.getName());
subsServletHolder.setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, WebsocketDstu2Config.class.getName() + "\n" + WebsocketDstu2DispatcherConfig.class.getName());
proxyHandler.addServlet(subsServletHolder, "/*");

View File

@ -28,6 +28,7 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.DispatcherServlet;
import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3Config;
import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3DispatcherConfig;
import ca.uhn.fhir.jpa.dao.dstu3.BaseJpaDstu3Test;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.testutil.RandomServerPortProvider;
@ -111,7 +112,7 @@ public abstract class BaseResourceProviderDstu3Test extends BaseJpaDstu3Test {
dispatcherServlet.setContextClass(AnnotationConfigWebApplicationContext.class);
ServletHolder subsServletHolder = new ServletHolder();
subsServletHolder.setServlet(dispatcherServlet);
subsServletHolder.setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, WebsocketDstu3Config.class.getName());
subsServletHolder.setInitParameter(ContextLoader.CONFIG_LOCATION_PARAM, WebsocketDstu3Config.class.getName() + "\n" + WebsocketDstu3DispatcherConfig.class.getName());
proxyHandler.addServlet(subsServletHolder, "/*");
// Register a CORS filter

View File

@ -17,8 +17,9 @@ import org.springframework.web.cors.CorsConfiguration;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.WebsocketDstu2Config;
import ca.uhn.fhir.jpa.config.WebsocketDstu2TomcatConfig;
import ca.uhn.fhir.jpa.config.WebsocketDstu2DispatcherConfig;
import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3Config;
import ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3DispatcherConfig;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu1;
@ -30,7 +31,11 @@ import ca.uhn.fhir.jpa.provider.dstu3.JpaSystemProviderDstu3;
import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.narrative.DefaultThymeleafNarrativeGenerator;
import ca.uhn.fhir.rest.server.*;
import ca.uhn.fhir.rest.server.ETagSupportEnum;
import ca.uhn.fhir.rest.server.EncodingEnum;
import ca.uhn.fhir.rest.server.HardcodedServerAddressStrategy;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
import ca.uhn.fhir.rest.server.interceptor.BanUnsupportedHttpMethodsInterceptor;
import ca.uhn.fhir.rest.server.interceptor.CorsInterceptor;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
@ -106,7 +111,7 @@ public class TestRestfulServer extends RestfulServer {
myAppCtx.register(TdlDstu2Config.class);
baseUrlProperty = FHIR_BASEURL_TDL2;
} else {
myAppCtx.register(TestDstu2Config.class, WebsocketDstu2TomcatConfig.class);
myAppCtx.register(TestDstu2Config.class, WebsocketDstu2DispatcherConfig.class);
baseUrlProperty = FHIR_BASEURL_DSTU2;
}
myAppCtx.refresh();
@ -129,7 +134,7 @@ public class TestRestfulServer extends RestfulServer {
myAppCtx.register(TdlDstu3Config.class);
baseUrlProperty = FHIR_BASEURL_TDL3;
} else {
myAppCtx.register(TestDstu3Config.class, WebsocketDstu3Config.class);
myAppCtx.register(TestDstu3Config.class, WebsocketDstu3DispatcherConfig.class);
baseUrlProperty = FHIR_BASEURL_DSTU3;
}
myAppCtx.refresh();

View File

@ -1,17 +0,0 @@
package ca.uhn.fhirtest.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DbServerConfig {
@Bean
public String dbServer() {
return "";
// For mysql
// return new ca.uhn.fhirtest.MySqlServer();
}
}

View File

@ -115,9 +115,9 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
return extraProperties;
}
@Bean(autowire = Autowire.BY_TYPE)
public IServerInterceptor subscriptionSecurityInterceptor() {
return new SubscriptionsRequireManualActivationInterceptorDstu2();
}
// @Bean(autowire = Autowire.BY_TYPE)
// public IServerInterceptor subscriptionSecurityInterceptor() {
// return new SubscriptionsRequireManualActivationInterceptorDstu2();
// }
}

View File

@ -128,10 +128,10 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
return requestValidator;
}
@Bean(autowire = Autowire.BY_TYPE)
public IServerInterceptor subscriptionSecurityInterceptor() {
return new SubscriptionsRequireManualActivationInterceptorDstu3();
}
// @Bean(autowire = Autowire.BY_TYPE)
// public IServerInterceptor subscriptionSecurityInterceptor() {
// return new SubscriptionsRequireManualActivationInterceptorDstu3();
// }
@Bean()
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {

View File

@ -89,6 +89,10 @@
<appender-ref ref="SUBSCRIPTION_FILE"/>
</logger>
<logger name="org.eclipse.jetty.websocket" additivity="true" level="debug">
<appender-ref ref="SUBSCRIPTION_FILE"/>
</logger>
<logger name="ca.uhn.fhir.jpa.subscription" additivity="true" level="debug">
<appender-ref ref="SUBSCRIPTION_FILE"/>
</logger>

View File

@ -29,7 +29,11 @@
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>ca.uhn.fhirtest.config.FhirTesterConfig</param-value>
<param-value>
ca.uhn.fhirtest.config.FhirTesterConfig
ca.uhn.fhir.jpa.config.WebsocketDstu2Config
ca.uhn.fhir.jpa.config.dstu3.WebsocketDstu3Config
</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>