Skip to content

Update the module to Platform 3.x#221

Merged
dkayiwa merged 25 commits intoopenmrs:masterfrom
wikumChamith:3.x-new
Feb 24, 2026
Merged

Update the module to Platform 3.x#221
dkayiwa merged 25 commits intoopenmrs:masterfrom
wikumChamith:3.x-new

Conversation

@wikumChamith
Copy link
Member

No description provided.

@wikumChamith wikumChamith marked this pull request as draft October 1, 2025 09:33
@wikumChamith wikumChamith requested a review from dkayiwa October 1, 2025 09:33
@wikumChamith
Copy link
Member Author

@dkayiwa, @ibacher, any suggestions on how to fix errors like:

The requested URI has more than one handler: /options.form ==> expected: <false> but was: <true>

@wikumChamith wikumChamith force-pushed the 3.x-new branch 2 times, most recently from 947106b to 93606dd Compare October 2, 2025 08:43
</property>
</bean>

<bean parent="obsServiceTarget" >
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind explaining why we removed this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this causes an error.

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'obsServiceTarget' available

<!-- Add here beans related to the web context -->

<bean id="legacyUiUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="patternParser"><null/></property>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add it if the value is null?

Copy link
Member Author

@wikumChamith wikumChamith Oct 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caused by: org.springframework.web.util.pattern.PatternParseException: No more pattern data allowed after {*...} or ** pattern element

This is a hack I used to avoid PatternParseException.

@ibacher
Copy link
Member

ibacher commented Oct 3, 2025

any suggestions on how to fix errors like

So what's happening is that there are two "org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" beans registered in the context. One we explicitly register here and one that is implicitly registered here by the use of the <mvc:view-controller /> elements in the legacy UI.

The bean we explicitly create gets named org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#0 but has an alias added of org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter. The bean created implicitly is simply named org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.

I'm not entirely sure what happened, but this commit is part of Spring 6 and it will just remove the implicit alias of org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter from the bean we created.

So a couple of things suggest themselves:

  1. Explicitly name the bean we create org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter via the name attribute on the bean definition.
  2. Remove the <mvc:view-controller /> annotations and find some other way of mapping those things.
  3. Remove our explicit create of the org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter and either add a new Spring @Configuration object annotated @EnableWebMvc in the web project of core.

Personally I think 3 is the cleanest thing, but may require more tweaks, e.g., to ensure that the new @Configuration class is properly loaded in tests.

@wikumChamith
Copy link
Member Author

wikumChamith commented Oct 5, 2025

any suggestions on how to fix errors like

So what's happening is that there are two "org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" beans registered in the context. One we explicitly register here and one that is implicitly registered here by the use of the <mvc:view-controller /> elements in the legacy UI.

The bean we explicitly create gets named org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#0 but has an alias added of org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter. The bean created implicitly is simply named org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.

I'm not entirely sure what happened, but this commit is part of Spring 6 and it will just remove the implicit alias of org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter from the bean we created.

So a couple of things suggest themselves:

1. Explicitly name the bean we create `org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter` via the `name` attribute on the bean definition.

2. Remove the `<mvc:view-controller />` annotations and find some other way of mapping those things.

3. Remove our explicit create of the `org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter` and _either_ add a new Spring `@Configuration` object annotated `@EnableWebMvc` in the `web` project of core.

Personally I think 3 is the cleanest thing, but may require more tweaks, e.g., to ensure that the new @Configuration class is properly loaded in tests.

@ibacher I tried both 1 and 3. However, I am still seeing the error. Here are the PRs for them.

1:openmrs/openmrs-core#5373
3:openmrs/openmrs-core#5374

@ibacher
Copy link
Member

ibacher commented Oct 8, 2025

Well, I stupidly assumed that the XML stuff wouldn't interfere with the @EnableWebMvc stuff and... that turns out to be false.

@ibacher
Copy link
Member

ibacher commented Oct 8, 2025

Anyways, @wikumChamith I added a commit here and to openmrs/openmrs-core#5374 that fixes that issue in a way I'm happy with. There are still some test failures but they aren't caused by this issue.

Btw, we should take every opportunity available to dump XML Spring configurations if possible. There were some issues with the services wrapped in TransactionProxyFactoryBeans, but we Platform 3, we should be dropping those.

@wikumChamith
Copy link
Member Author

PR to fix test errors on ChangePasswordFormControllerTest: openmrs/openmrs-core#5394

@dkayiwa
Copy link
Member

dkayiwa commented Oct 13, 2025

I put a comment on that pull request.

@wikumChamith
Copy link
Member Author

@dkayiwa, @ibacher, any idea on what is causing the TransientObjectException in ConceptFormControllerTest#shouldVoidShortName?

