OpenMRS and Web sockets

This is an old thread but I am reviving it because I’m facing the same problem described by the OP. We are implementing a chat feature within an OpenMRS module to enable clinical workers to exchange text messages in real-time. Consequently, I have implemented a web socket based on the Spring WebSocket API and the STOMP messaging protocol. However, while the code compiles correctly, it fails at runtime with:

DefaultSockJsService.getDefaultTransportHandlers(95) |2022-06-27T02:56:28,449| Failed to create a default WebSocketTransportHandlerjava.lang.IllegalStateException: No suitable default RequestUpgradeStrategy found Further along, I have a BeanCreationException caused by a LinkageError as shown below:WARN - AbstractApplicationContext.refresh(559) |2022-06-27T02:56:28,462| Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stompWebSocketHandlerMapping' defined in class path resource [org/springframework/web/socket/config/annotation/DelegatingWebSocketMessageBrokerConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'stompWebSocketHandlerMapping' threw exception; nested exception is java.lang.LinkageError: loader constraint violation: when resolving method "org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build()Lcom/fasterxml/jackson/databind/ObjectMapper;" the class loader (instance of org/openmrs/module/ModuleClassLoader) of the current class, org/springframework/web/socket/sockjs/frame/Jackson2SockJsMessageCodec, and the class loader (instance of org/apache/catalina/loader/ParallelWebappClassLoader) for the method's defining class, org/springframework/http/converter/json/Jackson2ObjectMapperBuilder, have different Class objects for the type com/fasterxml/jackson/databind/ObjectMapper used in the signature

It appears that the module classloader loads an additional copy of the Jackson library, besides the one loaded by the container’s (Tomcat) classloader, and I am unable to figure out how to resolve this issue. As a side note, I have also tried to switch to the Java WebSocket API and integrate it with Spring using @ServerEndpoint and the SpringConfigurator class as explained here: “https://www.baeldung.com/java-websockets”. While that does not lead to any Exceptions, the web socket returns a 404 rather than the expected 101 (switching protocols) status code. It’s possible there’s something I am missing critical about how the OpenMRS module system works because I can otherwise get both of these approaches to work on standalone Spring projects. Any help will be highly appreciated @ibacher @dkayiwa @wyclif

cc @gitahi86 @ningosi

Related threads

may be you would need to inspect where the conflicting libraries are loaded from and explicitly exclude one. Most probably the dependencies are transitively loaded.

When i get these kinds of errors, the first place that i usually check is the compiled module’s lib folder. Check to see if it contains a duplicate of this jar.

What @mozzy and @dkayiwa said is right. Your module is probably accidentally importing a version of Jackson, which is already provided as part of core. Concretely, there are likely two solutions:

  1. If you explicitly include Jackson in your POM, mark it as <scope>provided</scope>
  2. If you don’t explicitly include Jackson, check your dependencies (e.g., using mvn dependency:tree -Dscope=compile) and add an <exclusion> to the appropriate dependency to stop it loading Jackson.

Thanks, @mozzy @dkayiwa and @ibacher for the response and hints. We previously tried playing around with the dependency exclusion to not much success. We’ll give it another shot and post the outcome here.

As @moshon has pointed out, we’ve excluded Jackson from our dependencies and we don’t explicitly include it as a dependency itself. Our pom file looks as below:

FWIIW, this issue only manifests when you include the @EnableWebSocketMessageBroker annotation on the web socket configuration, which you have to do to configure the web socket. I see no obvious connection here, but I’m stating it anyway just in case someone else does.

Yeah it should be transitively loaded

@gitahi86 after seven years? Yikes!!! Indeed this has been a blocker to bring you back after all that long. :smiley:

Is the module available on github?

1 Like

@dkayiwa haha … yeah … I know :smiley: (and now 8 days later again!). Veered off to do a bunch of other things and just recently got back here to help with this project. It’s nice to see all you old timers keeping the fire burning. I am not authorized to share the module, but here’s a throw-away one I’ve created to demonstrate the issue.

PS: Apologies for the delay in responding. I am working on this on part-time basis so I am not constantly plugged in.

Sorry this is creating distraction on a technical thread, but I wonder @moshon if the use case could be shared in more details?

The reason I’m asking is because it could inform feature ideas for O3. Such as clinicians pushing structured or free text clinical notifications to each other about a patient.

We will plan for a presentation at the next TAC

and also here on Talk of course