Restclient returning Uni<Void> causes ProcessingException: RESTEASY003145 - quarkus

I have a restclient with a method returning a Uni<Void>. When calling this rest endpoint I am getting the following exception. What have I done wrong here? How am I supposed to code for rest endpoints that return void? I am doing a call with this endpoint in the middle of a chain
javax.ws.rs.ProcessingException: RESTEASY003145: Unable to find a MessageBodyReader of content-type application/octet-stream and type class java.lang.Void: javax.ws.rs.client.ResponseProcessingException: javax.ws.rs.ProcessingException: RESTEASY003145: Unable to find a MessageBodyReader of content-type application/octet-stream and type class java.lang.Void
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.extractResult(ClientInvocation.java:199)
In the pom.xml I have quarkus-resteasy-jackson quarkus-rest-client quarkus-resteasy-mutiny

Related

EOFException with GZIP Compression

I enabled the GZIP compression for the REST API and during testing, I am getting an EOFException exception.
The Endpoint annotations are here:-
#POST
#Path("/")
#Consumes("application/json")
#Produces("application/json")
#GZIP
Even though I removed the #ZIP annotation still I am getting the same error.
The test case code is here:-
val compressedPayLoad = EntityBuilder.create()
.setText(jsonLoader.loadAsString("abc.json"))
.gzipCompress()
.build()
val req = HttpPost("$rootPath/").entity(compressedPayLoad).addAuthorization()
req.addHeader(HttpHeaders.CONTENT_ENCODING, "gzip")
req.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
val resp = execute(req)
assertEquals(200, resp.statusLine.statusCode)
I added the Provider classes in the METE-INF.services folder
org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor
org.jboss.resteasy.plugins.interceptors.GZIPEncodingInterceptor
org.jboss.resteasy.plugins.interceptors.AcceptEncodingGZIPFilter
During debugging I found the Interparator method called twice and My assumption is that stream is being consumed twice on the server-side, making it “empty” for the second consumer.
Note:- .addAuthorization() is our internal helper function.
The logs from the service are here:-
Interceptor Context: org.jboss.resteasy.core.interception.jaxrs.ServerReaderInterceptorContext, Method : proceed
DEBUG o.j.r.r.i18n ReaderInterceptor: org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor
DEBUG o.j.r.r.i18n Interceptor : org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor, Method : aroundReadFrom
DEBUG o.j.r.r.i18n Interceptor Context: org.jboss.resteasy.core.interception.jaxrs.ServerReaderInterceptorContext, Method : proceed
DEBUG o.j.r.r.i18n MessageBodyReader: org.jboss.resteasy.core.providerfactory.SortedKey
DEBUG o.j.r.r.i18n MessageBodyReader: org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider
DEBUG o.j.r.r.i18n Provider : org.jboss.resteasy.plugins.providers.jackson.ResteasyJackson2Provider, Method : readFrom
DEBUG o.j.r.r.i18n Interceptor : org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor$FinishableGZIPInputStream, Method : read
DEBUG o.j.r.r.i18n Interceptor Context: org.jboss.resteasy.core.interception.jaxrs.ServerReaderInterceptorContext, Method : proceed
DEBUG o.j.r.r.i18n ReaderInterceptor: org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor
DEBUG o.j.r.r.i18n Interceptor : org.jboss.resteasy.plugins.interceptors.GZIPDecodingInterceptor, Method : aroundReadFrom
ERROR c.t.s.e.CatchAllExceptionMapper Unhandled exception
java.io.EOFException: null
Here we can see the aroundReadFrom method called twice. Is there anything that I am missing or anyone faced this issue before. Please help me with this.

Pass through SOAP proxy spring Unsupported media type multipart/related; type="application/xop+xml"; boundary

