RestTemplate Project: the DTO fields changing on their own - java

So I made Rest Client using Spring Boot that is consuming a Rest Web Service. I am passing the required requestbody but on printing the requestbody out it is not the same as my input.
For Example: What I entered was TransactionId then it would be changed to transactionId, AB_NAME would be changed to ab_NAME.
So all these fields get assigned null values.
The ResponseEntity being formed also does the same thing. I don't know why this is happening.
The dtos I have made are in line with the input I want to send so I don't know how they are changing on their own.
EDIT: So basically the web service dto fields are not using the Java naming convention but JSON automatically assumes them to be, had to use #JsonProperty to make sure the fields remain the same. Thanks for all of your help.

See your request body properties names and your model properties name should be the same as case. Writing here one example
DTO
publi class SomeName{
private string transactionId;
private string ab_NAME;
}
Sending body format should be
{
"transactionId":"11111",
"ab_NAME":"ABCDE"
}
Thanks.

Related

How to annotate a request body that is oneOf external models?

I'm working on documenting an API made with RESTeasy + Jackson in Java using Swagger/OpenAPI (version 1.5.18 - I did add in v3 OAS 2.0.1 to try oneOf/anyOf). One of the endpoints takes in a String as a request body, which is then transformed into one of several classes. The documentation needs to display each of these models so that users can see them. The models are defined in another project. Is there a way to do this through annotations? The closest thing I've found is adding #RequestBody(content=#Content(schema=#Schema(oneOf= {class1.class, class2.class}))) but haven't been able to get it to add the model using that. I also tried adding a dummy class with #ApiModel(subTypes={class1.class, class2.class}. I don't want to add additional endpoints for each object type due to code maintainability.
My question is: is it possible to add the models through annotations while leaving the input type as String?
Here is the relevant code:
#POST
#Path("/{filetype}/new")
#Consumes("application/json")
public Response writeFile(
#ApiParam(required=true, allowableValues = "class1, class2") #PathParam("filetype") String filetype,
#RequestBody(content=#Content(schema=#Schema(oneOf= {class1.class, class2.class}))) String inputFile
) {
return validateFileAndSaveToServer(filetype, inputFile);
}

Swagger UI with Java Rest Service

I am new to using Swagger documentation. I am using Swagger's annotations on Java rest service class. Could you please provide some help on the below problem -
My rest method is as below:
public String testMethod3(#ApiParam(value = "Mailing address of the user", required = true) #FormParam("address") final String address) {}
As you see, I am passing a JSON String parameter - address to my rest method. On the Javascript side, I have the below code to set up the data -
var addressMap = {};
addressMap.city = 'SS';
addressMap.zipCode = '98877';
addressMap.state = 'CA';
I am now sending this to the rest method by calling JSON.stringify(addressMap).
In Swagger-UI, I am only getting one parameter option to enter. How can I let the user to know that this is a complex object and they need to pass city, zipcode and state values.
If you're passing data in a #FormParam, you'll need to add a value for each of the fields. For example, city, zipCode, and state.
But I believe what you really want to do is post the JSON as a HTTP POST method, which case you would remove the #FormParam and consume the values into a java object that has the fields in the payload.

Equivalent of #JsonIgnore for a request in Spring MVC

I have a collection which has a DBRef inside it (and this secondary collection has a not null field). When I am using #ResponseBody, I am getting a 415 HTTP response. If I remove this secondary collection then everything works properly.
Is there way I can say certain fields are for input and certain field are for output in Spring MVC?
I see #JsonIgnore only for outgoing response. But did not find anything for input.
Is there way I can say certain fields are for input and certain field are for output in Spring MVC?
Solution to the problem is to ensure Setter is ignored and getter is not.
#Getter
#Setter(onMethod = #__( #JsonIgnore ))
private String FullName;
In the above example FullName is calculated by FirstName and LastName and should not be set using json input
{
"FirstName":"VinayaKumar"
"LastName":"Thimmappa"
}

Limiting Fields in JSON Response for REST API?

I am using Spring and Java and implementing REST Based services. I have a set of developers who develop for mobile,iPad and Web too. Consider I have a bean
Class User{
private String Name;
private Integer id;
private String photoURL;
private ArrayList<String> ProjectName;
private ArrayList<String> TechnologyList;
private ArrayList<String> InterestList;
//Getters and setters
}
While the Web Developers need the entire fields and mobile developers just require two fields from it whereas the iPad requires something in between mobile and web.
Since I am using jackson as a parser, is there a way where while requesting to the controller I can specify which all data I require and avoid the others. For example consider I do a GET request like
GET>http://somedomain.com/users?filter=name,id,photoUrl
Which returns me a JSON structure something like
{
"name":"My Name",
"id":32434,
"photoUrl":"/sss/photo.jpg"
}
Sameway if someone asks for some more fields, they could be filtered. Please let me know how this can be done so that my API remains generic and useable for all.
You can achieve what you want but some extra work is necessary. I can offer you two solutions.
1. Return a Map
Simply put every property that is requested into the map.
2. Use Jacksons Object Mapper directly
Jackson lets you set filters that specify which properties are serialized or ignored.
FilterProvider filter = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept(requestedProperties));
String json = objectMapper.writer(filter).writeValueAsString(value);
You can then return the JSON string directly instead of an object.
For both solutions you would ideally write a class that does the job. But if you do that you could as well write your own message converter. You could extend the MappingJackson2HttpMessageConverter, for instance, and overwrite the writeInternal method to suit your needs. That has the big advantage that you don't need to change your controllers.
The straightforward solution is to implement custom Jackson JSON serializer that will get field names that should be serialized from thread local storage and then serialize only fields which names are presented in that context. For other hand, in controller you can grab all allowed fields names from url and store them into thread local context. Hope this helps.

