I have a Response Class with the set of private fields. Front end developers asked me to send the response of a service in this JSON format.
So far
Response should in JSON format and like this
{
"status": "SUCCESS",
"message": {
"code": "040",
"description": "verified"
},
"qrContent": "aaa | bbb"
}
QrCodePaymentResponse response = new QrCodePaymentResponse();
if (firstThree.equalsIgnoreCase(QRType.EZDYNAMIC.getDescription())) {
axiPayQrCodePaymentService.ezCashDynamicQR(axiPayQrCodePayment,serviceContext);
response.setStatus(RequestStatus.SUCCESS.getStatus());
response.setMessage(----------------);
response.setQrContent(returnValue.getQrContent);
}
How to modify above code to send requested format?
Thanks.
use the spring RestController. it's methods return the data as a JSON format
QrCodePaymentResponse.java
public class QrCodePaymentResponse{
private String response;
private String qrContent;
private Message message;
//set getters and setters
}
Message.java
public class Message{
private String code;
private String description;
//set getters and setters
}
AppController.java
#RestController
public class AppController {
#RequestMapping(value="/get", method=RequestMethod.GET)
public QrCodePaymentResponse getPaymentResponse(){
QrCodePaymentResponse response = new QrCodePaymentResponse();
Message message = new Message();
//set values to message
if (firstThree.equalsIgnoreCase(QRType.EZDYNAMIC.getDescription())) {
axiPayQrCodePaymentService.ezCashDynamicQR(axiPayQrCodePayment,serviceContext);
response.setStatus(RequestStatus.SUCCESS.getStatus());
response.setMessage(message);
response.setQrContent(returnValue.getQrContent);
}
return response;
}
}
Related
I am new to Apex and SF and I have to manage some errors from an 3rd party API we are calling. I have been using DTO with very simple response objects and the error response object we get back has one more level.
JSON response from API:
{
"error": {
"message": "File couldn't be downloaded: main_panel"
}
}
DTO file:
public class CreateCadRequestError {
public string error;
public CreateCadRequestErrorMessage message;
}
public class CreateCadRequestErrorMessage {
public string message;
}
Apex class deserializing data
class SoloConnector {
resp = makeNetworkCall()...
SoloDTO.CreateCadRequestError resp = ( SoloDTO.CreateCadRequestError )JSON.deserialize( response.getBody(), SoloDTO.CreateCadRequestError.class );
System.debug('resp: ' + resp.error + resp.message);
}
I am getting an error
illegal value for primitive
I assume its my DTO class and not being able to serialize the data. Any suggetsions?
Found the answer, My DTO set up was incorrect:
public class CreateCadRequestError {
public CreateCadRequestErrorMessage error;
}
public class CreateCadRequestErrorMessage {
public string message;
}
I am developing a restful web application using java and jax-rs. In server side, I have to accept Json type requests as given by the client using POST method.
#POST
#Path("/Request")
#Consumes(MediaType.APPLICATION_JSON)
public String process(SMessage message) throws Exception {
message.getHeader();
message.getBody();
}
The json object have two composite fields like in the below format.
{
"header": {
"serviceType": "A"
},
"body": {
"id": "1",
"name": "abc"
}
}
Based on the serviceType specified in the Header field, the parameters in the body will differ. I need to map this body field in to a java POJO class. The POJO class is not the same for all requests. How can I achieve this effectively?
If you are using Jackson as your JSON parser, a simple way is to declare body to be a JsonNode to handle dynamic keys as follows:
class MyResponse {
private MyHeader header;
private JsonNode body;
//general getters and setters
}
And I assumed that you have already a POJO for header such as:
class MyHeader {
private String serviceType;
//general getters and setters
}
Finally, let's verify that it works:
String responseStr = "{\"header\": {\"serviceType\": \"A\"},\"body\": {\"id\": \"1\",\"name\": \"abc\"}}";
ObjectMapper mapper = new ObjectMapper();
MyResponse myResponse = mapper.readValue(responseStr, MyResponse.class);
System.out.println(myResponse.getBody().get("name").asText());
Console output:
abc
Another way to solve this issue is by using Map and everything else is the same:
class MyResponse {
private MyHeader header;
private Map<String, Object> body;
//general getters and setters
}
#RequestBody not accepting the request from the client. Kindly help me to solve this
For testing, I am sending JSON data from postman in raw(application/JSON) to my controller in the below format
Error in postman: The request sent by the client was syntactically incorrect.
But I guess this is the correct format of JSON. Please correct me if am wrong
{
"flight_details": [
{
"flight_from": "Bangalore",
"flight_to": "Hyderabad"
},
{
"flight_from": "Delhi",
"flight_to": "Pune"
}]
}
Here is my controller code:
#RequestMapping(value="addFlightDetails", method = RequestMethod.POST)
public void addOfferTest(HttpServletRequest request, HttpServletResponse
response,#RequestBody RequirementBean requirementbean){
System.out.println("flightdetails:"+requirementbean.getFlight_details());
}
My Bean class:
public class RequirementBean {
private String flight_details;
//Getters and Setters
}
If I am sending the same request in the below format I am able to receive request
{"flight_details":"Bangalore"}
But my desired format is the one which mentioned above.
Please help me to fix this issue
Try this might works for you...
#RequestMapping(value="addFlightDetails", method = RequestMethod.POST)
public void addOfferTest(HttpServletRequest request, HttpServletResponse
response,#RequestBody String json){
JSONObject mainObject=new JSONObject(json);
JSONObject flightdetails=mainObject.getJSONObject("flight_details");
String flight_from=flightdetails.getString("flight_from");
String flight_from=flightdetails.getString("flight_from");
System.out.println(flight_from);
System.out.println(flight_to);
}
let me know any issues...
You send a json array to controller. you need to a list to get this array. It could be like this.
public class FlightDetails{
private String flight_from;
private String flight_to;
//Getters and Setters
}
public class RequirementBean {
private List<FlightDetails> flight_details;
//Getters and Setters
}
Change your RequirementBean code as below
public class RequirementBean {
private List<FlightDetail> flight_details;
//Getters and Setters
}
public class FlightDetail {
private String flight_from;
private String flight_to;
//Getters and Setters
}
You are trying to convert a JSON array to String which is incorrect. You can do it in two ways
1. Create a bean FlightDetails with fields from and to. In this case your controller becomes
#RequestMapping(value="addFlightDetails", method = RequestMethod.POST)
public void addOfferTest(HttpServletRequest request, HttpServletResponse
response,#RequestBody FlightDetails[] requirementbean){ }
Use RequirementBean which contains array or list of FlightDetail beans.
public class RequirementBean {
private List flight_details;
//Getters and Setters
}
Can you try this ?
#RequestMapping(value="addFlightDetails",method=RequestMethod.POST)
public #ResponseBody void addFlightDetails(#RequestBody String data,HttpServletRequest request,HttpServletResponse response,HttpSession session,OutputStream outp) {
DBObject dBObject = new BasicDBObject();
String message = "";
JSONParser parser = new JSONParser();
Object obj = parser.parse(new StringReader(data));
JSONObject jsonObject = (JSONObject) obj;
System.out.println(jsonObject);
}
I have to read JSON values from the URL using a query parameter for GET request.
I am using Tomcat latest in a Spring Boot project.
#RequestMapping(
value = "/values",
method = RequestMethod.GET,
headers = HttpHeaders.ACCEPT + "=" + MediaType.APPLICATION_JSON_VALUE,
produces = "application/json")
public ResponseEntity<String> myMethod(
#RequestParam(value="key") String jsonRequestString) {
//parse JSONString
//--
}
GET request to the URL
Url:- http://localhost:port/values?key={"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Throws
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
EDIT :- Sending JSON in original form leading me to nowhere, so working approach would be to send the JSON in an encoded form.
You can encode the key parameter to Base64 format and append to the URL, then decode and use it in your controller method.
Key JSON text:
{"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Base64 encoded text:
eyJvcmciOiJBQSIsInBvaW50cyI6W3sibmFtZSI6Inh5IiwiTWVhc3VyZXMiOiIzNDMifV19XQ==
Decoded to again back to JSON text:
{"org":"AA","points":[{"name":"xy","Measures":"343"}]}]
Few things you should take care of.
Use POST HTTP method to post your JSON to server.
Create a JAVA pojo class which should has a same structure as your JSON. Like for below JSON,
{
"id": 123,
"status": "Ordered",
"product": "Pepsi"
}
i would create a class( You can create a two separate class as you has array inside json) ,
public class Order {
private long id ;
private String status;
private String product ;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
}
Then,
#RequestMapping(value = "/values", method = RequestMethod.POST,produces={"application/json"},
consumes={"application/json"})
public ResponseEntity myMethod(
#RequestBody Order orderObj) {
}
Please take reference from this example and build the solution.
You can directly pass String into the JSONObject constructor
There are lots of libraries available.
1.http://www.java2s.com/Code/Jar/j/Downloadjavajsonjar.htm (JSON jar)
2.http://www.java2s.com/Code/Jar/j/Downloadjsonsimple11jar.htm (Simple JSON)
3.http://www.java2s.com/Code/Jar/g/Downloadgson224sourcesjar.htm (GSON from google)
I personally use JSON and GSON jars.
JSONObject jsonObject = new JSONObject(variable)
You can simply try something like this
#GetMapping(value = "/values", produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<String> testMethod(#RequestParam("key") String key) throws Exception {
JSONObject jsonObject = new JSONObject(key);
//
}
I use Jersey API for my REST service. My question is: Is there a more elegant way of returning exceptions in a JSON form? Is it better to concern myself with creating a json object myself and attaching it to the response directly?
This is a simplified example of one of the methods in the service. As you see, I use HashMap only because the method may throw an exception, in which case I need to return information about It.
#Path("/admin")
public class AdminService {
#Context
HttpServletRequest request;
#POST
#Produces(MediaType.APPLICATION_JSON)
public Map<Integer, String> createCompany(Company company){
Map<Integer, String> map = new HashMap<>();
try{
AdminFacade adminFacade = (AdminFacade)Utility.getFacade(request);
adminFacade.createCompany(company);
map.put(1,"success");
} catch (ExceptionREST e) {
map.put(e.getErrorNumber(), e.getMessage());
} finally {
return map;
}
}
}
You can create a class like the one below to represent an error,
#JsonPropertyOrder({ "code", "field", "message" })
public class ErrorInfo {
private String code;
private String field;
private String message;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
You can create a class which extends an exception like this,
public class InvalidInputException extends RuntimeException {
private static final long serialVersionUID = -5027121014723838738L;
private List<ErrorInfo> errors;
public List<ErrorInfo> getErrors() {
return this.errors;
}
public InvalidInputException(List<ErrorInfo> errors) {
super();
this.errors = errors;
}
public InvalidInputException(String message, List<ErrorInfo> errors) {
super(message);
this.errors = errors;
}
}
And have a exception mapper, where you can convert the List to json and return to the user with http status code 400 (Bad Request).
#Provider
public class InvalidInputExceptionMapper implements ExceptionMapper<InvalidInputException> {
#Override
#Produces(MediaType.APPLICATION_JSON)
public Response toResponse(InvalidInputException e) {
ResponseBuilder rb = Response.status(Status.BAD_REQUEST);
rb.entity(e.getErrors());
return rb.build();
}
}
Http Response will be,
HTTP/1.1 400 BAD REQUEST
{
"errors": [{
"error": {
"code": "100",
"field": null,
"message": "Name is required"
},
"error": {
"code": "100",
"field": null,
"message": "Age is required"
}
}]
}
I believe it is quite popular that people use http response status code to handle the error. E.g. 404 status is not found 5xx is server internal error e.t.c.
You can easily set the error code by using the Response object.
Instead of returning a map, return a Response object.
#Path("/admin")public class AdminService {
#Context
HttpServletRequest request;
#POST
#Produces(MediaType.APPLICATION_JSON)
public Response createCompany(Company company){
Map<Integer, String> map = new HashMap<>();
try{
AdminFacade adminFacade = (AdminFacade)Utility.getFacade(request);
Company commpany=adminFacade.createCompany(company);//this entity annotated by XmlRootElement
Response response=Response.ok().entity(company).build();
} catch (ExceptionREST e) {
response=Response.status(404).build();
} return response;
}}
To make the Restful api more robust, some will return an OK response to prevent "smart redirect" from the server and output some weird html.
you can refer here for a list of http status code and what it mean.
For Java EE Response class, you can refer the official javadoc
You can wrap your error into a class, say I have an ErrorData class which has status, message and stacktrace. Everytime an exception occurs, I throw a GeneralAppException with the errordata object.
public class GeneralAppException extends WebApplicationException {
public GeneralAppException(ErrorData er) {
super(Response.status(er.getStatusCode()).
entity(er).type(MediaType.APPLICATION_JSON).build());
}
}
I have another class which has all the known errors, eg.
public static final ErrorData NODATAFOUND = new ErrorData(Response.Status.NOT_FOUND.getStatusCode(),"No data was found for given query");
public static final ErrorData CODEERROR = new ErrorData(502,"CodeError");
Your catch can look like
catch (ExceptionREST e) {
throw new GeneralAppException(ErrorData.NODATAFOUND);
}
Reference used : https://jersey.java.net/documentation/latest/representations.html#d0e6665