Bad header in CXF - java

I'm working with CXF WebClient, i tried to do a webclient service and make the call with it, i set JSON type in header, but i getting the wild card in the header
I did this for make the webClient
client = WebClient.create(endPoint,Collections.singletonList(new JacksonJsonProvider())).
accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON);
ClientConfiguration config = WebClient.getConfig(client);
config.getInInterceptors().add(new LoggingInInterceptor());
config.getOutInterceptors().add(new LoggingOutInterceptor());
And i have this to make the get call
Response reponse=clientThreadSafe().path("tokens/{id}",virtualToken.getId()).get();
return genericReponse(Token.class,Status.OK,reponse);
With clientThreadSafe
private WebClient clientThreadSafe() throws CertEuropeException{
//thread safe, see http://cxf.apache.org/docs/jax-rs-client-api.html#JAX-RSClientAPI-ThreadSafety
return WebClient.fromClient(client);
}
And genericReponse
private <T> T genericReponse(Class<T> classReponse, Status status, Response reponse ) throws Exception{
if(reponse.getStatusInfo()!=status){
throw new Exception("somthing bad here");
}
return reponse.readEntity(classReponse);
}
But i getting the wildcard in the call
INFOS: Setting the server's publish address to be
http://localhost:9090 mars 14, 2016 1:52:31 PM
org.apache.cxf.interceptor.LoggingOutInterceptor INFOS: Outbound
Message
--------------------------- ID: 1 Address: http://localhost:9090/api/v1/tokens/1 Http-Method: GET
Content-Type: Headers: {Accept=[*/*]}
And i getting one exception
GRAVE: No message body reader has been found for class com.client.Token, ContentType: application/octet-stream
mars 14, 2016 1:52:31 PM
org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
AVERTISSEMENT: javax.ws.rs.WebApplicationException: HTTP 415 Unsupported Media Type
I don't know why the WebClient is not taking the MediaType.APPLICATION_JSON header, maybe i don't use the right function for set the headers.
If i try with other rest client, like post man, and i set the right header all seem work fine.

After a lots of test, i found that the "Fluent interface" is not really working like it should, it seem that the order is important, and if you set the accept and the type of the WebClient at the beginning, this can be reset.
So for every call i have to made accept(MediaType.APPLICATION_JSON).type(MediaType.APPLICATION_JSON) after the path method, like:
path("tokens/{id}",token.getId())
.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.invoke("GET", "")
If i change the order, the accept and type will not take in count

Related

Sending post request to S3 with RestAssured

I want to reproduce a postman call with RestAssured.
The call send some text parameters and a file parameter to upload file to S3
It look like this :
In rest assured I've done this :
Response response = RestAssured
.given()
.header("Content-Type","multipart/form-data")
.header("Connection","keep-alive")
.formParams(credentials) // credentials is a hashmap containing all the text params
.multiPart("file",new File("src/main/resources/media/desktop_1.webm"),"video/webm")
.post();
I'm getting this error NFOS: I/O exception (java.net.SocketException) caught when processing request to {s}->https://s3HIDDENURL: Connection reset by peer: socket write error avr. 26, 2022 3:40:29 PM org.apache.http.impl.client.DefaultHttpClient tryExecute
I've also tried to change the file from multipart to formParam like this : .formParam("file",new File("src/main/resources/media/desktop_1.webm"),"video/webm")
I've got another error Cannot serialize because cannot determine how to serialize content-type multipart/form-data

Spring Boot: How to resolve Content-Type when incorrectly received from server

I have the following class in Java. I'm expecting it to issue a GET request to the url, get back a JSON payload, and transform that payload to List<LocationData>.
package ...
import ...
#Repository
public class ProxiedLocationRepo {
public List<LocationData> findAll() throws Exception {
RestTemplate restTemplate = new RestTemplate();
String url = UriComponentsBuilder
.fromUriString("https://my-host/path")
.queryParams("some", "queryParams")
.toUriString();
ResponseEntity<List<LocationData>> res = restTemplate.exchange(
url,
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<LocationData>>(){});
if (res.getStatusCode() == HttpStatus.ACCEPTED) {
return res.getBody();
} else {
throw new ResponseStatusException(res.getStatusCode(), "Did not receive a 200 response from Server.");
}
}
}
However, I'm getting back this error:
org.springframework.http.InvalidMediaTypeException: Invalid mime type "charset=UTF-8": does not contain '/'
Which is expected, because if I do the same request from curl, and check the headers I get this (notice Content-Type line):
$ curl -sfi 'https://my-host/path?some=queryParams'
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 06 Mar 2019 13:58:58 GMT
Content-Type: charset=UTF-8
Content-Length: 1821
Connection: keep-alive
Vary: Accept-Encoding
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
... # perfectly formatted JSON payload here
I know that the Content-Type returned from this server is going to be application/json, but it is not providing it to me.
Is there anyway to inform RestTemplate#exchange of what the Content-Type of the response will be? If not, is there any other methodology I could use to resolve this issue besides getting the owners of the server to set the Content-Type correctly?
EDIT:
I have also tried adding the "Accept" header but got the same results:
$ curl -sfi 'https://my-host/path?some=queryParams' \
-H 'Accept: application/json'
Unfortunately I don't think there's any way to fix this while leveraging the Spring framework. Even if you were to create a custom JsonbHttpMessageConverter that accepts a MIME type of ANY, Spring would still fail to parse the incorrect Content-Type received from the request (because it can't find "/" in the Content-Type string).
So the resolution here was to do use java.net.HttpURLConnection to do the networking instead, and then use com.fasterxml.jackson.databind.ObjectMapper to map from the JSON to a POJO.
It works, but at the cost of no longer being able to leverage any of Spring's HTTP handling, which is likely much much more robust than anything I can implement alone.

How do you consume http response content asynchronously with Apache's HTTP async client?

I'm new to Java NIO. I'm using it to make HTTP Get requests. The requests executes properly, but I am unable to figure out how to get the content of the response.
For example,
CloseableHttpAsyncClient httpClient = HttpAsyncClients.createDefault();
httpClient.start();
url = buildUrl(); //builds the url for the GET request
BasicAsyncResponseConsumer consumer = new BasicAsyncResponseConsumer();
Future<HttpResponse> future = httpClient.execute(HttpAsyncMethods.createGet(url), consumer, null)
Now how do I get the content of the response? On printing future, I get the following:
HTTP/1.1 200 OK [Content-Type: application/json, Date: Fri, 24 Jun 2016 20:21:47 GMT, Content-Length: 903, Connection: keep-alive] [Content-Length: 903,Chunked: false]
My response (on the browser) is 903 characters, so I know the it makes the request correctly. However, how do I print out the json content of the result?
There are a couple of ways for you to approach this.
One, call get() on the Future returned by execute, blocking until a result is ready. Once the result is ready, get() will return the HttpResponse object which you can use to retrieve the content with getEntity. The HttpEntity has an InputStream. Read it however you think is appropriate.
Two, provide a smarter HttpAsyncResponseConsumer implementation than BasicAsyncResponseConsumer which reads (and closes) the HttpResponse's HttpEntity and produces a value that can be consumed by the FutureCallback value that is expected as the third argument to HttpAsyncClient#execute. This solution will not block your current thread.

Using JAX-RS (RESTEasy) as middleware: brokering a client's request to another server

I'm building a server using JAX-RS (RESTEasy) that will provide a REST interface to clients. The server will act as a broker between the client and another server. The other server, a 3rd-party server (JasperReports), also has a REST interface. I'd like to use JAX-RS to have my broker talk to that server. (My broker server adds authentication and other services.) So, there you have the three parties: client, broker-server, reports-server.
I see the workflow this way. The broker-server implements JAX-RS (server) to get the client's requests, repackage them, and pass them along to the reports-server, using JAX-RS (client). When the broker-server has obtained a report, I'd like to relay that back to the client. But, so far, I believe that's where things break down.
Here's some code:
// Server gets a request and passes it to its (internal) client, handler.
#GET
#Path("/jobs")
public Response fetchAllScheduledJobs() {
ReportScheduleHandler handler = new ReportScheduleHandler();
Response response = handler.fetchAllScheduledJobs();
return response;
}
Here is the handler sending that off to the reports-server...
public Response fetchAllScheduledJobs() {
Client client = ClientBuilder.newClient();
client.register(getBasicAuthentication());
Response response =
client.target(getReportsBaseUri())
.request()
.accept("application/json")
.get();
client.close();
return response;
}
So, in my (misguided) thinking, I'm thinking that the broker-server just returns the response back to the client, and all is well. But, as I said above, the client is getting nothing back. I'm using a REST developer's client ("Postman"), and here are the headers I'm getting back:
Cache-Control →private
Content-Length →0
Content-Type →application/json
Date →Mon, 14 Jul 2014 16:05:46 GMT
Expires →Wed, 31 Dec 1969 19:00:00 EST
P3P →CP="ALL"
Server →Apache-Coyote/1.1
Transfer-Encoding →chunked
(Copied and pasted, it looks just like that. I have no idea why Postman shows these arrows!)
Any idea what I'm missing here? Does the broker need to somehow unpack the Response it receives from its internal client and repackage that before returning it to the original client? Please ask any questions you need for clarification. Thanks!
Edit
Wait! Could it be that my Response has an input stream and that I need to read that and write out and output stream to the client -- or something like that?
You're closing your client, therefore not unwrapping the Response in an open client context. Unwrap your response, close the client, and return your unwrapped object.
edit:
Sorry, not your client. I believe in the Response object you've got a close() method.
Pretty much like this:
Client client = ClientFactory.newClient();
WebTarget target = client.target("http://foo.com/resource");
Response response = target.request().get();
String value = response.readEntity(String.class);
response.close(); // You should close connections!
return value;

Jersey: how to set MediaType to javax.ws.rs.core.Response, if real "physical" response header does not have any information about it

When I send request to server
...
Response response = builder.method(req.getMethod(), Entity.entity(req, req.getMediaType())); // req.getMediaType() return MediaType.APPLICATION_XML
if(response.getStatus() != 200)
throw new CoreErrorException("core resulted error with status = " + response.getStatus());
T resp = response.readEntity(respType);
...
Jersey throw exception on the last line:
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyReader not found for media type=application/octet-stream
I did some investigation. First of all, I catch that response:
Content-Length: 93
Date: Thu, 21 Nov 2013 12:53:46 GMT
Server: APP
<root>
<returncode>XXX</returncode>
<desc>some description</desc>
</root>
Header does not contain any information about MediaType.
Indeed, when I try to call response.getMediaType(), it returns null.
I think, that is the problem. Jersey cann't detect MediaType of response and set it by default ("application/octet-stream"). But in really the body of my response is XML. Is there some way to tell Jersey about it?
Try to add Accept header into your request by calling WebTarget#request(MediaType),
ClientBuilder.newClient()
.target("mytarget")
.request("application/xml")
.method(req.getMethod(), Entity.entity(req, req.getMediaType()));
whether the server doesn't add Content-Type header to the response. If not you can try to change the headers on the client site using WriterInterceptor or simply by calling
Response response = ...;
response.getStringHeaders().putSingle(HttpHeaders.CONTENT_TYPE, "text/plain");
T resp = response.readEntity(respType);

Categories