Netty doesn't allow pipe symbol | and throws Exception - spring

My Endpoint is /mz/api/mot/pol/re/pt?Output=1|920222|R1205200130|Success|
I am using a Gateway application on Spring Boot which runs on Netty
and facing below exception,
java.lang.IllegalArgumentException: Illegal character in query at index 46:
at java.net.URI.create(URI.java:852) ~[na:1.8.0_242]
at reactor.netty.http.HttpOperations.resolvePath(HttpOperations.java:300) ~[reactor-netty-0.9.4.RELEASE.jar:0.9.4.RELEASE]
at reactor.netty.http.server.HttpServerOperations.<init>(HttpServerOperations.java:128) ~[reactor-netty-0.9.4.RELEASE.jar:0.9.4.RELEASE]
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:157) ~[reactor-netty-0.9.4.RELEASE.jar:0.9.4.RELEASE]
at
The same error happens in Tomcat also and I solved it by setting relaxedQueryChars property. Kindly suggest how to do this. Thanks in advance.

You'll have to encode the pipes in your query string for netty. The "|" will become %7C
So this: /mz/api/mot/pol/re/pt?Output=1%7C920222%7CR1205200130%7CSuccess
Becomes: `/mz/api/mot/pol/re/pt?Output=1%7C920222%7CR1205200130%7CSuccess
There are lots of tools that will URL encode that string for you if you have control over the client side.
See also:
https://docs.oracle.com/javase/8/docs/api/java/net/URLEncoder.html

Related

Sleuth TraceId IllegalArgumentException Exception

Encountering the below exception, when using Sleuth along with Spring Boot
The Stack trace is as follows :
ZipkinHttpSpanExtractor.joinTrace 51 : Exception occurred while trying to extract span from carrier java.lang.IllegalArgumentException: Can't convert empty hex string to long at org.springframework.util.Assert.hasText(Assert.java:181) at org.springframework.cloud.sleuth.Span.hexToId(Span.java:583) at org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanExtractor.buildParentSpan(ZipkinHttpSpanExtractor.java:91) at org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanExtractor.joinTrace(ZipkinHttpSpanExtractor.java:49) at org.springframework.cloud.sleuth.instrument.web.ZipkinHttpSpanExtractor.joinTrace(ZipkinHttpSpanExtractor.java:19)
Using Sprint Boot version is 1.5.3 and spring-cloud-sleuth-core/1.3.1
Any pointers on the fix would be helpful... Thanks in advance.

Handling custom error code in spring cloud load balancer

In my current project, one of our microservices calls a REST Api of an another microservice and in an error scenario it returns a custom(469) error code.
I'm using a load balanced rest template in the calling service and its throwing an IllegalArgumentException error since 469 error code is not present in HttpStatus enum.
Is there any workaround to resolve this like using raw status codes instead of converting it into an enum?
java.lang.IllegalArgumentException: No matching constant for [469]
at org.springframework.http.HttpStatus.valueOf(HttpStatus.java:547)
at org.springframework.http.client.AbstractClientHttpResponse.getStatusCode(AbstractClientHttpResponse.java:33)
at org.springframework.cloud.client.loadbalancer.ResponseData.<init>(ResponseData.java:68)
at org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.getClientResponse(BlockingLoadBalancerClient.java:120)
at org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient.execute(BlockingLoadBalancerClient.java:94)
at org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor.lambda$intercept$2(RetryLoadBalancerInterceptor.java:129)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:225)
at org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor.intercept(RetryLoadBalancerInterceptor.java:79)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
at org.springframework.boot.actuate.metrics.web.client.MetricsClientHttpRequestInterceptor.intercept(MetricsClientHttpRequestInterceptor.java:86)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
at org.springframework.cloud.sleuth.instrument.web.mvc.TracingClientHttpRequestInterceptor.intercept(TracingClientHttpRequestInterceptor.java:69)
at org.springframework.cloud.sleuth.instrument.web.client.LazyTraceClientHttpRequestInterceptor.intercept(LazyTraceClientHttpRequestInterceptor.java:51)
at org.springframework.http.client.InterceptingClientHttpRequest$InterceptingRequestExecution.execute(InterceptingClientHttpRequest.java:93)
at org.springframework.http.client.InterceptingClientHttpRequest.executeInternal(InterceptingClientHttpRequest.java:77)
at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:670)
I think we can manipulate the status coming from downstream service using interceptors.
Have you tried ClientHttpRequestInterceptor? Here is an example
Fixed in Spring cloud 2021.0.2 and above
https://github.com/spring-cloud/spring-cloud-commons/issues/1066
To use raw status codes instead of converting into an enum add the following property
spring.cloud.loadbalancer.use-raw-status-code-in-response-data: true

"Ambiguous search mapping detected" thrown after adding Springfox 3.0.0 to SpringBoot

I have a SpringBoot application (spring-boot-starter-parent:2.4.0) and I want to use Swagger. I followed this Baeldung-Tutorial, and I am unfortunately getting this exception on startup:
org.springframework.context.ApplicationContextException: Failed to
start bean 'documentationPluginsBootstrapper'; nested exception is
java.lang.IllegalStateException: Ambiguous search mapping detected.
This is due to the fact that I am in some cases overloading methods in my repositories as follows:
Page<Message> findByConversationId(Long conversationId, Pageable pageable);
List<Message> findByConversationId(Long conversationId);
The exception says that both methods
are mapped to /findByConversationId! Tweak configuration to
get to unambiguous paths!
Is there any way to overcome this issue ?
Thank you !
This is not an answer to your problem but it might help you.
Consider using springdoc instead of Springfox. It is a newer library that is easier to use and way less error-prone than Springfox. We moved to it 2 years ago and we are very glad we did. There is very good documentation and tutorials online for it:
https://springdoc.org/
https://www.baeldung.com/spring-rest-openapi-documentation
It is also very active and you usually get your issues answered very fast on the github page.

JDBC DatabaseMetaData method not implemented by JDBC(T4SQLMX) driver

I am setting up a Spring-boot application to connect to HP NonStop Tandem's SQL/MX. First I achieved this connection by hard-coding the jdbc parameters like dataSource, URL, etc in the service section of the application and it worked (I was able to access tables by executing query).
Now I am trying to remove the hard coded part and have my database related info in application.properties file, but now I am getting the following error
org.springframework.jdbc.support.MetaDataAccessException: JDBC DatabaseMetaData method not implemented by JDBC driver - upgrade your driver; nested exception is java.lang.AbstractMethodError: Method com/tandem/t4jdbc/SQLMXConnection.isValid(I)Z is abstract
Can someone help me understand the root cause? The same driver jar is being used when hard-coding the datasource details and it worked but not working when having the data source properties in application.properties and needs an upgrade to the jar.
I encountered the same exception when using Spring Data JPA in a Spring Boot application, the JTDS driver and the Hikari connection pool. In my case I discovered that the following fixed the problem:
Examining the class com.zaxxer.hikari.pool.PoolBase, the following can be observed:
this.isUseJdbc4Validation = config.getConnectionTestQuery() == null;
Thus JDBC 4 validation will not be attempted if there is a connection test query configured. In a Spring Boot application, this can be accomplished like this:
spring.datasource.hikari.connection-test-query=select 1;
Regretfully I do not have any experience with the T4SQLMX driver but nevertheless hope this can be of some use.
I recently fought through the same issue, for me I was using a JDBC type 3 driver; but my spring implementation only supported a type 4 driver, thus when the method you linked above was attempted to be called, it caused the error.
I suggest you look for a type 4 driver for your particular database and see if that resolves your issue.

java.lang.NumberFormatException: For input string: "443,80"

I am getting the following exception while hitting my backend Spring boot application which is deployed on a Kubernetes container:
java.lang.NumberFormatException: For input string: "443,80"
All my services are registered with eureka:
#Eureka
spring.application.name=app-name
eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.client.serviceUrl.defaultZone=http://app-eureka-dev/eureka
eureka.instance.preferIpAddress=true
eureka.instance.non-secure-port-enabled=true
And all my requests are routed through ingress/zuul services.
spring.application.name=app-gateway
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=true
eureka.client.serviceUrl.defaultZone=http://app-eureka-dev/eureka
When we try hitting backend services from the Swagger API, I am getting below exception.
java.lang.NumberFormatException: For input string: "443,80"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at springfox.documentation.swagger2.web.HostNameProvider.componentsFrom(HostNameProvider.java:72)
at springfox.documentation.swagger2.web.Swagger2Controller.getDocumentation(Swagger2Controller.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod
I am connecting to the eureka service through the container name, even though I am getting above exception. Is there any other configuration required, as we do ssl offloading in ingress, rest should be plain http or unsecure calls within the container services.
This should have been fixed with Springfox 2.7.0, as can be seen in this GitHub issue and the release notes of this version.
Before Springfox 2.7.0, the following code was used to determine the port number in HostNameProvider:
String port = request.getHeader("X-Forwarded-Port");
if (hasText(port)) {
builder.port(Integer.parseInt(port));
}
So basically it used the X-Forwarded-Port header to determine the port number. However, in your case it seems like it passes both the HTTP and HTTPS ports (443,80), which is obviously not a valid integer.
Upgrading your springfox-swagger2 dependency to 2.7.0 (or higher) should do the trick.
I experienced the same problem in SWAGGER when my DTO properties annotated with #APIModelProerty. Majorly, the problem occurred when Long type properties are present in the DTO object and failed to convert the empty string ("") value into 0.
So, it solved when I added example property in #APIModelProperty(example = "1", required = "false").

Resources