@dkayiwa
Copy link
Member

dkayiwa commented Oct 25, 2025

@wikumChamith did you eventually figure this out?

@dkayiwa
Copy link
Member

dkayiwa commented Oct 25, 2025

@wikumChamith in that failing test, try changing new Concept() to new Concept(3)

@wikumChamith
Copy link
Member Author

@dkayiwa, @ibacher the module is compiling now, but I’m seeing an error when I run the module:

SEVERE: Servlet.service() for servlet [openmrs] in context with path [/openmrs] threw exception [java.lang.NoClassDefFoundError: javax/servlet/jsp/tagext/TagLibraryValidator] with root cause
java.lang.ClassNotFoundException: javax.servlet.jsp.tagext.TagLibraryValidator
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:225)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:205)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.findClassInternal(ClassRealm.java:256)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:351)
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:36)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:225)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:205)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.findClassInternal(ClassRealm.java:256)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:351)
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:36)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:225)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:580)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:222)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:205)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:534)
	at java.base/java.lang.Class.forName(Class.java:513)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1209)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1059)
	at org.openmrs.util.OpenmrsClassLoader.loadClass(OpenmrsClassLoader.java:165)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
	at org.apache.jasper.compiler.TagLibraryInfoImpl.createValidator(TagLibraryInfoImpl.java:352)
	at org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:192)
	at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:408)
	at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:461)
	at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1289)
	at org.apache.jasper.compiler.Parser.parse(Parser.java:130)
	at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:243)
	at org.apache.jasper.compiler.ParserController.parse(ParserController.java:146)
	at org.apache.jasper.compiler.Parser.processIncludeDirective(Parser.java:325)
	at org.apache.jasper.compiler.Parser.parseIncludeDirective(Parser.java:362)
	at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:453)
	at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1289)
	at org.apache.jasper.compiler.Parser.parse(Parser.java:130)
	at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:243)
	at org.apache.jasper.compiler.ParserController.parse(ParserController.java:106)
	at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:195)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:368)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:346)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:332)
	at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:591)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:288)
	at org.openmrs.module.web.OpenmrsJspServlet.service(OpenmrsJspServlet.java:51)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130)
	at org.openmrs.web.filter.JspClassLoaderFilter.doFilter(JspClassLoaderFilter.java:47)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:514)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:334)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:263)
	at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171)
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314)
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1438)
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1168)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:622)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:514)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:334)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:263)
	at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171)
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314)
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1438)
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1168)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:622)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130)
	at org.openmrs.module.web.filter.ForcePasswordChangeFilter.doFilter(ForcePasswordChangeFilter.java:61)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.module.web.filter.RedirectAfterLoginFilter.doFilter(RedirectAfterLoginFilter.java:64)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.GZIPFilter.doFilterInternal(GZIPFilter.java:66)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:73)
	at org.openmrs.web.xss.XSSFilter.doFilter(XSSFilter.java:40)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)
	at org.openmrs.module.web.filter.ModuleFilter.doFilter(ModuleFilter.java:57)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.owasp.csrfguard.CsrfGuardFilter.handleSession(CsrfGuardFilter.java:107)
	at org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:97)
	at org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:68)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.OpenmrsFilter.doFilterInternal(OpenmrsFilter.java:114)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.CookieClearingFilter.doFilterInternal(CookieClearingFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:155)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:125)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:120)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:120)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:120)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:79)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:396)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1773)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:59)
	at java.base/java.lang.Thread.run(Thread.java:1583)

To resolve this, I removed the taglib dependencies from core and used org.glassfish.web:jakarta.servlet.jsp.jstl in this module. However, I’m still seeing the same error. We’re currently using the JstlCoreTLV validator, but since it now uses Jakarta EE, removing it didn’t fix the issue either.

Is there anywhere else that might still be using a javax-era taglib that I may have missed?

@dkayiwa
Copy link
Member

dkayiwa commented Oct 27, 2025

@wikumChamith did you figure this out?

@wikumChamith
Copy link
Member Author

@wikumChamith did you figure this out?

Nope, still trying to sort it out. Any suggestions??

@wikumChamith wikumChamith requested a review from dkayiwa October 28, 2025 10:39
Concept concept = cs.getConcept(5497);
//sanity check, the current preferred Name should be different from what will get set in the form
Assert.assertNotSame("CD3+CD4+ABS CNT", concept.getPreferredName(britishEn).getName());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why you did not use a different pull request for these formatting changes?

ProgramFormController controller = (ProgramFormController) applicationContext.getBean("programForm");
controller.handleRequest(request, new MockHttpServletResponse());

