I implemented a rest web service by Jax-RS and CXF.
#Path("/StudentServices")
#Produces({"application/json"})
public class Student
{
#POST
#Path("/save")
public String persist(#QueryParam("StudentName") String name,
#QueryParam("StudentAge") String age)
{
System.out.println("*******************************");
System.out.println(" Incomming student with = " + name + " " + age);
System.out.println("*******************************");
return "Hello " + name;
}
}
Actually, I want to call the service with the url: localhost:9000/StudentServices/save
and with the body message as JSON: {"StudentName": "John", "StudentAge": "30"}
but when the request arrived to persist method, its inputs is null or empty. I examined with some others way like Jackson annotations, JAXB annotations but no one worked correctly.
Furthermore, I want to fix parameters' name when my service has input primitive types and String, because when I use a class for input, it works fine.
You cannot use #QueryParam to read the body of the request.
As specified in the #QueryParam docs, It binds the value(s) of a HTTP query parameter to a resource method parameter, resource class field, or resource class bean property. Values are URL decoded unless this is disabled using the Encoded annotation. so if you forward the request like below your exisiting code should work:
localhost:9000/StudentServices/save?StudentName=John& StudentAge=30
Now if you want to accept json request Then you will have to create seprate javaBean.
#XmlRootElement
public class StudentRequest {
private String studentName;
private int studentAge;
// getter and setter
}
And in your Controller. (i.e. Student.)
#Path("/StudentServices")
public class Student {
#POST
#Path("/save")
#Produces({"application/json"})
public String persist(StudentRequest studentRequest)
{
//your custom logic
}
}
Also specify your produces or consumes annotation on method level. It gives flexibility to return some other content type from other method.
You are defining the Parameter as QueryParam this means, that JAX-RS is expecting them as parameter added to your url, e.g. localhost:9000/StudentServices/save?StudentName=John&StudentAge=30
What you want is that the data is send in the body. So you can define a simple POJO:
public class Student {
private String StudentName;
private int StudentAge;
// getters and setters
}
And use it as parameter in the JAX-RS method:
#POST
#Path("/save")
public String persist(Student student) {
System.out.println("*******************************");
System.out.println(" Incomming student with = " + student.getStudentName() + " " + student.getStudentAge());
System.out.println("*******************************");
return "Hello " + student.getStudentName();
}
The JAXB provider is transforming your body data (JSON) into the corresponding POJO and you can access the data via the getters.
Related
Let's say I have:
#GET
public UserList fetch(#PathParam("user") String userId) {
// Do stuff here
}
Now, let's say I have my own type for userId, let's call it UserId. Is it possible to parse that String to UserId when it is passed into the fetch method, i.e.:
#GET
public UserList fetch(#PathParam("user") UserId userId) {
// Do stuff here
}
I realize I can parse the String once I am inside the method, but it would be more convenient that my method gets the type I want.
Well you've attempted to make a GET call with a request body is what I find not very helpful. Do read Paul's answer here -
you can send a body with GET, and no, it is never useful to do so
What would be good to practice is, to make a PUT or a POST call (PUT vs POST in REST) as follows -
#POST
#Path("/some-path/{some-query-param}")
public Response getDocuments(#ApiParam("user") UserId userId,
#PathParam("some-query-param") String queryParam) {
UserId userIdInstance = userId; // you can use the request body further
Note - The ApiParam annotation used is imported from the com.wordnik.swagger.annotations package. You can similarily use FormParam,QueryParam according to your source of input.
Dropwizard is using Jersey for HTTP<->Java POJO marshalling. You could use the various annotations from Jersey #*Param (#FormParam, #QueryParam, etc.) for some of the parameters.
If you need to use map/marshall to/from Java POJOs take a look at the test cases in Dropwizard:
#Path("/valid/")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class ValidatingResource {
#POST
#Path("foo")
#Valid
public ValidRepresentation blah(#NotNull #Valid ValidRepresentation representation, #QueryParam("somethingelse") String xer) {
return new ValidRepresentation();
}
This defines an API endpoint responding to HTTP POST method which expects ValidRepresentation object and "somethingelse" as HTTP method query parameter. The endpoint WILL respond ONLY when supplied with JSON parameters and will return only JSON objects (#Produces and #Consumes on the class level). The #NotNull requires that object to be mandatory for the call to succeed and #Valid instructs Dropwizard to call Hibernate validator to validate the object before calling the endpoint.
The ValidRepresentation class is here:
package io.dropwizard.jersey.validation;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
public class ValidRepresentation {
#NotEmpty
private String name;
#JsonProperty
public String getName() {
return name;
}
#JsonProperty
public void setName(String name) {
this.name = name;
}
}
The POJO is using Jackson annotations to define how JSON representation of this object should look like. #NotEmtpy is annotation from Hibernate validator.
Dropwizard, Jersey and Jackson take care of the details. So for the basic stuff this is all that you need.
I'm passing a JSON object from a PUT request to my server. The request itself works, however the fields in the JSON which have an underscore (snake_case) seem to bi ignored. The request outputs the received data to see what comes out, and the value with the underscore converts to camelCase, and doesn't get parsed. Here's the class:
Public User{
private int id;
private String name;
private int some_value;
}
The JSON object I pass to the PUT request:
{ "id":1, "name":John, "some_value":5 }
The PUT method only returns what MOXy caught in this case
#PUT
#Path("user")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public User addUser(User user){
return user;
}
And the output is:
{ "id":1, "name":John, "someValue":0 }
Notice how "some_value" changed to "someValue" and didn't get the actual value updated. Any idea on why this is happening?
MOXy follows Java Bean conventions by default, which suggest camel case. If you don't want to (or can't) use camel case, you can add an annotation to the field:
#XmlElement(name = "some_value")
private int some_value;
If you don't want to annotate all your fields, use an XMLNameTransformer.
Using RestEasy, can I use a #HeaderParam, #PathParam, or #QueryParam annotations on the properties of one of the incoming object parameters?
This is my method:
#Consumes(MediaType.APPLICATION_JSON)
#POST
#Path("/test/{testPathParam}")
#Produces(value = {MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN})
public Response test(
#HeaderParam("testHeaderParam") String testHeaderParam,
#QueryParam("testQueryParam") String testQueryParam,
#PathParam("testPathParam") String testPathParam,
TestInputBean testInputBean
) {
Logger.info(this, "testHeaderParam: ", testHeaderParam);
Logger.info(this, "testQueryParam: ", testQueryParam);
Logger.info(this, "testPathParam: ", testPathParam);
Logger.info(this, "testInputBean.getTestHeaderParam(): ", testInputBean.getTestHeaderParam());
Logger.info(this, "testInputBean.getTestQueryParam(): ", testInputBean.getTestQueryParam());
Logger.info(this, "testInputBean.getTestPathParam(): ", testInputBean.getTestPathParam());
Logger.info(this, "testInputBean.anotherParam(): ", testInputBean.anotherParam);
return null;
}
This is TestInputBean (deleted the getters and setters):
public class TestInputBean {
#HeaderParam("testHeaderParam")
String testHeaderParam;
#QueryParam("testQueryParam")
String testQueryParam;
#PathParam("testPathParam")
String testPathParam;
String anotherParam;
}
This is the request:
This is the output:
testHeaderParam: testHeaderParam-fromHeader
testQueryParam: testQueryParam-fromQuery
testPathParam: testPathParam-fromPath
testInputBean.getTestHeaderParam(): null
testInputBean.getTestQueryParam(): null
testInputBean.getTestPathParam(): null
testInputBean.anotherParam(): anotherParam-fromJson
But this is what I want:
testHeaderParam: testHeaderParam-fromHeader
testQueryParam: testQueryParam-fromQuery
testPathParam: testPathParam-fromPath
testInputBean.getTestHeaderParam(): testHeaderParam-fromHeader
testInputBean.getTestQueryParam(): testQueryParam-fromQuery
testInputBean.getTestPathParam(): testPathParam-fromPath
testInputBean.anotherParam(): anotherParam-fromJson
Is this possible?
You can put all the #XxxParam properties into a bean, using the #BeanParam annotation, but I don't think it is possible to also include the JSON entity bean into this bean. You will just need to put is as a separate parameter.
public class Bean {
#PathParam("id")
private String id;
#XxxParam("..")
private String param;
// getters and setters
}
#POST
public Response(#BeanParam Bean bean, JsonBody entity) {}
#BeanParam is standard JAX-RS (2.0) annotation, but RESTEasy has a specific #Form annotation that works exactly the same way as #BeanParam. See here for more info. If you are using RESTEasy 2.x, then you can only use #Form, as RESTEasy 2.x still used JAX-RS 1.x, which doesn't have #BeanParam.
I want to make a JAX-RS web service using jersey implementation.
I need a post method with 3 parameters.
#POST
#Path ("/addData")
#produce(MediaType.Application_Json)
#Consume(MediaType.Application_JSON)
public User addData(int id, String name, String pass){
User u = new User();
u.setId(id);
u.setName(name);
u.setPass(pass);
return u;
}
#POST
#Path ("/addData")
#produce(MediaType.Application_Json)
#Consume(MediaType.Application_JSON)
public User addSingleData(int id){
User u = new User();
u.setId(id);
return u;
}
There is a separate User class as follow:
public class User{
int id;
String name;
String pass;
// here are the getter setter and constructors
}
First, can I use jersey-media-moxy-2.3.jar file for conversion to JSON (i dont want to use maven). because this jar file is not converting content to json but if i use maven its working fine without parameters in post method.
second, how to get param in body of method if i am using only one param. i.e. second method
third, how to use multiple params in post method.
fourth, in further i need to upload and download an image. how to do that.
last, i am not able to get data in json format.
NOTE: I am making web service for android mobile. i am going to consume it via andorid.
for RESTful API, you should not be relay on the usual web application parameter passing style,
... URL..?param=value
you should form a url in a way that, it make sense to access the resource:
for example:
#POST
#Path("/{courseId}/subjects/{"subjectId"}/description")
public Message get(#PathParam("courseId") String courseId,
#PathParam("subjectId") String subjectId) {
// ....
}
this resource endpoint is giving a way to post a new description for a specific subject under a specific course. So this is how you could access multiple Path parameters in the same Post request.
On the other hand, if you are talking about how to get value of all fields on your 'User' class then you should consider annotating the class with #XmlRootElement
#XmlRootElement
public class User{
int id;
String name;
String pass;
//empty contractors is mandatory in addition to the public getter and
// setters
public User(){
}
// here are the getter setter and constructors
}
now if you send with a POST method something like below : [JSON format] :
{
"id":"123"
"name":"user name"
"pass":"pass"
}
jersey will take of creating instance of User class with the data in the body of the request. which is the reason why you will need mandatory empty constructor in your User class, jersey will first create the instance of the class using the empty constructor and calls setters of each field to set values.
with that in place, if you simple put User in parameter of your method you will have object passed to your method.
#POST
#Path ("/addData")
#produce(MediaType.Application_Json)
#Consume(MediaType.Application_JSON)
public User addData(User newUser){
//do something
return newUser;
}
I have a spring web service method where i want to get a string as a parameter. The string is sent in body of the request. My web service class is:
#Controller
#RequestMapping(value = "/users/{uid}/openchart")
public class OpenChartWebService {
#RequestMapping(method = RequestMethod.POST)
#ResponseBody
public String saveABC(#PathVariable("uid") Long uid,
#RequestBody String myString) {
System.out.println("sent string is: "+myString);
return "something";
}
}
My request in body is :
{
"name":"Ramesh"
}
But this is not working. This shows "Bad Request" HTTP error(400). How to send a string in a body and how to get a string sent in a body inside webservice method?
As #Leon suggests, you should add the media type to your request mapping, but also make sure you have Jackson on your classpath. You'll also want to change your #RequestBody argument type to something that has a "name" property, rather than just a String so that you don't have to convert it after.
public class Person {
private name;
public getName() {
return name;
}
}
If your data object looked like the above, then you could set your #RequestBody argument to Person type.
If all you want is a String, then perhaps just pass the value of "name" in your request body rather than an object with a name property.