I have a REST Webservice, I get my data from a JSON request:
#POST
#Path("load")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#RequestMapping(value="load", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON, consumes = MediaType.APPLICATION_JSON)
public #ResponseBody
Respuesta loadData(#RequestBody Persons person) {
//code
em.persist(person);
}
This is my Person class:
#Entity
#Table(name = "myparenttable", schema = "myschema", catalog = "mydb")
public class Parent {
private Integer id_parent;
private String name;
private String last_name;
private String username;
//getters and setters
public Parent(){}
}
I want to generate the username member with parts of the name and last_name members; for simplicity, lets say I need the username be = name + last_name; the username member is not specified in the json request, is there a way to load a member with values of other members in the object initialization? in this case, automatic initialization with #RequestMapping and #RequestBody
Related
My REST controller :
#RestController
#RequestMapping("/api/people")
public class PersonController {
#Autowired
private PersonRepository people;
#Transactional
#RequestMapping(path = "/{personId}", method = RequestMethod.PUT)
public ResponseEntity<?> update(
#PathVariable String personId,
#RequestBody PersonDTO dto) {
// get the entity by ID
Person p = people.findOne(personId); // we assume it exists
// update ONLY entity attributes that have been defined
if(/* dto.getFirstName is defined */)
p.setFirstName = dto.getFirstName;
if(/* dto.getLastName is defined */)
p.setLastName = dto.getLastName;
System.out.println(dto);
return ResponseEntity.ok(p);
}
}
My People DTO :
private class PersonDTO {
private String firstName;
private String lastName;
private List<String> designations;
private String location;
/* getters and setters ... */
}
I'm not passing the value designations in my REST request made through postman here and i see the values in the DTO while debuging in local or when printing, it says the designations is "Null" but i want it to be seen as blank arraylist. How can i do it?
There is nothing stopping you from defining the your PersonDto like so:
private List<String> designations = new ArrayList<>();
Meaning that even if the client sends null you'll be deserializing into an empty list.
First initialize your designations array in PersonDTO like so:
private List<String> designations = new ArrayList<String>();
Then make the following changes to your setter method for designations
public void setDesignations(List<String> designations) {
if (designations != null)
this.designations = designations;
}
In my request body DTO, I want specific fields to be required for one of the API but not for another.
My request body:
#Data
class MyClass {
#NotNull
private String fullName;
#NotNull
private String firstName;
#NotNull
private String lastName;
}
I want fullName to be required for /api/v1 but not for /api/v2. I am using #Valid on request body from javax.validation.
You have to use Spring's #Validated, which is a variant of JSR-303's #Valid. This is used at the method-level:
Controller:
#RequestMapping(value = "apiV1Method")
public String apiV1Method(#Validated(Account. ValidationAPI1.class) MyClassDTO myClassDTO) {...}
#RequestMapping(value = "apiV2Method")
public String apiV2Method(#Validated(Account. ValidationAPI2.class) MyClassDTO myClassDTO) {...}
Object:
class MyClassDTO {
public interface ValidationAPI1 {}
public interface ValidationAPI2 {}
#NotNull(groups = {ValidationAPI1.class})
private String fullName;
#NotNull(groups = {ValidationAPI1.class, ValidationAPI2.class})
private String firstName;
#NotNull(groups = {ValidationAPI1.class, ValidationAPI2.class})
private String lastName;
...
}
I have created an API using jersey and spring boot. Now when I hit POST request using Postman with following in request body:
{
"name":"something", "email":"something","location":"something","dateOfBirth":"something"
}
It works. Function to save this data is:
#POST
#Path("/addEmployee")
#Produces(MediaType.TEXT_PLAIN)
public String addEmployee(#RequestBody Employee employee) {
service.save(employee);
return "Saved Successfully";
}
Employee model is:
#Entity
#Table(name = "employee")
#XmlRootElement(name = "employee")
#EntityListeners(AuditingEntityListener.class)
public class Employee {
public Employee() {
}
#Id
#Column(nullable = false, name = "id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false, name = "name")
private String name;
#Column(nullable = false, name = "email")
private String email;
#Column(nullable = false, name = "location")
private String location;
#Column(nullable = false, name = "DOB")
private String dateOfBirth;
// getters and setters
This api is called by follwing function at client side:
#RequestMapping(value = "/addEmployee", method = RequestMethod.GET)
public ModelAndView addEmployee(ModelAndView model) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/api/addEmployee";
EmployeeInfo employee = new EmployeeInfo();
employee.setName("Ashish");
employee.setEmail("anyhing");
employee.setDateOfBirth("mybirthday");
employee.setLocation("home");
ResponseEntity<String> response = restTemplate.postForEntity(url, employee, String.class);
model.setViewName("homePage");
return model;
}
Employee info class is:
public class EmployeeInfo {
private String name;
private String email;
private String location;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
Error I'm getting is :
2018-09-16 15:57:13.706 ERROR 14892 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 null] with root cause
org.springframework.web.client.HttpClientErrorException: 404 null
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:86) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE]
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:708) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:661) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:621) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE]
at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:415) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE]
at com.example.controller.Home.addEmployee(Home.java:82) ~[classes/:na]
and a long list like this.
Form which calls this is:
<form name="myform" method="post" action="addEmployee" >
<input type="submit" value="Save">
</form>
EDIT: On changing client side's method = RequestMethod.GET to RequestMethod.POST, nothing happens, still getting same erro
What I'm doing wrong?
After reviewing your code problem is at client side app where your back end is running on 8090 port while in api you calling is having 8080 for addEmployee.
Change this String url = "http://localhost:8080/api/addEmployee"; to String url = "http://localhost:8090/api/addEmployee"; and you should be good.
#RequestMapping(value = "/addEmployee", method = RequestMethod.GET)
public String addEmployee(ModelAndView model) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8090/api/addEmployee";
EmployeeInfo employee = new EmployeeInfo();
employee.setName("Ashish");
employee.setEmail("anyhing");
employee.setDateOfBirth("mybirthday");
employee.setLocation("home");
System.out.println("WE HAVE REACHED HERE");
String response = restTemplate.postForObject(url, employee, String.class);
System.out.println(response);
return "redirect:/home";
}
The 404 means that the requested source does not exist maby because one of these reasons:
There is no controller method to handle the POST request so try to change the which#RequestMapping(value = "/addEmployee", method = RequestMethod.GET) to #RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
try to move this method and make it a service in a restful controller using this annotation #RestController
I see that you are accessing this /api/addEmployee which I think not configured right?
We should be using RequestMethod.POST instead of RequestMethod.GET
#RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public ModelAndView addEmployee(ModelAndView model) {
RestTemplate restTemplate = new RestTemplate();
String url = "http://localhost:8080/api/addEmployee";
EmployeeInfo employee = new EmployeeInfo();
employee.setName("Ashish");
employee.setEmail("anyhing");
employee.setDateOfBirth("mybirthday");
employee.setLocation("home");
ResponseEntity<String> response = restTemplate.postForEntity(url, employee, String.class);
model.setViewName("homePage");
return model;
}
I am trying to add HATEOAS links with Resource<>, while also filtering with #JsonView. However, I don't know how to add the links to nested objects.
In the project on on Github, I've expanded on this project (adding in the open pull request to make it work without nested resources), adding the "Character" entity which has a nested User.
When accessing the ~/characters/resource-filtered route, it is expected that the nested User "player" appear with the firstNm and bioDetails fields, and with Spring generated links to itself, but without the userId and lastNm fields.
I have the filtering working correctly, but I cannot find an example of nested resources which fits with the ResourceAssembler paradigm. It appears to be necessary to use a ResourceAssembler to make #JsonView work.
Any help reconciling these two concepts would be appreciated. If you can crack it entirely, consider sending me a pull request.
User.java
//package and imports
...
public class User implements Serializable {
#JsonView(UserView.Detail.class)
private Long userId;
#JsonView({ UserView.Summary.class, CharacterView.Summary.class })
private String bioDetails;
#JsonView({ UserView.Summary.class, CharacterView.Summary.class })
private String firstNm;
#JsonView({ UserView.Detail.class, CharacterView.Detail.class })
private String lastNm;
public User(Long userId, String firstNm, String lastNm) {
this.userId = userId;
this.firstNm = firstNm;
this.lastNm = lastNm;
}
public User(Long userId) {
this.userId = userId;
}
...
// getters and setters
...
}
CharacterModel.java
//package and imports
...
#Entity
public class CharacterModel implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#JsonView(CharacterView.Summary.class)
private Long characterId;
#JsonView(CharacterView.Detail.class)
private String biography;
#JsonView(CharacterView.Summary.class)
private String name;
#JsonView(CharacterView.Summary.class)
private User player;
public CharacterModel(Long characterId, String name, String biography, User player) {
this.characterId = characterId;
this.name = name;
this.biography = biography;
this.player = player;
}
public CharacterModel(Long characterId) {
this.characterId = characterId;
}
...
// getters and setters
...
}
CharacterController.java
//package and imports
...
#RestController
#RequestMapping("/characters")
public class CharacterController {
#Autowired
private CharacterResourceAssembler characterResourceAssembler;
...
#JsonView(CharacterView.Summary.class)
#RequestMapping(value = "/resource-filtered", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.OK)
public Resource<CharacterModel> getFilteredCharacterWithResource() {
CharacterModel model = new CharacterModel(1L, "TEST NAME", "TEST BIOGRAPHY", new User(1L, "Fred", "Flintstone"));
return characterResourceAssembler.toResource(model);
}
...
}
CharacterResourceAssembler.java
//package and imports
...
#Component
public class CharacterResourceAssembler implements ResourceAssembler<CharacterModel, Resource<CharacterModel>>{
#Override
public Resource<CharacterModel> toResource(CharacterModel user) {
Resource<CharacterModel> resource = new Resource<CharacterModel>(user);
resource.add(linkTo(CharacterController.class).withSelfRel());
return resource;
}
}
i have a problem with rest and method post on my controler i have this 2 class the first is user in my class user i have my class with the getters and setter and a default contructor because for the finally I would like use Hibernate .:
#Entity
#Table(name="Utilisateur") // mapping with hibernate (but not using in this situation)
public class User {
#Id
private long id;
#Column(name="nom")
private String nom;
#Column(name="prenom")
private String prenom;
#Column(name="admin")
private boolean admin;
#Column(name="actif")
private boolean actif;
#Column(name="logins")
private String logins;
#Column(name="email")
private String email;
#Column(name="naissance")
private String naissance;
#Column(name="pwd")
private String pwd;
#Column(name="compte")
private String compte;
public User(){
}
/*
with getter and setter.
*/
}
and my class controler (User controller) : is using for make the api principally post api .
#RestController
public class UserController {
#RequestMapping(
value="/api/greetings/post",
method = RequestMethod.POST,
consumes = MediaType.APPLICATION_JSON_VALUE,
produces=MediaType.APPLICATION_JSON_VALUE
)
#ResponseBody
public ResponseEntity<User> getByEmail(#RequestBody User user){
if(user==null){
return new ResponseEntity<User>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
and i get this erreur I am using postman for make the query and in parameter of my query I send this Json query :
{"id":"3","nom":"Gille","prenom":"Laurent","admin":"1","actif":"0","logins":"gilaur","email":""toto#hotmail.com,"naissance":"1990/09/09","pwd":"gal","compte":"autre"}
And i get this error :
{"timestamp":1457906727481,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message":"Content type 'text/plain;charset=UTF-8' not supported","path":"/api/greetings/post/"}
Thank you
you are change headers content-type application/json in Postman because you try set text/plain