added data to the custom Dto class - spring-boot

also I have a user dto class
class UserDto{
Long id;
String name;
String email;
String password
}
when user login is success, I wants to show response like this
{
"user":{
"id":"1",
"name":"imesh"
},
"token":{
"access_token":{
"token":"bhacvyusbi",
"expired_at":"20200210"
},
"refresh_token":{
"token":"bhacvyusbi",
"expired_at":"20200210"
}
}
}
so I have created a Response dto
class ResponseDto{
UserDto user;
AllTokenDto reponse;
}
class AllTokenDto{
TokenDto access_token;
TokenDto refresh_token;
}
class TokenDto{
String token;
Date expiredDate;
}
In here userData is which I am get the data from database
ResponseDto responseDto = new ResponseDto();
responseDto.setUser(modelMapper.map(**userData**, UserDto.class));
I have successfully added ResponseDto to UserDto data,
how to added tokens data to the ResponseDto.

Related

Spring boot application not accepting ID of incoming POST request

I have an existing system that uses string based unique IDs for users and I want to transfer that System into a Spring boot application. I want to creat a user so I send a POST request with the following content:
As you can see, the id gets ignored.
This is my Spring code for the user class:
#PostMapping("/user")
ResponseEntity addUser(User receivedUser) {
Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
logger.info("Empfangener User: " + receivedUser.toString());
try {
User mailCheckUser = userService.getUserByMail(receivedUser.getEmail());
User nameCheckUser = userService.getUserByName(receivedUser.getUsername());
if (mailCheckUser != null){
return new ResponseEntity("Email already exists", HttpStatus.NOT_ACCEPTABLE);
}
if (nameCheckUser != null){
return new ResponseEntity("Username already exists", HttpStatus.NOT_ACCEPTABLE);
}
userService.addUser(receivedUser);
} catch (Exception userCreationError) {
return new ResponseEntity(receivedUser, HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity(receivedUser, HttpStatus.OK);
}
public void addUser(User user) {
userRepository.save(user);
}
And this is my user class:
#Entity
#Table
public class User {
#Id
#Column(unique =true)
private String id;
private #Column(unique =true)
String username;
private #Column(unique =true)
String email;
private #Column(unique =true)
String simpleAuthToken;
private
String password;
/*REDACTED*/
private
boolean isBlocked;
public User(String id, String name, String email, boolean isBlocked) {
this.id = id;
this.username = name;
this.email = email;
this.simpleAuthToken = simpleAuthToken;
this.isBlocked = false;
}
public User() {
}
/*GETTERS AND SETTERS ARE HERE, BUT I CUT THEM FOR SPACING REASONS*/
}
And this is the Spring Output:
My expected outcome would be that Spring would recognize the id and then create a user with the id I provided. Why is the id always null?
EDIT: If I put the ID in a Put or Get Mapping as Path variable, like so:
#PutMapping("/user/{id}")
ResponseEntity updateUser(#PathVariable String id, User receivedUser) {}
then it gets read and recognized, but it will still be null in the receivedUser
First add #RequestBody in the post request body. In the Post request (/test/user) your passing some params but in the method level not received.
If you want receive id from postman then add #RequestParam("id")String id in the method level.
How you generating unique Id by manually or some generators?
And double check user id at the database console level.

What is the CLI command to view inside of a set data type in redis

I user a CRUDRepository in my spring data redis project to persist a redis hash in my redis cluster. i have rest api written to persist and get thte values of the data. this works fine.
however my entity annotated with RedisHash is being saved as a set / and i am not able to look inside the value using redis cli.
how do i look inside a set data type(without popping) in redis cli
i looked at redis commands page https://redis.io/commands#set
i only get operations which can pop value . i neeed to simply peek
EDIT:
to make things clearer, i am using spring crudrepo to save the user entity into redis data store. the user entity gets saved as a set data type.
when i query back the user details, i can see entire details of the user
{
userName: "somak",
userSurName: "dattta",
age: 23,
zipCode: "ah56h"
}
i essentially want to do the same using redis cli... but all i get is
127.0.0.1:6379> smembers user
1) "somak"
how do i look inside the somak object.
#RestController
#RequestMapping("/immem/core/user")
public class UserController {
#Autowired
private UserRepository userRepository;
#RequestMapping(path = "/save", method = RequestMethod.GET, produces = "application/json")
#ResponseStatus(HttpStatus.OK)
public void saveUserDetails() {
User user = new User();
user.setAge(23);
user.setUserName("somak");
user.setUserSurName("dattta");
user.setZipCode("ah56h");
userRepository.save(user);
}
#RequestMapping(path="/get/{username}", method = RequestMethod.GET, produces = "application/json")
public User getUserDetails(#PathVariable("username") String userName) {
return userRepository.findById(userName).get();
}
}
#Repository
public interface UserRepository extends CrudRepository<User, String>{
}
#RedisHash("user")
public class User {
private #Id String userName;
private #Indexed String userSurName;
private #Indexed int age;
private String zipCode;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserSurName() {
return userSurName;
}
public void setUserSurName(String userSurName) {
this.userSurName = userSurName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
}
I don't understant your descr with your problem, but I understand your title.
In redis set, the member is always string type.
I hope you can offer more info about UserRepository.save:
User user = new User();
user.setAge(23);
user.setUserName("somak");
user.setUserSurName("dattta");
user.setZipCode("ah56h");
userRepository.save(user);
And you can check your redis data and check data type when rest api invoked.

How to ignore specific fields on income in Spring boot?

I have my domain class as follows
#Getter
#Setter
public class Student {
private Long id;
private String firstName;
private String lastName;
}
And I have this controller
#RestController
#RequestMapping("/student")
public class StudentController {
#PostMapping(consumes = "application/json", produces = "application/json")
public ResponseEntity<Student> post(#RequestBody Student student) {
//todo save student info in db, it get's an auto-generated id
return new ResponseEntity<>(student, HttpStatus.CREATED);
}
}
Now what I want is to configure serializer in a way that it ignores the id field on income, so I get only firstName and lastName, but serialize it when I'm returning the object to the caller.
Its easy to use it with jackson. There is an annotation named #JsonProperty(access = Access.READ_ONLY) where you can define if the property should be de- or serialized. Just put that annotation on your id field.
#JsonProperty(access = Access.READ_ONLY)
private Long id;
The Controller:
#PostMapping(consumes = "application/json", produces = "application/json")
public ResponseEntity<Student> post(#RequestBody Student student) {
//here we will see the that id is not deserialized
System.out.println(student.toString());
//here we set a new Id to the student.
student.setId(123L);
//in the response we will see that student will serialized with an id.
return new ResponseEntity<>(student, HttpStatus.CREATED);
}
Requestbody:
{
"id":1,
"firstName": "Patrick",
"lastName" : "secret"
}
Output of toString():
Student [id=null, firstName=Patrick, lastName=secret]
Response:
{
"id": 123,
"firstName": "Patrick",
"lastName": "secret"
}
P.S. It will also work if you dont send an id property:
{
"firstName": "Patrick",
"lastName" : "secret"
}

How to send Java collections containing subclasses to spring controller

I'm trying to send collections to my spring MVC controller:
#RequestMapping("/postUsers.do")
public #ResponseBody ResponseDTO postUsers(#ModelAttribute("mapperList") MapperList mapperList) {
//prints {"users":null}
System.out.println(new ObjectMapper().writeValueAsString(mapperList));
return new ResponseDTO();
}
this is the code posting my users :
public ResponseDTO postUsers(ArrayList<User> users) {
ResponseDTO serverResponse = null;
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestMethod("POST");
// prints {"users":[{"property1":"x","property1":y}]}
System.out.println(objectMapper.writeValueAsString(new MapperList(users)));
objectMapper.writeValue(connection.getOutputStream(), objectMapper.writeValueAsString(new MapperList(users)));
//blabla ...
}
and this is the object containing my list :
public class MapperList implements Serializable {
private static final long serialVersionUID = 8561295813487706798L;
private ArrayList<User> users;
public MapperList() {}
public MapperList(ArrayList<User> users) {
this.setUsers(users);
}
public ArrayList<User> getUsers() {
return users;
}
public void setUsers(ArrayList<User> users) {
this.users = users;
}
}
and this is the users type to post:
public abstract class User implements Serializable {
private static final long serialVersionUID = -1811485256250922102L;
private String property1;
private String property2;
public User() {}
public User(String prop1, String prop2) {
// set properties
}
// getters and setters
}
the problem is, when I output the value of the users's array before to post it to the controller, I got the following json value :
{"users":[{"property1":"x","property1":y}]}
but in the controller, when I print what I get from the request body, I only get :
{"users":null}
I also tryed with the annotation #RequestBody instead of #ModelAttribute("mapperList") and a JSONException is displayed :
*A JSONObject text must begin with '{' at 1 [character 2 line 1]\r\n*
My array list of users contains only one user that should be displayed. I don't understand why this doesn't work...
Thanks for any help !
You can chnage your MapperList class definition as public class MapperList extends ArrayList<User>{ ..} you dont need to define any instance variable like private ArrayList users inside MapperList class. Use #Requestbody annotation. You will be able to use MapperList as a ArrayList
Try to use:
public class MapperList{
private List<User> users;
//setter and getter
//toString
}
public class User{
private String property1;
private String property2;
//getter + setter
}
json:
{"users":[{"property1":"x", "property2":"y"}]}
in controller use #RequestBody. In that case Jackson will map your json to ArrayList of users.
#ResponseStatus(HttpStatus.OK)
#RequestMapping("/postUsers.do")
public #ResponseBody ResponseDTO postUsers(#RequestBody MapperList users) {
System.out.println(users);
return null;
}
no need to get objectMapper in that case. Don't forget to set content-type in request header to application/json. It required by Spring to handle #RequestBody processing.
If not working try to change MapperList:
List<User> users = new ArrayList<User>();
On the server side keep the #RequestBody annotation:
public #ResponseBody ResponseDTO postUsers(#RequestBody MapperList mapperList)
...
But this line causes problems:
objectMapper.writeValue(
connection.getOutputStream(),
objectMapper.writeValueAsString(new MapperList(users))
);
First it converts the object to JSON and then again uses objectMapper to JSON-encode the string into output stream. Try the following instead:
connection.getOutputStream().write(
objectMapper.writeValueAsString(new MapperList(users))
.getBytes("UTF-8")
);
or directly output to stream:
objectMapper.writeValue(
connection.getOutputStream(),
new MapperList(users))
);
Zbynek gave me part of the answer. Indeed
objectMapper.writeValue(
connection.getOutputStream(),
objectMapper.writeValueAsString(new MapperList(users))
);
doesn't work properly in my case
But moreover, my User class was an abstract class, with many type of User as subclasses. so the #RequestBody annotation couldn't work without specified the object type in the Json.
I used the following annotations on User class to make it working :
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
#JsonSubTypes({
#JsonSubTypes.Type(value = SubClassA.class, name = "a"),
#JsonSubTypes.Type(value = SubClassB.class, name = "b")
})
Thanks a lot for all your answers.

