Jersey2 - Multivalue response headers are not comma separated - jersey

For a REST service, I'm adding multiple values to a header and the client expects the values to be comma separated in the response header:
test-header: value1, value2
I have implemented this in a ContainerResponseFilter like this:
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
String headerOfInterest = "test-header";
List<String> header = responseContext.getStringHeaders().get(headerOfInterest);
if (header == null) {
responseContext.getHeaders().addAll(headerOfInterest, "value1", "value2");
}
}
However this seems to add the headers twice, instead of comma separating the values.
...
test-header: value1
test-header: value2
...
I have tried using responseContext.getHeaders().add() twice and adding each value, but whichever way I add the values, they end up showing two times in the response instead of being comma separated.
From this SO post, to me it seems comma separated multi value is the standard. So how do I achive this in Jersey?
Jersey version: 2.29
Tomcat version: 9.5

Related

Array format changes with WebClient Post is used

I am trying to send the below JSON via WebClient to an endpoint. I tried sending it as a POJO, a Map, and a JsonNode for the request body but the array is converted to the index-based format.
JSON to be sent;
{
"jediId":"23",
"name":luke,
"master":"yoda",
"address":[
{
"planet":"tatooine",
"city":"mos eisley"
}
],
"filters":{
"male":1,
"female":1,
"padawan":0,
"master":1
}
}
On the other side, the address is converted to address[0].planet=tatooine, address[0].city=mos eisley i.e the format changes
I created a JsonNode with the Jackson and printed the exact format but the array changes in the response.
public Jedi sendRequest(String url, JsonNode request) {
return webClient.post()
.uri(url)
//.bodyValue(request)
.body(BodyInserters.fromValue(request))
.retrieve()
.bodyToMono(Jedi.class)
.blockOptional()
.orElseThrow();
}
}
A similar format change happens to "filters" as well. For example, filters.male=1
I tried both body and bodyValue functions but the result is the same. I am missing something but could not figure out what it is. Any help would be great.
Thanks!
You need to send it as a String that holds valid JSON format. SpringBoot uses JSON Jackson lib and will parse it. It is a responsibility of your SpringBoot end point to parse it. So, really you should ask person who developed the endpoint what info is expected. But in most cases it is String that holds valid json. It might be required that json conforms to particular schema but that is the info that should be included in your endpoint requirments
Thanks to Michael for stating the point of using String in the request. I converted the whole JSON into a String but what I should have done was convert the "filters" and "address" into a String as well.
private ObjectNode setRequestWithMapper() throws JsonProcessingException {
ObjectNode request = objectMapper.createObjectNode();
//other key values ..
String AddressArrayStr = objectMapper.writeValueAsString(addressArray);
String filterStr = objectMapper.writeValueAsString(filters);
request.put("address", AddressArrayStr );
request.put("filters", filtersStr);
return request;
}
And for the body;
public Jedi sendRequest(String url, JsonNode request) {
return webClient.post()
.uri(url)
.bodyValue(request)
.retrieve()
.bodyToMono(Jedi.class)
.blockOptional()
.orElseThrow();
}
}

Pass a string in payload of POST

Usually we pass key-value pair in JSON payload for POST/PUT request. Is it possible to pass a sting only ex:
If so what do we set the object for #RequestBody? Would it be String type or JSONObject?
I did this:
#PostMapping(value = "businessdate", consumes = MediaType.TEXT_PLAIN_VALUE)
public void postBusinessDate(#RequestBody String businessDate) throws IOException, InterruptedException, SQLException {
businessDateService.updateBusinessDate(LocalDate.parse(businessDate));
}
and passed this:
It would be a String. Even though you choose content type as application/json
What worked for me is setting
#PutMapping(value = "/test/{id}", consumes = MediaType.APPLICATION_JSON_VALUE)
String updateInfo(#RequestHeader(#PathVariable("id") String id, #RequestBody String payload){...}
and passing the string payload by escacping the double quotes
updateInfo(token, id, "\"TEST\"");

swagger documentation for endpoint with url pattern

I want to create swagger documentation for an endpoint with ** pattern. In swagger-ui page I find the endpoint but there isn't any input for url of **. My endpoint signature is:
#GetMapping("/{category}/**")
public DocumentModel fetch(HttpServletRequest httpServletRequest, #PathVariable("category") String category)
I want to call above endpoint by myCategory/test/document1 address but there isn't any placeholder for test/document1. How can I call this endpoint by swagger?
Unfortunately, it is not doable. Swagger supports neither wildcards in the path, nor optional path segments, nor slashes in path parameter values. If you look at the request that swagger-ui executes for your mapping, you will see something like this:
curl -X GET "http://localhost:8080/category1/**"
The stars are not replaced, they are treated as a normal string, not as a placeholder.
I am afraid your only option is modifying the endpoint or adding a new one, e.g:
#GetMapping("/{category}/test/{document}")
#Parameter(name = "document", in = ParameterIn.PATH)
public DocumentModel fetchTest(HttpServletRequest httpServletRequest, #PathVariable("category") String category) {
return fetch(httpServletRequest, category);
}
#GetMapping("/{category}/**")
public DocumentModel fetch(HttpServletRequest httpServletRequest, #PathVariable("category") String category) {
// ...
}
If you need to, you can hide the original endpoint from the swagger-ui:
#GetMapping("/{category}/**")
#Operation(hidden = true)
public DocumentModel fetch(HttpServletRequest httpServletRequest, #PathVariable("category") String category) {
// ...
}

Source code in spring which takes in a JSON String(key-value Pair ) as an input and gives out the Updated JSON string

I need help in the coding of a program in spring which takes in a JSON String(key-value Pair ) as an input and gives out the Updated JSON string
I'm assuming you are asking in terms of REST, if yes then refer below snippet -
#Controller
public class JSONTest {
// Below method will take iput as JSON
#RequestMapping(value="/getData",consumes = MediaType.APPLICATION_JSON_VALUE)
public void consumeJson(#RequestBody String s) {
System.out.println("json body : " + s);
}
// Below method will produce output as JSON
#RequestMapping(value="/sendData",produces= MediaType.APPLICATION_JSON_VALUE)
public String sendJson() {
//Create jsonObject
//do some things with jsonObject, put some header information in jsonObject
return jsonObject.toString();
}
}

Escape hash in post service in Java

I am writing a Test case in Spring boot 1.5.6 Release as shown below:
#Test
public void auditTrailSenderTest() throws Exception {
String queryParameters = "auditActionId=#Create&objectTypeId=#AccBalance";
mockMvc.perform(post("/api/v10/event?"+queryParameters))
.andExpect(status().isOk());
}
The problem is that due to presence of hash in #Create and #AccBalance, the test case fails with status of 400. If i replace # with %23, then it is passed as '%23' without being converted to hash ('#') in Rest Api.
Is there any way to escape this number sign ('#') in query string parameters?

Resources