Context.clearSession();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What failure is the above addressing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you see the above?

@dkayiwa
Copy link
Member

dkayiwa commented Oct 28, 2025

@wikumChamith because org.apache.taglibs.standard.tlv.JstlCoreTLV does not have a corresponding jakarta implementation, can you just remove the whole validator element? https://github.com/openmrs/openmrs-module-legacyui/blob/1.23.0/omod/src/main/webapp/taglibs/c-rt.tld#L13-L20

@wikumChamith
Copy link
Member Author

@wikumChamith because org.apache.taglibs.standard.tlv.JstlCoreTLV does not have a corresponding jakarta implementation, can you just remove the whole validator element? https://github.com/openmrs/openmrs-module-legacyui/blob/1.23.0/omod/src/main/webapp/taglibs/c-rt.tld#L13-L20

@dkayiwa, that also gives a similar error:

java.lang.ClassNotFoundException: javax.servlet.jsp.tagext.TagExtraInfo
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:42)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:225)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:205)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1027)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:714)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.findClassInternal(ClassRealm.java:256)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClassFromSelf(ClassRealm.java:351)
	at org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy.loadClass(SelfFirstStrategy.java:36)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:225)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:580)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.unsynchronizedLoadClass(ClassRealm.java:222)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:210)
	at org.codehaus.plexus.classworlds.realm.ClassRealm.loadClass(ClassRealm.java:205)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:534)
	at java.base/java.lang.Class.forName(Class.java:513)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1209)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1059)
	at org.openmrs.util.OpenmrsClassLoader.loadClass(OpenmrsClassLoader.java:165)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526)
	at org.apache.jasper.compiler.TagLibraryInfoImpl.createTagInfo(TagLibraryInfoImpl.java:299)
	at org.apache.jasper.compiler.TagLibraryInfoImpl.<init>(TagLibraryInfoImpl.java:196)
	at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:408)
	at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:461)
	at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1289)
	at org.apache.jasper.compiler.Parser.parse(Parser.java:130)
	at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:243)
	at org.apache.jasper.compiler.ParserController.parse(ParserController.java:146)
	at org.apache.jasper.compiler.Parser.processIncludeDirective(Parser.java:325)
	at org.apache.jasper.compiler.Parser.parseIncludeDirective(Parser.java:362)
	at org.apache.jasper.compiler.Parser.parseDirective(Parser.java:453)
	at org.apache.jasper.compiler.Parser.parseElements(Parser.java:1289)
	at org.apache.jasper.compiler.Parser.parse(Parser.java:130)
	at org.apache.jasper.compiler.ParserController.doParse(ParserController.java:243)
	at org.apache.jasper.compiler.ParserController.parse(ParserController.java:106)
	at org.apache.jasper.compiler.Compiler.generateJava(Compiler.java:195)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:368)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:346)
	at org.apache.jasper.compiler.Compiler.compile(Compiler.java:332)
	at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:591)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:376)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:337)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:288)
	at org.openmrs.module.web.OpenmrsJspServlet.service(OpenmrsJspServlet.java:51)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130)
	at org.openmrs.web.filter.JspClassLoaderFilter.doFilter(JspClassLoaderFilter.java:47)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:514)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:334)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:263)
	at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171)
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314)
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1438)
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1168)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:622)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:110)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:514)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:334)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:263)
	at org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171)
	at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:314)
	at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1438)
	at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1168)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1106)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:622)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:710)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:130)
	at org.openmrs.module.web.filter.ForcePasswordChangeFilter.doFilter(ForcePasswordChangeFilter.java:61)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.module.web.filter.RedirectAfterLoginFilter.doFilter(RedirectAfterLoginFilter.java:64)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.GZIPFilter.doFilterInternal(GZIPFilter.java:66)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:73)
	at org.openmrs.web.xss.XSSFilter.doFilter(XSSFilter.java:40)
	at org.openmrs.module.web.filter.ModuleFilterChain.doFilter(ModuleFilterChain.java:71)
	at org.openmrs.module.web.filter.ModuleFilter.doFilter(ModuleFilter.java:57)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.owasp.csrfguard.CsrfGuardFilter.handleSession(CsrfGuardFilter.java:107)
	at org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:97)
	at org.owasp.csrfguard.CsrfGuardFilter.doFilter(CsrfGuardFilter.java:68)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.OpenmrsFilter.doFilterInternal(OpenmrsFilter.java:114)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.CookieClearingFilter.doFilterInternal(CookieClearingFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:155)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:125)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:120)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:120)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.openmrs.web.filter.StartupFilter.doFilter(StartupFilter.java:120)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:109)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:79)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:116)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:396)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:903)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1773)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:59)
	at java.base/java.lang.Thread.run(Thread.java:1583)

