spring-ws icon indicating copy to clipboard operation
spring-ws copied to clipboard

Problem on updating from Java 8 to Java 17

Open beat2 opened this issue 2 years ago • 3 comments

My SOAP service worked for the last few years with Java 8. Then I tried to update to Java 17.

When sending (a valid) request with Soap-UI I am getting this stacktrace:

15:57:49 WARN [fd416dff-2bc7-4d49-86ca-4b3d68cfc627] [] [] [c.a.b.l.s.e.CustomFaultHandler]: Processing Exception java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 16 at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.mergeContext(XMLSchemaValidator.java:494) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElementPSVI(XMLSchemaValidator.java:2561) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleEndElement(XMLSchemaValidator.java:2477) at java.xml/com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.endElement(XMLSchemaValidator.java:944) at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.finishNode(DOMValidatorHelper.java:342) at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:247) at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:190) at java.xml/com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:108) at java.xml/javax.xml.validation.Validator.validate(Validator.java:124) at org.springframework.xml.validation.Jaxp15ValidatorFactory$Jaxp15Validator.validate(Jaxp15ValidatorFactory.java:97) at org.springframework.ws.server.endpoint.interceptor.AbstractValidatingInterceptor.handleRequest(AbstractValidatingInterceptor.java:187) at org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:221) at org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:174) at org.springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88) at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:60) at org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:288) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) at javax.servlet.http.HttpServlet.service(HttpServlet.java:515) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:583) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:212) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at ch.admin.bit.jeap.log.correlation.web.CorrelationIdFilter.doFilterInternal(CorrelationIdFilter.java:71) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.web.servlet.resource.ResourceUrlEncodingFilter.doFilter(ResourceUrlEncodingFilter.java:67) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:126) at org.springframework.boot.web.servlet.support.ErrorPageFilter.access$000(ErrorPageFilter.java:64) at org.springframework.boot.web.servlet.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:101) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.springframework.boot.web.servlet.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:181) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:156) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:682) 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:617) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:932) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1695) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:833)

With Java 8 it just works. Spring-WS 3.1.6 is used.

Interestingly, I found a workaround. If I use a custom PayloadValidatingInterceptor (like mentioned here: Stackoverflow), it works again.

beat2 avatar Jun 23 '23 14:06 beat2

Java 8 -> Java 17 seems to hit SOAP land hardest due to the sheer number of packages pulled out of the JDK that migrated either to Jakarta EE or to external projects.

Some of the clues are captured here: https://spring.io/blog/2022/12/02/spring-ws-samples-upgraded-for-spring-boot-3-0

And there are more code examples here: https://github.com/spring-projects/spring-ws-samples

Of course, the examples just provided illustrate how to use Spring WS with Spring Boot 3 combined with Java 17, so that means Java 17 as well as Jakarta EE 9+. To use Spring WS 3.1 with Java 17 requires a bit of a mixture because that version does NOT use Jakarta EE 9+, meaning you are still on the javax.* packages, but you won't find anything you are looking for inside the JDK.

Now we actually test the 3.1.x branch against Java 17 on our CI system (https://github.com/spring-projects/spring-ws/blob/3.1.x/Jenkinsfile#L127-L140). The clue is in the java11 profile in our build file (https://github.com/spring-projects/spring-ws/blob/3.1.x/pom.xml#L723-L840).

You may want to check that out, and also compare that with the versions of the SOAP provider we have on our 3.1.x branch compared to the version of your SOAP provider. SOAP can be rather brittle, so it's vital that all these parts are properly aligned.

I frankly can't see what's breaking, but it could be any of these things (or something else!)

gregturn avatar Jul 12 '23 14:07 gregturn

Thanks for your reply.

Yes, that is true. We use Spring Boot 2.7.12, are not (yet) on Spring Boot 3.

I am unsure if the problem is in Spring WS or in the JDK. The exception happens in internal JDKs Xerces code.

  • But then again, if I log and validate the XML in question that works.
  • It also works when providing the "real" / original Xerces, but then Spring complains a bit about the OWASP-Security-Settings.
  • It also works when using the mentioned workaround, but converting to a String might double the used Heap-Size I fear.

I will try to compare the dependencies next, to see if something differs.

beat2 avatar Jul 14 '23 12:07 beat2

Tried to change dependencies, but it did not make a difference.

I tried to switch off the webservice security, then it validates. So it might be related to something like wss4j, I don't know. We are using Wss4jSecurityInterceptor wrapped in a DelegatingSmartSoapEndpointInterceptor.

Here is a reproducible project that has the issue: https://github.com/beat2/demo

beat2 avatar Aug 04 '23 12:08 beat2

@beat2 Java 17 doesn't include all the dependencies you need. If you are on Spring Boot 2.7.x I suggest remain on Java 8. If you want to move to Java 17 consider upgrading to Spring Boot 3.2.x

corneil avatar May 09 '24 11:05 corneil

Tried to change dependencies, but it did not make a difference.

I tried to switch off the webservice security, then it validates. So it might be related to something like wss4j, I don't know. We are using Wss4jSecurityInterceptor wrapped in a DelegatingSmartSoapEndpointInterceptor.

Here is a reproducible project that has the issue: https://github.com/beat2/demo

The jakarta xml dependencies are not going to work with Spring WS 3.x

corneil avatar May 09 '24 11:05 corneil