How to change content type for two different objectives in Spring Controller? - spring

I am working on an API that displays JSON data and downloads CSV in one single API.
The problem is how to change Content-type of my header when I intend to download CSV file ?
Below is my code :
#RequestMapping(value = "${api.route.get.all.report}", method = RequestMethod.POST)
#PreAuthorize("hasAnyAuthority('super_admin','owner','admin')")
public ResponseEntity<?> getReportForAll(
#ApiParam("partnerId") #RequestParam(value = "partnerId", required = false) String partnerId,
#ApiParam("orgId") #RequestParam(value = "orgId", required = false) String orgId,
#ApiParam("eventId") #RequestParam(value = "eventId", required = false) String eventId,
#ApiParam("export") #RequestParam(value = "export") boolean export,
#ApiParam("Search Filter") #RequestBody SearchCriteriaDTO filterRequestDTO,
HttpServletResponse httpServletResponse) throws WazooException, IOException {
Object response = reportService.getReportsForAll(filterRequestDTO, partnerId, orgId, eventId, export,
httpServletResponse);
if (export) {
httpServletResponse.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
httpServletResponse.setHeader("Content-Disposition", "filename=" + response);
return ResponseEntity.ok(waasAppUtils.createResponseEntityDTO(HttpStatusCodes.OK,
applicationUtility.getMessage("fetched"), response));
} else {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
return ResponseEntity.ok(waasAppUtils.createResponseEntityDTO(HttpStatusCodes.OK,
applicationUtility.getMessage("fetched"), response));
}
}
If the purpose is only to display data(when JSON data is populated), then its working as expected and I am getting following Headers :
Content-Type →application/json;charset=UTF-8
Date →Wed, 14 Mar 2018 12:27:07 GMT
Expires →0
Here is my response
{
"response_code": 200,
"response_message": null,
"response_body": [
{
"name": "",
"totalCharges": {
"platformCharge": 0.5,
"totalCharge": 0.2,
"basicCharge": 0.3
},
"id": "5a97a5930467kf42f6a2eof1"
},
All good till this point. Now the problem is, when I wish to download CSV(export flag set to true), it returns simply the file name in response body :
{
"response_code": 200,
"response_message": null,
"response_body": "/home/reports/Report_Wed Mar 14 12:26:56 UTC 2018.csv"
}
and the content-type is still displaying me "application/json;charset=UTF-8"
How can i change the content type when the flag is set to be true and display data accordingly ???

If you want to return just file in case of export, try this out:
...
if (export) {
return ResponseEntity
.ok()
.contentType(MediaType.parseMediaType("text/csv"))
.header("Content-Disposition", "filename=" + fileName)
.body(<put your file content here as byte array>);
}
...

Related

Call GraphQL api from Rest endpoint in spring boot returning null value

From my rest endpoint I am trying to call 3rd party graphql api but in response I am getting null values.
Request:
{
"query": "query($id: String!) { hiringOrganization (id: $id) { name } }",
"variables": {
"id": "seekAnzPublicTest:organization:seek:93WyyF1h"
}
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"data": {
"hiringOrganization": {
"name": "Acme Corp"
}
}
}
Inside the resource folder I have placed Query and variable request:
query($id: String!) { hiringOrganization (id: $id) { name } }
Variables:
{
"id": "hiringId"
}
From Postman I am getting the below response:
[![enter image description here][3]][3]
Calling the Query and variables from resource folder:
public static String getSchemaFromFileName(final String fileName) throws IOException {
if(fileName.contains("Variables")){
log.info("inside variables::"+fileName);
return new String(
GraphqlSchemaReaderUtil.class.getClassLoader()
.getResourceAsStream("seekGraphQL/variables/"+fileName+".graphql")
.readAllBytes()
);
} else {
log.info("inside query::"+fileName);
return new String(
GraphqlSchemaReaderUtil.class.getClassLoader()
.getResourceAsStream("seekGraphQL/query/" + fileName + ".graphql")
.readAllBytes()
);
}
}
Calling the graphql endpoint:
public Mono<HiringDTO> getHirerDetails(final String id) throws IOException {
GraphqlRequestBody requestBody=new GraphqlRequestBody();
final String query= GraphqlSchemaReaderUtil.getSchemaFromFileName("hiringQuery");
final String variables= GraphqlSchemaReaderUtil.getSchemaFromFileName("hiringVariables");
log.info("before id::"+id);
requestBody.setQuery(query);
requestBody.setVariables(variables.replace("hiringId",id));
log.info("id::"+id);
return webclient.post()
.uri(url)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(HiringDTO.class);
}
My rest end point is a post request which has hiring Id in request body . I don't know why I am getting the null values. Please assist me to find out the issues.
Postman request/response:

Servicestack GlobalRequestFilters populating additional user auth data into Jwt tokens

I want to add additional properties to the response when a user logs in.
When calling https://Servicestackservice/auth/credentials?userName=****&password=**** I get the below response. I want to add 2 additional values. DateFormat & TimeZone
{
"userId": "21",
"sessionId": "****",
"userName": "SystemAdmin",
"displayName": "System Admin",
"referrerUrl": null,
"bearerToken": "****",
"refreshToken": *",
"profileUrl": *",
"roles": [ View
],
"permissions": [ View
],
"responseStatus": {
"errorCode": null,
"message": null,
"stackTrace": null,
"errors": null,
"meta": null
},
"meta": null
}
I found an example from the SS forums. I had to modify it some to make it run.
From the SS docs
Modifying the Payload
Whilst only limited info is embedded in the payload by default, all matching AuthUserSession properties embedded in the token will also be populated on the Session, which you can add to the payload using the CreatePayloadFilter delegate. So if you also want to have access to when the user was registered you can add it to the payload with:
I am hoping this is how i get them into the "matching AuthUserSession"
this.GlobalRequestFilters.Add(async (req, res, requestDto) =>
{
AuthFilter.AuthResponse(req, res, requestDto);
});
public static void AuthResponse(IRequest req, IResponse res, object response)
{
var authRes = response as Authenticate;
if (authRes == null || authRes.UserName == null)
{
return;
}
var session = (CustomUserSession)req.GetSession();
if (session != null && session.UserAuthId != null)
{
//General Format for US
string dformat = "g";
using (var db = HostContext.TryResolve<IDbConnectionFactory>().Open())
{
var userAuthExt = db.Single<UserAuthExtension>(ext => ext.UserAuthId == int.Parse(session.UserAuthId));
if (userAuthExt != null)
{
dformat = userAuthExt.DateTimeFormat;
}
}
authRes.Meta = new Dictionary<string, string> {{"TimeZone", session.TimeZone}, {"DateFormat", dformat}};
}
}
Adding this to try to get the JWT tokens to hold the new data. Examining the payload i can see the 2 new values are added to the list.
new JwtAuthProvider(AppSettings)
{
CreatePayloadFilter = (payload, session) =>
{
if (session != null && session.UserAuthId != null)
{
//General Format for US
string dformat = "g";
using (var db = HostContext.TryResolve<IDbConnectionFactory>().Open())
{
var userAuthExt = db.Single<UserAuthExtension>(ext => ext.UserAuthId == int.Parse(session.UserAuthId));
if (userAuthExt != null)
{
dformat = userAuthExt.DateTimeFormat;
}
}
payload["TimeZone"] = ((AuthUserSession) session).TimeZone;
payload["DateFormat"] = dformat;
}
},
You should link to the docs you're referring to, which I believe is ServiceStack's JWT Modifying the Payload docs. Although it's not clear which example in the Customer Forums you're referring to.
It's also not clear what the question is, I'm assuming it's this statement:
When calling /auth/credentials?userName=****&password=**** I do not see the new values.
Where exactly are you expecting these values? If you're authenticating by credentials you're not Authenticating by JWT so you will not have these additional properties populated on your User Session. If they're embedded in your JWT's body payload then as TimeZone is a AuthUserSession property, it should be populated if it was contained within the JWT payload:
case "TimeZone":
authSession.TimeZone = entry.Value;
break;
But DateFormat is not an AuthUserSession property so you will need to populate it manually by providing an implementation for PopulateSessionFilter, e.g:
new JwtAuthProvider(AppSettings)
{
PopulateSessionFilter = (session,payload,req) =>
session.Meta["DateFormat"] = payload["DateFormat"];
}
But these properties are only going populated in the Users Session when authenticating via JWT.
To help diagnose any issues you should but a breakpoint in your CreatePayloadFilter to see what you've populated the JWT payload with and conversely put a breakpoint in your PopulateSessionFilter to inspect what's contained in the payload and resulting populated session.

How to remove unwanted keys from rest-assured response object and assert remaining object data with constant variable having json string using java

In rest-assured test cases I am getting response as mentioned, where I want to remove keys such as "updated_at", "deleted_at", "created_at" and "notice" and then assert this response object with expected json string constant which contains 'settings'
{
"notice": "The Settings are updated successfully.",
"settings": {
"push_notification": {
"enabled": true,
"credentials": [{
"key": "value"
}],
"service_name": "API Testing"
},
"created_at": "2019-05-04T14:52:32.773Z",
"deleted_at": "false",
"updated_at": "2019-05-07T11:23:22.781Z"
}
}
For given response the expected json string is...
public static String SETTING_EXPECTED = "{\"push_notification\": {\"enabled\": true, \"credentials\": [{\"key\": \"value\"}], \"service_name\": \"API Testing\"}}"
Please help me with creating a common method using java which can be reuse for response assertions in all the test cases.
To delete keys from response you can use below code I am using jayway jsonpath library, you need to pass Json Response and field name jsonPath, in case your it will be "$.settings.created_at" :
public String deleteFieldNameFromResponse(String jsonResponse, String fieldToDelete)
throws ParseException, FileNotFoundException, IOException {
Object obj = null;
JSONParser parser = new JSONParser();
JsonPath jsonPath = null;
DocumentContext docCtx = null;
obj = parser.parse(jsonResponse);
docCtx = JsonPath.parse(obj);
docCtx.delete(fieldToDelete);
jsonPath = JsonPath.compile("$");
return docCtx.read(jsonPath).toString();
}

HttpMediaTypeNotAcceptableException when application/json-patch+json is used as 'Content-Type' header

we are using patch operation to support partial update.
#ApiOperation(value="Patch (Partial Update) user payment")
#RequestMapping(method = RequestMethod.PATCH, consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<UserPaymentInfo> patchPaymentInfo(#ApiParam(value = "The user id", required = true)#PathVariable final String uid,
#ApiParam(value = "Whether to reteurn new payment info back") #RequestParam(name = "includeResponse", defaultValue = "false") final boolean includeResponse,#ApiParam(value = "Description of changes")#RequestBody final String userPaymentInfoPatchJson) {
UserPaymentInfo paymentInfo = userPaymentService.patchPaymentInfo(uid,userPaymentInfoPatchJson,includeResponse);
HttpStatus status = includeResponse ? HttpStatus.OK : HttpStatus.NO_CONTENT;
return new ResponseEntity<>(paymentInfo,status);
}
Below mentioned is exception :
{"code": "0000",
"message": "Could not find acceptable representation (HttpMediaTypeNotAcceptableException)",
"host": "localhost",
"url": "/users/000020800464/paymentinfo/test",
"method": "PATCH",
"causes": [
{
"code": "0000",
"message": "Could not find acceptable representation (HttpMediaTypeNotAcceptableException)"
}
]
}
The same endpoint works good for application/json as header value of Content-Type but 'application/json-patch+json' fails.
Does spring boot support patch bcs i am not able to find related header name mentioned in org.springframework.http.MediaType.java

How do i send JsonObject with nested values as Post request in REST assured

I am using rest assured -https://code.google.com/p/rest-assured/wiki/Usage
My JsonObject looks like this
{
"id": "12",
"employeeInfo": null,
"employerInfo": null,
"checkDate": 1395093997218,
"netAmount": {
"amount": 70,
"currency": "USD"
},
"moneyDistributionLineItems": [
{
"mAmount": 100,
"employeeBankAccountId": "BankAccount 1"
}
],
}
how can i send this as part of parameters using REST-assured POST?
I have tried
given().param("key1", "value1").param("key2", "value2").when().post("/somewhere").then().
body(containsString("OK"));
but that is not scalable for HUGE objects with nested values. Is there a better approach?
You just send the JSON document in the body. For example if you have your JSON document in a String called myJson then you can just do like this:
String myJson = ..
given().contentType(JSON).body(myJson).when().post("/somewhere"). ..
You can also use a POJO, input stream and byte[] instead of a String.
URL file = Resources.getResource("PublishFlag_False_Req.json");
String myJson = Resources.toString(file, Charsets.UTF_8);
Response responsedata = given().header("Authorization", AuthorizationValue)
.header("X-App-Client-Id", XappClintIDvalue)
.contentType("application/vnd.api+json")
.body(myJson)
.with()
.when()
.post(dataPostUrl);

Resources