Is there any way to call an API to know its required parameters?
for example, if there is a controller has a method takes a name and date as a parameters
[HttpPost]
public string testUrl(string name,string date)
{
return "success";
}
now what I am trying to do is to make a dynamic form take an API URL and generate all required inputs so I have to find some way to call the URL and return the required parameters.
The quick and dirty way would be to just hard code it:
[HttpPost]
public string testUrl(string name,string date)
{
return "success";
}
public APISchema TestUrlSchema(){
return new APISchema() {
Parameters = new List<Parameter>(){
new Parameter(){ Name = "name", Type = "String" },
new Parameter(){ Name = "date", Type = "String" }
}
};
}
public class APISchema {
public List<Parameter> Parameters {get;set;}
}
public class Parameter {
public String Name {get;set;}
public String Type {get;set;}
}
You could use Reflection to auto-generate this if you want to do it for a large number of actions.
As comments have mentioned, there are libraries Swagger which will do this for you.
I am trying to set up a rest endpoint with jersey. I am using an angular2 client.
the angular code looks like this:
post() {
let headers = new Headers({ 'Content-Type': 'application/json' });
this.http.post('http://localhost:8050/rest/addentity', JSON.stringify(this.getValues()), new RequestOptions({ headers: headers })).
subscribe(data => {
alert('ok');
}, error => {
console.log(JSON.stringify(error.json()));
});
}
The post is sent correctly and I can see in the payload that all the values are there.
However, for two values I always get null in the server. Here's the method:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Path("addentity")
public void saveEntity(User user) {
System.out.println("ADD CALLED");
System.out.println(user.getId()); // null
addUser(user);
}
I have no idea why. The media type is correct, I get a 204 response...
Does anybody have any ideas what I'm doing wrong?
EDIT
JSON
{"id":"1234",
"name":"john",
"age":15,
"height":"6.2"}
User
public class User implements Serializable {
private static final long serialVersionUID = -5320367665876425279L;
private Integer userId;
private String name;
private double height;
private int age;
public User() {
// TODO Auto-generated constructor stub
}
public User(final Integer userId, final String name,
final double height, final int age) {
this.userId = userId;
this.name = name;
this.height = height;
this.age = age;
}
public Integer getuserId() {
return userId;
}
public void setuserId(final Integer userId) {
this.userId = userId;
}
public String getname() {
return name;
}
public void setname(final String name) {
this.name = name;
}
public double getheight() {
return height;
}
public void setheight(final double height) {
this.height = height;
}
public int getage() {
return age;
}
public void setage(final int age) {
this.age = age;
}
}
All values except height are null or 0, so only the double value is read correctly.
Well your actual code shows many problems, from what we can state:
In your User class you have an attribute userId while in your JSON you don't have it, it's id instead.
And the getters and setters in the User class are incorrect they should have the attribute first letter in Uppercase, ie : getage() should be getAge() and setage should be setAge().
You have to fix these problems otherwise your POJO won't be correctly mapped with your JSON.
You can refer to Getters and Setters in Java convention for further reading about it.
In javascript I am making an ajax post request to one of my JAX-RS functions like this
var postPackingListRequest = $http({
method: "post",
url: "/rest/v1/submit",
data: $scope.items
});
And now in my JAX-RS method I am trying to get the varibale $scope.items that was passed. I know I can get path params in the path like this
public Response getPathParams(#QueryParam("id") int id) {
But how can I get the data, which is passed in the body?
Thanks
EDIT
#POST
#Path("submit")
#Consumes(MediaType.APPLICATION_JSON)
#ApiResponses({ #ApiResponse(code = 201, response = Response.class) })
#Produces("application/json")
public Response submitPackingList(TestUser testUser) {
}
public class TestUser {
public String id;
public String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
When I send a request to this with the TestUser there I am getting a HTTP 400 error. Here is how I am sending it
var postPackingListRequest = $http({
method: "post",
url: "/rest/v1/submit",
data: "{'user':'1', 'name':james}"
});
Lets say your method is supposed to handle GET request like below
#GET
public Response getPathParams(#QueryParam("id") int id)
Now in the above method every argument must be annotated with something. In your case it is QueryParam. It may be PathParam and several others as well.
Only one argument is allowed which is not annoatated in JAX-RS.
Let's say you have User object like below:
public class User{
String userName;
int userId;
//getters and setters
}
and you want to accept user details that are coming via body of request then your method signature would look like below:
#GET
public Response getPathParams(#QueryParam("id") int id, User user)
Depending upon what the above method consumes whether it be json or xml the request body will be converted to User object and will get bind to your argument.
In case you are using Json you will need explicit MessageBodyReader for it.
I have two small projects, backend spring-boot side is responsible for providing the data, and angularjs frontend part is just displaying that data. I am trying to post a json from angular side and spring-boot side consumes and sends a respond.
This is horse racing data in json; "jokey" means rider and contains rider information:
var list = {"horses": [{"horseId":45942,"horseName":"Decolte","raceId":8449,"kilo":61.0,"jokey":{"name":"AYETULLAH DEMİR","raceNumber":41,"first":1,"second":4,"third":0,"fourth":1},"ekuriId":0},
{"horseId":27520,"horseName":"Busıness Man","raceId":8449,"kilo":57.0,"jokey":{"name":"CİVAN ÖZŞAHİN","raceNumber":190,"first":7,"second":15,"third":18,"fourth":12},"ekuriId":0},
{"horseId":55856,"horseName":"Erselçuk","raceId":8449,"kilo":57.0,"jokey":{"name":"NAİL EREN","raceNumber":64,"first":2,"second":0,"third":4,"fourth":2},"ekuriId":0},
{"horseId":52940,"horseName":"Haşim Ağa","raceId":8449,"kilo":57.0,"jokey":{"name":"DOĞUKAN AYDOĞAN","raceNumber":380,"first":11,"second":18,"third":10,"fourth":24},"ekuriId":0},
{"horseId":53431,"horseName":"İhtiyar","raceId":8449,"kilo":57.0,"jokey":{"name":"CÜNEYİT GÖKÇE","raceNumber":598,"first":32,"second":52,"third":64,"fourth":65},"ekuriId":0},
{"horseId":51778,"horseName":"Urla Zamanı","raceId":8449,"kilo":57.0,"jokey":{"name":"ADEM ŞEN","raceNumber":280,"first":18,"second":25,"third":32,"fourth":32},"ekuriId":0},
{"horseId":51816,"horseName":"Wın Every Day","raceId":8449,"kilo":57.0,"jokey":{"name":"EMRE NALBANT","raceNumber":405,"first":19,"second":26,"third":36,"fourth":33},"ekuriId":0},
{"horseId":58650,"horseName":"Lıon Amed","raceId":8449,"kilo":52.0,"jokey":{"name":"CANER KARADEMİR","raceNumber":134,"first":7,"second":7,"third":8,"fourth":7},"ekuriId":0},
{"horseId":51239,"horseName":"Catch The Wınd","raceId":8449,"kilo":57.0,"jokey":{"name":"MÜSLÜM CANPOLAT","raceNumber":238,"first":5,"second":12,"third":12,"fourth":19},"ekuriId":0},
{"horseId":46263,"horseName":"Ian Tapp","raceId":8449,"kilo":58.0,"jokey":{"name":"ERDEM NUR TÜFEKÇİ","raceNumber":79,"first":3,"second":1,"third":4,"fourth":5},"ekuriId":0},
{"horseId":51647,"horseName":"Sılverado","raceId":8449,"kilo":57.0,"jokey":{"name":"ÜMİT DERYA ALTEKİN","raceNumber":1185,"first":48,"second":53,"third":64,"fourth":84},"ekuriId":0},
{"horseId":57231,"horseName":"Junıor Duru","raceId":8449,"kilo":58.0,"jokey":{"name":"BEDRİ TEPE","raceNumber":716,"first":45,"second":55,"third":50,"fourth":67},"ekuriId":0}
]};
It was basically an array but somebody on stackoverflow told the data inside ajax request should be an object so I added "horses:" to the front. The json is manually added inside the code.
This is http request:
$http({
url: 'http://localhost:8080/horseHistory',
method: 'POST',
contentType: "application/json",
data: list.horses,
headers: {
"Content-Type": "application/json"
}
}).success(function(data) {
console.log(data);
});
On the backend I just want to see a working http connection so it is mostly empty. This is spring-boot function:
#RequestMapping(value = "/horseHistory", method = RequestMethod.POST )
public ResponseEntity<Void> getHorseHistory(#RequestBody HorseRaceModel[] horseRaces) throws IOException {
System.out.println(horseRaces[0]);
return null;
}
HorseRaceModel:
package ganyan;
public class HorseRaceModel {
int horseId;
String horseName;
int raceId;
double kilo;
JokeyModel jokey;
int ekuriId;
public HorseRaceModel(int horseId, String horseName, int raceId, double kilo, JokeyModel jokey, int ekuriId) {
this.horseId = horseId;
this.horseName = horseName;
this.raceId = raceId;
this.kilo = kilo;
this.jokey = jokey;
this.ekuriId = ekuriId;
}
public int getHorseId() {
return horseId;
}
public void setHorseId(int horseId) {
this.horseId = horseId;
}
public void setHorseName(String horseName) {
this.horseName = horseName;
}
public String getHorseName() {
return horseName;
}
public int getRaceId() {
return raceId;
}
public void setRaceId(int raceId) {
this.raceId = raceId;
}
public double getKilo() {
return kilo;
}
public void setKilo(double kilo) {
this.kilo = kilo;
}
public JokeyModel getJokey() {
return jokey;
}
public void setJokey(JokeyModel jokey) {
this.jokey = jokey;
}
public int getEkuriId() {
return ekuriId;
}
public void setEkuriId(int ekuriId) {
this.ekuriId = ekuriId;
}
}
JokeyModel:
public class JokeyModel {
private String name;
private int raceNumber;
private int first;
private int second;
private int third;
private int fourth;
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getRaceNumber() {
return raceNumber;
}
public void setRaceNumber(int raceNumber) {
this.raceNumber = raceNumber;
}
public int getFirst() {
return first;
}
public void setFirst(int first) {
this.first = first;
}
public int getThird() {
return third;
}
public void setThird(int third) {
this.third = third;
}
public int getFourth() {
return fourth;
}
public void setFourth(int fourth) {
this.fourth = fourth;
}
}
The error from Chrome console:
Failed to load resource: the server responded with a status of 400 (Bad Request) http://localhost:8080/horseHistory
The error from Java console:
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.HashMap out of START_ARRAY token
I'm not familiar with Spring Boot and I don't know why you have been told to post a JSON object instead of a JSON array, but I see that you are not doing it coherently.
You wrapped your JSON array in a JSON object called list, but by specifying data: list.horses you are still only passing the embedded JSON array. Since you want to send the whole JSON object, you should specify data: list instead.
Furthermore, I think that you need to define the wrapper model on the server side, which may be some class like this:
public class ListModel {
private List<HorseRaceModel> horses;
public List<HorseRaceModel> getHorses() {
return horses;
}
public void setHorses(List<HorseRaceModel> horses) {
this.horses = horses;
}
}
Finally, the method consuming the post should be instructed to parse the request body into a ListModel. This means to modify the method to something like this:
#RequestMapping(value = "/horseHistory", method = RequestMethod.POST )
public ResponseEntity<Void> getHorseHistory(#RequestBody ListModel horseRaces) throws IOException {
System.out.println(horseRaces.getHorses().get(0).getName());
return null;
}
Side note: I also modified the code to print the name of the first horse instead of the object pointer that would be printed by System.out.println(horseRaces.getHorses().get(0));. You may want to print something else instead. You may also want to use better names for the wrapper object and model (instead of list and ListModel)
Note from comment: Your HorseRaceModel class does not have an empty constructor, you need to provide one for deserialization to work
I have an AngularJS app that has to post data to a 3rd party URL. To get around the CORS browser issue, I am posting the data to my .net controller which will then post it to the 3rd party URL. In my javascript file, I've built the query string I want to pass to the 3rd party URL. Here is my code that posts to my .net controller:
var parms = "name=john&phone=1234567890&sex=male";
return $http({
url: '/UserForm/PostData/',
method: "POST",
data: parms
});
My c# controller:
[HttpPost]
public string PostData(String parms)
{
return "";
}
the parms variable in PostData is null. What do I need to do to pass my querystring string to my controller?
Can you try this? First - why don't you just define all parameters inside the controller post request definition? Second - I guess you have an error in your URL, you don't need the slash after "/UserForm/PostData" (If you don't use some custom routing in your MVC of course)
$http.post("/UserForm/PostData", { name: "john", phone: "1234567890", sex: "male" }).then(blahblahal....;
+
[HttpPost]
public string PostData(String name, String phone, String sex)
{
return "";
}
If this is for a WebApi controller, instead of trying to read parms as a parameter passed to the action, use ReadAsString to read the posted data. In your example the result should be the same value in your parms variable.
[HttpPost]
public IHttpActionResult PostData()
{
var parms = Request.Content.ReadAsStringAsync().Result;
// Submit parms to third-party api.
return Ok();
}
This task is more appropriate for WebApi, but if you need to use an MVC controller, you can read what was posted by reading Request.InputStream:
public ActionResult PostData()
{
string parms;
using (var sr = new System.IO.StreamReader(Request.InputStream))
{
parms = sr.ReadToEnd();
}
// Submit parms to third-party api.
return new EmptyResult();
}
You can try this.
[HttpPost]
public string PostData(System.Net.Http.Formatting.FormDataCollection form)
{
string name=form.get("name");
string phone=form.get("phone");
string sex=form.get("sex");
}
Or else you can try this solution too, you just need to add couple of lines.
public class PersonData
{
public string name { get; set; }
public string phone { get; set; }
public string sex { get; set; }
}
[HttpPost]
public string PostData([FromBody]PersonData form)
{
string name=form.name;
string phone=form.phone
string sex=form.sex;
}