Hi I am trying to implement a pass through SOAP proxy via #RestController in spring. For this purpose I have mapped a rest controller in following way:
#RestController
class MyProxy {
#PostMapping(value = "/**")
public ResponseEntity<String> proxyPost(#RequestBody(required = false) String body, HttpServletRequest request) {}
}
The regular SOAP requests are going OK. The problem comes when a MTOM type of SOAP request is send via the proxy. Then spring failes with unrecognized content type. Here is the exception:
Caused by: org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is javax.servlet.ServletException: Unsupported Content-Type [multipart/related; type="application/xop+xml"; boundary="uuid:dacf4733-80b4-41bc-b2e1-db69b6beadf6"; start="<root.message#cxf.apache.org>"; start-info="text/xml"], expected [multipart/form-data]
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.handleParseFailure(StandardMultipartHttpServletRequest.java:124)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:115)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:88)
at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:122)
at org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1205)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
... 60 common frames omitted
Caused by: javax.servlet.ServletException: Unsupported Content-Type [multipart/related; type="application/xop+xml"; boundary="uuid:dacf4733-80b4-41bc-b2e1-db69b6beadf6"; start="<root.message#cxf.apache.org>"; start-info="text/xml"], expected [multipart/form-data]
at org.eclipse.jetty.server.Request.getParts(Request.java:2407)
at javax.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:317)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:95)
... 66 common frames omitted
When receiving a multipart/* request Spring delegates this to the configured Multipart handler. This is enabled by default and for this case should be disabled.
spring.servlet.multipart.enabled=false
Adding the above to your properties should disable it and prevent the parsing, so you can handle it in your controller.

Spring Boot WS-Server - Custom Http Status

I published endpoints using Spring Boot WS-Server
When I use SoapUI I see:
HTTP/1.1 200
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Content-Length: 828
Date: Thu, 29 Apr 2021 14:04:54 GMT
Keep-Alive: timeout=60
Connection: keep-alive
I would like to set custom HTTP Status in response (I know that it may be against the standard but it is an external requirement). I also read following topic:
Spring WS (DefaultWsdl11Definition) HTTP status code with void
But this solution failed
Spring Boot version: 2.2.7
Problem was solved
As I said I wanted to set custom HTTP status in SOAP response.
I found this post:
Spring WS (DefaultWsdl11Definition) HTTP status code with void
Author used EndpointInterceptor with TransportContext to get HttpServletResponse, then he changed status. The difference between my and his case is the fact, that he returned void from WebService method whereas I wanted to return some response.
In my situation following code in Spring WebServiceMessageReceiverObjectSupport class (method handleConnection) overrode servlet status previously set in interceptor:
if (response instanceof FaultAwareWebServiceMessage && connection instanceof FaultAwareWebServiceConnection) {
FaultAwareWebServiceMessage faultResponse = (FaultAwareWebServiceMessage)response;
FaultAwareWebServiceConnection faultConnection = (FaultAwareWebServiceConnection)connection;
faultConnection.setFaultCode(faultResponse.getFaultCode());
}
In order to bypass this fragment of code I needed to define class with my own implementation of handleConnection method, which extended class WebServiceMessageReceiverHandlerAdapter
In my implementation I excluded change of status. Important thing is to pass WebMessageFactory bean in autowired constructor of this class, otherwise exception is raised during app's startup.
This class has to be marked with Spring stereotype (eg. #Component) and name of this bean has to be configured in Configuration class when configuring ServletRegistrationBean:
#Bean
public ServletRegistrationBean<MessageDispatcherServlet> messageDispatcherServlet(ApplicationContext applicationContext){
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
servlet.setMessageFactoryBeanName("webServiceMessageFactory");
servlet.setMessageReceiverHandlerAdapterBeanName("myOwnMessageReceiverHandlerAdapter");
return new ServletRegistrationBean<>(servlet,"/ws/*");
}

Springboot throwing giving Jackson exceptions

During testing , I have faced the issue.I have published a rest API with a controller class with a model input .
While Calling the API , instead of a single string , an array [{"a":1,"b":2}] has been used. Which triggered the following error:
{
"timestamp": "2018-12-19T12:33:36.729+0000",
"status": 400,
"error": "Bad Request",
"message": "JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token\n at [Source: (PushbackInputStream); line: 3, column: 14] (through reference chain: com.xy.df.model.inputReq[\"req\"])",
"path": "x/y/z"
}
We did not imported JACKSON dependency in application , explicitly in POM. I have noticed in the parent pom jackson version used is :2.9.5
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
1.Is it vulnerable for RCE? How to resolve this in Spring-boot ?
2. How I can supress/override the exception message so that client never gets to know what libraries used underneath ?
JsonMappingException: out of START_ARRAY token exception is thrown by Jackson object mapper as it's expecting an Object {} whereas it found an Array [{}] in response.
This can be solved by replacing Object with Object[] in the argument for geForObject("url",Object[].class).
References:
Ref.1
Ref.2
Ref.3
I have resolved issue . Before going ahead , one needs to understand couple of very useful annotations-
#ExceptionHandler - This handler helps you define an error class for which you want to catch the exception
#controller advice - It caters a cross cutting approach . Any class mentioned as controller advice , it is available for all the controller under your microservice.
#ControllerAdvice
public class ExceptionController {
#Autowired
SomeGenericResponse someGenericResponse ; /* data model of common response */
#ExceptionHandler(value = <My case Jackson Class>.class)
public ResponseEntity<SomeGenericResponse> CustomException(HttpServletRequest req, HttpServletResponse res,Exception ex) {
someGenericResponse.setMessage("Your Message");
someGenericResponse.setStatus("false");
return new ResponseEntity<SomeGenericResponse> someGenericResponse ,HttpStatus.BAD_REQUEST);
}
}

How do i resolve this : javax.ws.rs.NotFoundException: HTTP 404 Resource_not_found

I was trying to get familier with JAX-RS and here is my code sniplets
WebTarget target; // this object reference was created successfully
public Client[] getClients() {
return target.request().get(Client[].class); // NOTE target is not null
}
This is the exception which is logged
Caused by: javax.ws.rs.NotFoundException: HTTP 404 Resource_not_found
at org.glassfish.jersey.client.JerseyInvocation.convertToException(JerseyInvocation.java:945)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:784)
at org.glassfish.jersey.client.JerseyInvocation.access$500(JerseyInvocation.java:91)
at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:672)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:668)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:397)
at org.glassfish.jersey.client.JerseyInvocation$Builder.get(JerseyInvocation.java:297)
at org.business.bee.client.ClientBean.getClients(ClientBean.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
If an error is thrown in a getter you'll get the _"FATAL: JSF1073: javax.el.ELException caught during processing of RENDER_RESPONSE 6"_ or similar. The underlying (real!) error has nothing to do with jsf, ejb, jstl or facelets. Just make sure the following exception (thrown in your code trying to access a rest service) does not happen:
javax.ws.rs.NotFoundException: HTTP 404 Resource_not_found

Resources