I also tried deleting all the tld files. However, that didn't resolved the issue.

@dkayiwa
Copy link
Member

dkayiwa commented Oct 29, 2025

Even after removing the validator?

@wikumChamith
Copy link
Member Author

Even after removing the validator?

Yes

@dkayiwa
Copy link
Member

dkayiwa commented Oct 29, 2025

Can you open a pull request for the changes you did in core for this?

@wikumChamith
Copy link
Member Author

Can you open a pull request for the changes you did in core for this?

@dkayiwa PR: openmrs/openmrs-core#5441

@dkayiwa
Copy link
Member

dkayiwa commented Oct 29, 2025

How are you running it? I seem to be getting a different error: org.apache.jasper.JasperException: /WEB-INF/view/index.jsp (line: [1], column: [1]) Failed to load or instantiate TagExtraInfo class: [org.apache.taglibs.page.AttributesTEI]

@wikumChamith
Copy link
Member Author

How are you running it? I seem to be getting a different error: org.apache.jasper.JasperException: /WEB-INF/view/index.jsp (line: [1], column: [1]) Failed to load or instantiate TagExtraInfo class: [org.apache.taglibs.page.AttributesTEI]

I tried running it with both the SDK and cargo:run from openmrs-core.

@wikumChamith
Copy link
Member Author

@dkayiwa @ibacher, there’s an issue. It looks like Spring 7 has removed org.springframework.web.servlet.theme, and we’re currently using it in multiple places. I think we have two options:

  1. Replace it with a custom solution that mirrors the Spring implementation.
  2. Switch to a CSS-based approach (which is what the Spring documentation recommends). The trade-off is that we would lose the ability to switch themes dynamically.

What do you recommend?

@dkayiwa
Copy link
Member

dkayiwa commented Feb 17, 2026

My preference is to go with the Spring recommendation because i have really not seen people using the dynamic theme switching.

@dkayiwa
Copy link
Member

dkayiwa commented Feb 17, 2026

@wikumChamith how is this going?

@wikumChamith
Copy link
Member Author

@dkayiwa I fixed the build errors.

api/pom.xml Outdated
<groupId>org.openmrs.module</groupId>
<artifactId>legacyui</artifactId>
<version>2.1.0-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be 3.0.0-SNAPSHOT because it will not run on any previous version of the platform?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumped the version to 3.0.0-SNAPSHOT


ConceptFormController conceptFormController = (ConceptFormController) applicationContext.getBean("conceptForm");

MockHttpServletRequest mockRequest = new MockHttpServletRequest();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is all this formatting about?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted them


}
final String EXPECTED_PREFERRED_NAME = "no such concept";
final String EXPECTED_SHORT_NAME = "nonesuch";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of formatting going on here. Can we use a separate pull request for it?

@dkayiwa
Copy link
Member

dkayiwa commented Feb 19, 2026

@wikumChamith did you also test and confirm that the module can now start in core 3.0.0-SNAPSHOT?

@wikumChamith
Copy link
Member Author

wikumChamith commented Feb 19, 2026

@dkayiwa I’m getting this error with core 3.0.0-SNAPSHOT even without this module:

java.lang.ClassCastException: class org.springframework.orm.jpa.EntityManagerHolder cannot be cast to class org.springframework.orm.jpa.hibernate.SessionHolder (org.springframework.orm.jpa.EntityManagerHolder and org.springframework.orm.jpa.hibernate.SessionHolder are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @5b76b891)

I think this is caused by the Spring 7 upgrade. It looks like Spring 7 has removed org.springframework.orm.hibernate5.support.OpenSessionInViewFilter

https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-7.0-Release-Notes?#jpa-32-and-hibernate-orm-7172

@wikumChamith
Copy link
Member Author

I think we’ll need to switch to JpaTransactionManager, since that’s what Spring is using now.

cc: @dkayiwa , @ibacher

@dkayiwa
Copy link
Member

dkayiwa commented Feb 19, 2026

@wikumChamith do you wanna fix it? :)

@wikumChamith
Copy link
Member Author

@wikumChamith do you wanna fix it? :)

Sure. I'll take a look

@ibacher
Copy link
Member

ibacher commented Feb 20, 2026

@wikumChamith Ok, I finally made it back this far. You're right that OpenSessionInViewFilter has been removed but it's been replaced with the equivalent OpenEntityManagerInViewFilter. It feels like switching that and switching to the JpaTransactionManager will fix things...

@dkayiwa dkayiwa marked this pull request as ready for review February 24, 2026 22:50
@dkayiwa dkayiwa merged commit 92411d1 into openmrs:master Feb 24, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants