I use the annotation #JsonView, but it doesn't work, here is my code and the return data, would you please help me to look where I am wrong.
My spring jar shows the edition of "spring-web-3.2.8.RELEASE.jar", and I just add this bean,I do not know whether it is useful or not, and I just use #JsonView directly in my code
<bean id = "jacksonMessageConverter" class = "org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
</bean>
Here is the View class
public class View {
public interface Summary{};
}
This is the User entity class(with "set" "get" method omitted), it has several attribute which corresponding to the database, there is a "status" attribute needn't return in the json data.
public Class User{
#JsonView(View.Summary.class)
private Integer uid;
#JsonView(View.Summary.class)
private String first;
#JsonView(View.Summary.class)
private String last;
#JsonView(View.Summary.class)
private String email;
#JsonView(View.Summary.class)
private String password;
private Integer status;
}
I had the controller
#RequestMapping(value="/login", method=RequestMethod.POST)
#JsonView(View.Summary.class)
#ResponseBody
public Message login(String email, String password){
User user = userMapper.findUser(email,password);
Message message = new Message();
message.setUser(user);
return message;
}
}
and here is my Message class with the "set" "get" methods
public class Message {
private int box_hits;
private List<Box> boxes;
#JsonView(View.Summary.class)
private User user;
}
when I use the postman to test the url,it shows json data, obviously, it should not return with the attribute without #JsonView, what' wrong with my code?
{
"box_hits": 0,
"boxes": null,
"user": {
"uid": 1,
"first": "yuan",
"last": "kang",
"email": "123#qq.com",
"password": "123",
"status": 0
}
}
As described in the announcement blog post, this feature is only available as of Spring Framework 4.2. It won't work with Spring 3.2.8.
Related
I have a basic spring-boot application (REST API), which should save contacts data in the database. When I send a POST request with a JSON content, the REST client testing tool doesn't show any errors, but the email attribute of the request is saved as a NULL value in the database.
Here is my function in the controller:
#Autowired
private ContactRepository contactRepository ;
#RequestMapping(value = "/contacts",method = RequestMethod.POST)
public Contact save(#RequestBody Contact contact){
return contactRepository.save(contact);
}
here is the entity :
#Entity
public class Contact implements Serializable
{
#Id
#GeneratedValue
private long id;
private String firstName;
private String secondName;
#Temporal(TemporalType.DATE)
private Date birthDate;
private String email;
private String tel;
private String photo;
here is the request body :
{
"firstName":"test",
"secondName":"test",
"email":"aa#gmial.com",
"tel":"0333433398",
"photo":null
}
Here is the response that I get :
{
"id": 16,
"firstName": "test",
"secondName": "test",
"birthDate": null,
"tel": "0333433398",
"photo": null
}
Thank you!
I sent correct JSON Format body from Postman.
{
"loginId": "xxxxxx",
"password": "xxxxxx",
"clientIP": "xxxxx",
"companyId": "xxxxx"
}
This is my controller
#RestController
#RequestMapping(path = "/umm")
public class LoginServer {
private transient Logger log = LogManager.getLogger(this.getClass());
#RequestMapping(value = "/basicLogin",method = RequestMethod.POST)
public #ResponseBody LoginRequest login(#RequestBody(required = true) LoginRequest loginRequest){
return null;
}
}
And this is my domain
public class LoginRequest implements Serializable {
private static final long serialVersionUID = -884241731093688658L;
private String loginId;
private String password;
private String clientIP;
private String companyId;
public LoginRequest(String loginId, String password, String clientIP, String companyId) {
this.loginId = loginId;
this.password = password;
this.clientIP = clientIP;
this.companyId = companyId;
}
//getter and setter omitted
}
I don't know why it's return me 400 error code (Bad Request) because I sent a correct JSON body
This is Response message.
{
"timestamp": 1549458416991,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.http.converter.HttpMessageNotReadableException",
"message": "JSON parse error: Can not construct instance of escf.api.domain.login.LoginRequest: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of escf.api.domain.login.LoginRequest: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)\n at [Source: java.io.PushbackInputStream#1c360a55; line: 2, column: 2]",
"path": "/umm/basicLogin"
}
I need it's return me code 200.
add super(); in domain class it's work.
Given that you are using Jackson for serialization/deserialization instead of Gson, the following solution should work for you.
public class LoginRequest implements Serializable {
private static final long serialVersionUID = -884241731093688658L;
private String loginId;
private String password;
private String clientIP;
private String companyId;
#JsonCreator
public LoginRequest(#JsonProperty("loginId") String loginId, #JsonProperty("password") String password, #JsonProperty("clientIP") String clientIP, #JsonProperty("companyId") String companyId) {
this.setLoginId(loginId);
this.setPassword(password);
this.setClientIP(clientIP);
this.setCompanyId(companyId);
}
// Define your getters and setters IMPORTANT
}
Resources: https://www.baeldung.com/jackson-annotations
Firstly,if you have any ideas or solution, thank you to present here.
I use #RequestBody on one of my controllers for a required parameter, I need some useful way of saying which parameter was missing if it's not there.
When there are some parameters missing, it will throw the NullPointerException, SO I create a new exception to instance of this null exception (please see the httpemun and the httphandler)
These are the primary codes which referring to this question.
my controller:
public ResponseEntity<?> createOrder(#RequestBody Cart cart) throws Exception {
// ......
}
my entity cart:
public class Cart{
private String channel
private String cartId;
private String status;
private String currency;
getters...
setters...
}
my Http emun class:
public enum HttpStatusEnum {
CRE_CART_INCOMPLETE_BODY(400,"E001","Incomplete request body","");
private HttpStatusEnum(int statusCode, String code,
String message, String detail) {
this.statusCode = statusCode;
this.code = code;
this.message = message;
this.detail = detail;
}
private final int statusCode;
private final String code;
private final String message;
private String detail;
public int getStatusCode() {
return statusCode;
}
public String getCode() {
return code;
}
public String getMessage() {
return message;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getDetail() {
if(detail.isEmpty()) {
return message;
}else {
return detail;
}
}
}
I also have one exception handle
#ControllerAdvice
public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
#ExceptionHandler(value = Exception.class)
#ResponseBody
public ResponseEntity<Object> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
if(e instanceof NullPointerException)
{if(req.getRequestURL().toString().contains(HttpSourceEnum.CART.toString()) && req.getMethod().equals(RequestMethod.POST.toString())){
errorBodyVo.setMessage(HttpStatusEnum.CRE_CART_INCOMPLETE_BODY.getMessage());
errorBodyVo.setDetails(HttpStatusEnum.CRE_CART_INCOMPLETE_BODY.getDetail());
errorBodyVo.setCode(HttpStatusEnum.CRE_CART_INCOMPLETE_BODY.getCode());
}else {
errorBodyVo.setMessage(HttpStatusEnum.COMMON_MISSING_FIELD.getMessage());
errorBodyVo.setDetails(HttpStatusEnum.COMMON_MISSING_FIELD.getDetail());
errorBodyVo.setCode(HttpStatusEnum.COMMON_MISSING_FIELD.getCode());
}
httpStatus = HttpStatus.BAD_REQUEST;
}
}
right now,
my API request is:
{
"channel": "XX",
"cartId": "109",
"status": "1",
}
I receive the API response just like below:
{
"error": {
"code": "E001",
"message": "Incomplete request body",
"details": ""
}
}
but it doesn't match my expect.
if the channel is missing in my request like below:
{
"cartId": "109",
"status": "1",
}
I expect to show "Required request body content is missing: Channel" in the details:
{
"error": {
"code": "E001",
"message": "Incomplete request body",
"details": "Required request body content is missing: Channel"
}
}
How could I do that? Thanks guys!
A better approach, if you can do it, would probably be to use JSR 303 Validation, which is probably included with your existing Spring dependencies, assuming you're using recent versions.
There's a good, if quite simple, tutorial here: https://www.mkyong.com/spring-mvc/spring-rest-api-validation/ and many more online with more details.
The official Spring docs on the subject are here: https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#validation-beanvalidation
You should only need to make changes to a few classes, and can potentially remove a lot of your exception handling, depending on how much control you want, or how much you're willing to go with Spring's defaults. The basic changes you'll need to make though are:
To tell Spring what validation is required, you add one or more annotations to the Cart class, for example, if you want to ensure that the channel is specified, you could do something like:
public class Cart{
#NotNull
private String channel
private String cartId;
private String status;
private String currency;
Then, to instruct Spring to validate the Cart object before passing it to your controller, you need to add an #Valid annotation to your controller method signature:
public ResponseEntity<?> createOrder(#Valid #RequestBody Cart cart) throws Exception {
Lastly, modify the createOrder signature again to accept an Errors object:
public ResponseEntity<?> createOrder(#Valid #RequestBody Cart cart, Errors errors) throws Exception {
In the createOrder method you can then query the Errors object and respond accordingly. This could mean sending a specific response from the controller or throwing an exception to be handled by your existing exception handling mechanism.
I'm coding an API using Jhipster. Server side is programmed with Spring-Boot. I want to get JSON Object that i send with PostMan
{
"user" : {
"name" : "name",
"surname": "surname"
}
}
I create a ressource and a class to get this JSON Object
#RequestMapping(value = "/",method = RequestMethod.POST,produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<AlertBalance> create(#RequestBody User user) throws URISyntaxException {
System.out.println("name "+ user.getName()+"/ surname : "+User.getSurname());
}
User class Code
#JsonIgnoreProperties(ignoreUnknown = true)
public class User implements Serializable {
private String name;
private String surname ;
#JsonCreator
public User(#JsonProperty("surname") String surname , #JsonProperty("name") String name){
this.surname = surname;
this.name = name;
}
public User(){
}
//setters and getters
}
The create() method is called when I do request from postman, but the value of name and surname is null. Do you know what I can do to get the real values ?
I just find the mistake, the JSON Object I sent was incompatible. I change it with
{
"name" : "name",
"surname": "surname"
}
and now it works.
I implemented Rest api with Spring Boot. In my controller class, I have code to handle GET request which will return JSON if record found.
// SeqController.java
#Autowired
private SeqService seqService;
#RequestMapping(
value = "/api/seqs/{analysis_id}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<SeqTb>> getSeqByAnalysisId(#PathVariable("analysis_id") String analysis_id) {
List<SeqTb> seqs = seqService.findByAnalysisId(analysis_id);
return new ResponseEntity(seqs, HttpStatus.OK);
}
I also create a bean class SeqServiceBean that extends the interface SeqService which in turn calls methods from the following JPA repository for query.
//SeqRepository.java
#Repository
public interface SeqRepository extends JpaRepository<SeqTb, Integer> {
#Override
public List<SeqTb> findAll();
public List<SeqTb> findByAnalysisId(String analysisId);
}
Problem is when I typed the url (http://localhost:8080/api/seqs/fdebfd6e-d046-4192-8b97-ac9f65dc2009) in my browser, it returned nothing but a pair of empty brackets. I just looked in the database and that record is indeed there. What did I do wrong?
A bit late to answer this quesiton, but in case anyone else is having this issue.
This problem may be caused by the class (that we want to be displayed as a json object) missing getter and/or setter methods.
In your case the "seqTab" class may be not have getters.
Without the getters our application can not extract the fileds to build the json object.
Example :
Sample user class
public class User {
private String firstname;
private String lasttname;
int age;
public User(){
}
public User(String fname, String lname, int age){
this.firstname = fname;
this.lasttname = lname;
this.age = age;
}
}
Sample rest controller
#RestController
public class SampleRS {
#RequestMapping(value = {"/sample/{input}"}, method = RequestMethod.GET , produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> startService(#PathVariable("input") String input){
User u = new User(input,"bikila",45);
return new ResponseEntity<User>(u,HttpStatus.OK);
}
}
// If we try to hit the endpoint /sample{input} .. e.g.
Request : localhost:8080/Sample/abebe
Response :
{}
But adding the getters for the User class will solve the problem.
Modified User class with getters
public class User {
private String firstname;
private String lasttname;
int age;
public User(){
}
public User(String fname, String lname, int age){
this.firstname = fname;
this.lasttname = lname;
this.age = age;
}
public String getFirstname() {
return firstname;
}
public String getLasttname() {
return lasttname;
}
public int getAge() {
return age;
}
}
Request : http://localhost:8080/sample/abebe
Response : {"firstname":"abebe","lasttname":"bikila","age":45}
Hope that helps !
In most of case, database driver jar is not deployed in server. Check deployment assembly of project in eclipse. Also see console message to check if it is showing driver jar not found.
If this is case simply deploy this jar in deployment assembly of eclipse.
One thing, if build path has this jdbc driverjar in eclipse, main method will connect to database. But if jar is not deployed jdbc connection will not happen over http request.