Converting #RequestBody to an object

Guys, Well I have done enough research still I can't find the solution to this.
In a nutshell, I'm simply passing url encoded form data to the Controller method and trying to convert it as a domain object which has Date and integers.
#RequestMapping(value = "/savePassport", method = RequestMethod.POST)
public #ResponseBody
AjaxResponse savePassport(#RequestBody StaffPassport passport, HttpServletResponse response) {
// Some operations.
}
The Staff Passport looks like this:
import java.sql.Date;
public class StaffPassport {
private int staffId;
private String passportNumber;
private String placeOfIssue;
private Date issueDate;
private Date expiryDate;
private String spouseName;
private String oldPassportRef;
private String visaInfo;
private String description;
//gets/sets
}
When I invoke the /savePassport, I get unsupported media exception. I guess it's related to casting.
I can't this working right. Of course I can catch individual form data using #RequestParam and manually do the casting but that's not the point of a framework isn't it?
Where am I going wrong? And you are right. I'm a beginner in Spring, but I love it.
Looks like you're using the wrong annotation. #RequestBody is for taking a request that has arbitrary content in its body,such as JSON, some application defined XML, comma separated variables.. whatever. And using a marshaller that you configure in the dispatcher servlet to turn it into objects.
If all you want to do is ask Spring to bind a plain old form post onto the backing object for you, the correct annotation to put on the method parameter is #ModelAttribute.
If you are posting a JSON Object with jQuery and you want Spring to be able to process it with #RequestBody, use JSON.stringify(....) in your data. Here an example:
var data = { "id": 3, "name": "test" }
$.post("processJsonData.html",JSON.stringify(data), function(data){
...
}
);
If you don't use the JSON.stringify() then you will submit the data as form data and Spring will tell you that you have an unsupported media type.
First of all be sure that you have
<mvc:annotation-driven />
in your Spring configuration file. This is mandatory for working with JSOn in SPring MVC.
Second, I recommend you to test wether request to the server has application/json content type. I belive Fiddler2 will help you to do so.
Third, but I'm not sure about it, Try to change Date items in your POJO from SQL type to regular java type.
UPDATE:
just looked at the Form and it seems like your "Accept" HTTP Header should be also application/json. Please test this issue with Fiddler2 as well.
I assume that you are posting JSON and want Spring to convert to StaffPassport. If you are getting an Unsupported media exception, it is because Spring could not figure out an appropriate way to perform the conversion.
For Spring to convert JSON, it needs Jackson -- make sure you have the Jackson jars in your project. If this is a Maven based project you can add the jackson-mapper-asl artifact ID to your pom.xml. This should give you the jackson-mapper and jackson-core jars.
Edit: I should mention that this applies to Spring 3 (I recently ran into this problem). I'm not sure what else is required for previous versions of Spring.
Check into HttpMessageConverter interface and its implementations. You could write your own implementation of it to convert it to the domain model you want. By the time the control gets to your method, you can access it as if your domain model object is passed.
Ok, I think I should refine my answer. I do not have direct experience of using it in a spring-mvc project but spring-integration. I am pretty sure the applicable media type (application/x-url-form-encoded) is already handled and converted to MultiMap by Spring framework; so, retrieve the values from that just like any other map with the key value being your form variable and populate your business model.
HTH.

Categories

Resources