I am facing this problem try to make post request with retrofit.
#Body parameters cannot be used with form or multipart encoding.
My body classes looks like below,
public class AddUser implements Serializable {
public String memberNo;
public List<AddUserLimit> limits;
}
public class AddUserLimit implements Serializable {
public String type;
public Value value;
}
public class Value implements Serializable {
public String unit;
public String unit_value;
}
And my interface method looks like below,
#FormUrlEncoded
#POST("api")
Call<ResponseBody> addMember(#QueryMap HashMap<String, Object> paramaters, #Body AddUser addUser);
I am waiting your helps.
You cannot use the #Body annotation with an #FormUrlEncoded annotation. You must use an #Part annotation, this annotation will compose the request body for you.
Related
I am developing an android application which sends the user entered data (Through edit textboxes) and it calls a POST API Method to send this data in the body of that API
Consider API URL is "htpps://xxxxx.com/forms/xxxxxx/reponse"
content-type "Json(Application/json)"
content looks like:
{"answers":
"[{\"questionId\":\"r8554145065f6486d8a362bec92030a06\",\"answer1\":\"xxxxx\"},
{\"questionId\":\"rf516c5bf916e4d6d960a1f8abc82f33b\",\"answer1\":\"xxxx\"}]"}
My problem is here how can I pass this type of body to retrofit and instead of "XXXXX" in content there will be a string which takes input from the user?
You probably already are using a interface to make the api calls and thats where you add the String body to the request.
public interface YourService{
#POST("forms/xxxxxx/reponse")
Call<Object> makeCall(#Body String body);
}
If you haven't been using an interface with retrofit than you can create an instance of the above interface by using your existing RetrofitClient:
YourService service = retrofitClient.create(YourService.class);
And now you can access the api by calling makeCall on the instance of the service:
service.makeCall(yourCustomString).enqueue(new Callback<Object>() {
#Override
public void onResponse(Response<MovieResponse> response) {...}
#Override
public void onFailure(Throwable t) {...}
});
You can build "yourCustomString" with String builder or so, even though I wouldnt recommend that, instead I would use an ConverterFactory and map your JSON-Data to Java POJOs. For example Moshi (com.squareup.retrofit2:converter-moshi).
If you do that you can use a Java POJO as the #Body annotated attribute and you simply ony set the two attributes "questionId" and "answer1" on the POJO instead of building a String.
If you would do that, you would end up with two classes:
public class Answer {
#Json(name = "questionId")
public String questionId;
#Json(name = "answer1")
public String answer1;
}
and
public class Body {
#Json(name = "answers")
private List<Answer> answers = new LinkedList<>();
}
Now with that you would just create an Body object and then add as many answers as you want to the answers attribute and then use the Body object as the parameter on the retrofit interface.
Note: If you do that, you have to add the MoshiConverterFactory to the RetrofitClient while building it.
I assume you are already familiar with how to implement Repositories and Interfaces for making API calls.
For the case you first need a DTO for answer.
public class AnswerDTO
{
private String questionId;
private String answer1;
public AnswerDTO(String questionId, String answer1)
{
this.questionId = questionId;
this.answer1 = answer1;
}
}
Now you can create an Interface for API call.
public interface QuestionsService
{
#FormUrlEncoded
#POST("requestUrlHere")
Call<Response> yourApiCall(#Field("answers[]") List<AnswerDTO> answers);
}
Hope this helps !.
I have created a Spring Boot with Spring REST application.
This is my controller code.
#RestController
public class SampleController {
#RequestMapping(value = "/sample/get", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public Response getResponse(SampleDTO dto) {
Response response = new Response();
response.setResponseMsg("Hello "+dto.getFirstName());
return response;
}
}
This is my SampleDTO
public class SampleDTO {
#JsonProperty("firstname")
private String firstName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
and this is my Response object
public class Response {
private String responseMsg;
public String getResponseMsg() {
return responseMsg;
}
public void setResponseMsg(String responseMsg) {
this.responseMsg = responseMsg;
}
}
When I try to access service this way
http://localhost:8080/sample/get?firstName=mvg
I am getting this expected output
{"responseMsg":"Hello mvg"}
When I try to access service this way
http://localhost:8080/sample/get?firstname=mvg
I am getting this output
{"responseMsg":"Hello null"}
My question is how do I map 'firstname' in request parameter with 'firstName' of DTO?
Thanks in advance
When you are setting #JsonProperty("firstname") make sure you are imported the this statement "import com.fasterxml.jackson.annotation.JsonProperty ;". One thing more if you are sending more properties and your bean class does not have that you can set the #JsonIgnoreProperties(ignoreUnknown=true) on the top of the bean name.
You are also missing the #RequestBody annotation. You should take this as (#RequestBody SampleDTO dto)in getResponse method.
Simply create a Pojo Java Bean with fields with names that match your request parameters.
Then use this class as an argument for your request handler method (without any additional annotations)
see this
First you need to choose which approach do you need (or want to use) param or model. When you use something like this http://localhost:8080/sample/get?firstName=mvg , you are passing data as request parameters. So you need to use the #RequestParam annotation.
Sample using #RequestParam annotation (use is explained in the docs)
#RequestMapping(method = RequestMethod.GET)
public Response foo(#RequestParam("firstName") String firstName) {
Response response = new Response();
response.setResponseMsg("Hello "+ firstName );
return response;
}
I have a rest webservice. For some reason I don't want to return class which needed to be converted to interface. I want to return interface and in the JSON I want to see only the methods(which starts get) values. Not the all attributes from the implemented class.
Say for an example:
#Path("getValues/")
#GET
#Produces( MediaType.APPLICATION_JSON)
public DetailInterface getClientDetail() {
return new DetailImpl();
}
and consider the interface:
public interface DetailInterface {
public String getName();
public String getAge();
}
and consider the implementation
public class DetailImpl implements DetailInterface {
public String getName()
return "my name";
}
public String getAge(){
return "my age";
}
public String iDontWantThisinJSON() {
return "I don't want this in JSON output";
}
}
when I request the rest service I see the iDontWantThisinJSON attribute also comes in the JSON response. I don't want to include it in the response.
How can I fix this?
Have you tried #JsonIgnore annotation? Marking the field as transient may be also helpful - however I'm not sure if it's ok.
This is a more of a java concept than Rest or Json. You will have to modify the code as follows and it should work as you want it to work.
#Path("getValues/")
#GET
#Produces( MediaType.APPLICATION_JSON)
public DetailInterface getClientDetail() {
DetailInterface di = new DetailImpl()
return di;
}
Is it possible to retrieve http headers inside JAXRS resource method without explicitly specifying these headers as method parameters?
For example I have a following interface:
#Path("/posts")
public interface PostsResource {
#GET
public List<Post> getAllPosts();
}
and the following class that implements this interface:
public class PostsResourceImpl implements PostsResource {
#Autowired
private PostsService postsService;
public List<Post> getAllPosts() {
return postsService.getAllPosts();
}
}
I don't want to change my method signature to:
public List<Post> getAllPosts(#HeaderParam("X-MyCustomHeader") String myCustomHeader);
This header will be added by interceptor on the client side so the client code doesn't know what to put here and this should not be explicit method parameter.
You can inject an object of type HttpHeaders within your resource as class variable to have access to request headers, as described below:
#Path("/test")
public class TestService {
#Context
private HttpHeaders headers;
#GET
#Path("/{pathParameter}")
public Response testMethod() {
(...)
List<String> customHeaderValues = headers.getRequestHeader("X-MyCustomHeader");
System.out.println(">> X-MyCustomHeader = " + customHeaderValues);
(...)
String response = (...)
return Response.status(200).entity(response).build();
}
}
Hope it answers your question.
Thierry
I have following jersey method declaration:
#POST
#Path("/fooPath")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public Response isSellableOnline(#FormParam("productCodes") final List<String> productCodes,
#FormParam("storeName") final String storeName,
#Context HttpServletRequest request) {
In rest client I try to invoke following method like this:
When I debug method I see that received parameters are null:
How to rewrite method declaration?
It is because on the isSellableOnlie method you are expecting or trying to extract form parameters, but the incoming POST request is JSON.
Well if you want JSON you should make POJO Class to be able to serialize the JSON.
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Store {
private String storeName;
private List<String> productCodes;
public Store() {
}
public String getName() {
return name;
}
public List<String> getProductCodes() {
return productCodes;
}
}
And then in your method:
#POST
#Path("/fooPath")
#Produces({MediaType.APPLICATION_JSON})
#Consumes({MediaType.APPLICATION_JSON})
public Response isSellableOnline(Store store) {
store.getName();
...
}