How to update record in springboot JpaRepository?

My model is
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name="name")
private String name;
#Column(name="email")
private String email;
//getter & setter
}
My controller is
#RequestMapping(value = "user/userProfile", method = RequestMethod.POST)
public String saveUserProfile(#Valid UserProfile userProfile, #RequestParam("file") MultipartFile file,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("userProfile", userProfile);
return "userprofileform";
}
userProfileService.saveUserProfile(userProfile);
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/user/home";
}
#RequestMapping("/user/userProfile/new")
public String newUserProfile(Model model) {
UserProfile profile = userProfileService.getUserProfileByUserId(userService.getLoggedInUser().getId());
model.addAttribute("userProfile", profile);
return "userprofile";
}
Repository is
#Transactional
public interface UserProfileRepository extends CrudRepository<UserProfile, Long>{
}
When I am creating first time userProfile it creates successfully but when I tried to update same it create new entry.
But in this controller when I use findone() and copy all information it works fine.
Same save method replaced below like :
public String saveUserProfile(#Valid UserProfile userProfile, #RequestParam("file") MultipartFile file,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("userProfile", userProfile);
return "userprofileform";
}
UserProfile tempProfile = userProfileService.getUserProfileByUserId(userService.getLoggedInUser().getId());
try {
if (tempProfile != null) {
tempProfile.setName(userProfile.getName());
tempProfile.setEmail(userProfile.getEmail()); userProfileService.saveUserProfile(tempProfile);
} else {
userProfile.setUserId(userService.getLoggedInUser().getId());
userProfileService.saveUserProfile(userProfile);
}
} catch (IOException e) {
e.printStackTrace();
}
return "redirect:/user/home";
}
Is this write way or how can we update record?.
Or saving in session attribute (#SessionAttributes("yourAttributeName")) is only the write way?
Make sure the userProfile object has an id assigned. If your object doesn't have an id, hibernate assumes it's a new entity and therefore it creates a new record in the database.
You need to confirm that when you want to do an update the UserProfile has an id. Put a debug point at: profileRepo.save(userProfile) to confirm this, as a new Entity will be created if no id exists, and should be updated if the id already exists.

Resources