How to update only chosen records from form? - java

The main question is, how to update just a few chosen fields from our form. I would like to give user choice which fields they want to update. For example, I have the form class:
public class UserRegistrationform {
private Integer userId;
#NotNull
private String name;
#NotNull
private String surname;
#Email
#NotNull
private String email;
#NotNull
private Integer genderId;
#NotNull
private Integer groupId;
#NotNull
private List<ContactInfoDto> contactsInfo;
#NotNull
private String userSecretkey;
#NotNull
private String password;
#NotNull
private boolean enabled;
#NotNull
private boolean resetPassword;
After that I'm setting fields in #Entity class User, and for example, if user want to change just their name and surname, I want to take the rest of the fields from the existing User, by findById() method and after that change a few fields and save the changed object to the database.

#BeshambherChaukhwan ok, maybe will be easier where I will use example, so I have a controller when is method:
#PostMapping(value = "{id}/updateuser")
public ResponseDTO updateUser(#PathVariable int id, #RequestBody UserRegistrationform userForm, BindingResult bindingResult) {
User user = userRepository.findById(id);
if (user == null) {
return ResponseDTO.of(Messages.Error_UserNotFound_MSG.getMessage(), ErrorCodes.NOT_FOUND);
} else if (bindingResult.hasErrors()) {
return ResponseDTO.of(bindingResult.getAllErrors().toString(), ErrorCodes.INVALID_FIELDS);
}
user.setName(userForm.getName);
user.setSurname(userForm.getSurname);
user.setEmail(userForm.getEmail);
.
.
.
userRepository.save(user);
return ResponseDTO.of(Messages.SUCCESS_Update_MSG.getMessage());
}
The problem is, like you noticed when in form someone miss few fields, and I will update right fields by null values

Related

I'm stuck trying to save #DBRef inside document

I have document user and document adventureHolidays. There is a lot of users and as well adventure holidays. So far I created a controller that return me a random element from adventureHolidays document. On that page I have button to randomize again and on each click new document from adventureHoliday is provided. What is my goal right now? I want to create a button that will actually save a current document that is provided as field in user document, so he can see on his profile which adventureHolidays he has saved.
This is user entity
#Document
public class User {
#Id
private String id;
#Indexed(unique = true)
#NonNull
private String username;
#Indexed(unique = true)
#NonNull
private String email;
#JsonIgnore
#NonNull
private String password;
#DBRef
private List<AdventureHolidays> adventureHolidaysList;
And this is AdventureHoldiays
#Document("adventureholidays")
public class AdventureHolidays {
#Id
private String id;
private String title;
private String description;
private String state;
private String typeOfAdventureHolidays;
private String image;
How I can now save document that is random returned to user to user entity? I even dont know where to start. Guess I need ID and that to save somehow it to field in user document

Saving a element from one document to user document

I have those two entites:
#Document
public class User {
#Id
private String id;
#Indexed(unique = true)
#NonNull
private String username;
#Indexed(unique = true)
#NonNull
private String email;
#JsonIgnore
#NonNull
private String password;
#Document("adventureholidays")
public class AdventureHolidays {
#Id
private String id;
private String title;
private String description;
private String state;
private String typeOfAdventureHolidays;
private String image;
I want to create a service that will save into user document element from adventureholidays.
I have a service to return a random element from adventureholidays document, so If user want to save that document I would like to save title of that document into user document.
So somehow I need to take a ID of current adventureholiday that is provided and then to save to current logged user.
I am just giving you the logic, add
#DBRef
private AdventureHolidays adventureHolidays;
in your User class it will map both classes, then get the id of holiday from the save button using link or value from your form and then using that id in find() function and fetch the data of that particular holiday store it in a object ie. holiday.
Now just save it in service class inside a method like this:
User user=new User();
user.setAdventureHolidays(holiday);
// create a userRepository which extends MongoRepository
userRepository.save(user);

returning specific version of DTO based on user role

I have a JobDTO class
class JobDTO{
private Integer id;
private String jobTitle;
private String secreateData;
...
}
I have a BidDTO class
class BidDTO{
private Integer id;
private String bidDetails;
private JobDTO jobDTO;
public BidDTO(Integer id, String bidDetails, JobDTO jobDTO){
this.id = id;
this.bidDetails = bidDetails;
this.jobDTO = jobDTO;
}
}
The reason I have JobDTO in BidDTO is because when I return a bid I need to return the related job details as well. The question is that what I want to hide the secretData in JobDTO from user based on users's role?
One solution could be to put individual JobDTO fields in BidDTO that I want to show to user rather than having a JobDTO object as part of it but what if there are 100 fields in JobDTO and I only have one secretData field that want to hide.

How to access the String json payload and mapping it to an Object in Spring rest controller?

I'm building a rest API using Spring Boot rest services.
I have a Java class:
class Person{
int id;
#notNull
String name;
#notNull
String password;
}
And I want to make an API to create a Person object. I will recieve a POST request with json body like:
{
"name":"Ahmad",
"password":"myPass",
"shouldSendEmail":1
}
As you can see there are an extra field "shouldSendEmail" that I have to use it to know if should I send an email or not after I create the Person Object.
I am using the following API:
#RequestMapping(value = "/AddPerson", method = RequestMethod.POST)
public String savePerson(
#Valid #RequestBody Person person) {
personRepository.insert(person);
// Here I want to know if I should send an email or Not
return "success";
}
Is there a method to access the value of "shouldSendEmail" while I using the autoMapping in this way?
There's many options for you solve. Since you don't want to persist the shouldSendEmail flag and it's ok to add into you domain class, you can use the #Transient annotation to tell JPA to skip the persistence.
#Entity
public class Person {
#Id
private Integer id;
#NotNull
private String name;
#NotNull
private String password;
#Transient
private Boolean shouldSendEmail;
}
If you want more flexible entity personalizations, I recommend using DTO`s.
MapStruct is a good library to handle DTO`s
You will need an intermediary DTO, or you will otherwise have to modify person to include a field for shouldSendEmail. If that is not possible, the only other alternative is to use JsonNode and manually select the properties from the tree.
For example,
#Getter
public class PersonDTO {
private final String name;
private final String password;
private final Integer shouldSendEmail;
#JsonCreator
public PersonDTO(
#JsonProperty("name") final String name,
#JsonProperty("password") final String password,
#JsonProperty("shouldSendEmail") final Integer shouldSendEmail
) {
this.name = name;
this.password = password;
this.shouldSendEmail = shouldSendEmail;
}
}
You can use #RequestBody and #RequestParam together as following
.../addPerson?sendEmail=true
So send the “sendEmail” value as request param and person as request body
Spring MVC - Why not able to use #RequestBody and #RequestParam together
You have mutli solutions
1 - You can put #Column(insertable=false, updatable=false) above this property
2 - send it as request param #RequestParam
#RequestMapping(value = "/AddPerson", method = RequestMethod.POST)
public String savePerson(
#Valid #RequestBody Person person, #RequestParam boolean sendMail) {}
3- use DTO lets say PersonModel and map it to Person before save

Only using #JsonIgnore during serialization, but not deserialization

I have a user object that is sent to and from the server. When I send out the user object, I don't want to send the hashed password to the client. So, I added #JsonIgnore on the password property, but this also blocks it from being deserialized into the password that makes it hard to sign up users when they don't have a password.
How can I only get #JsonIgnore to apply to serialization and not deserialization? I'm using Spring JSONView, so I don't have a ton of control over the ObjectMapper.
Things I've tried:
Add #JsonIgnore to the property
Add #JsonIgnore on the getter method only
Exactly how to do this depends on the version of Jackson that you're using. This changed around version 1.9, before that, you could do this by adding #JsonIgnore to the getter.
Which you've tried:
Add #JsonIgnore on the getter method only
Do this, and also add a specific #JsonProperty annotation for your JSON "password" field name to the setter method for the password on your object.
More recent versions of Jackson have added READ_ONLY and WRITE_ONLY annotation arguments for JsonProperty. So you could also do something like:
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;
Docs can be found here.
In order to accomplish this, all that we need is two annotations:
#JsonIgnore
#JsonProperty
Use #JsonIgnore on the class member and its getter, and #JsonProperty on its setter. A sample illustration would help to do this:
class User {
// More fields here
#JsonIgnore
private String password;
#JsonIgnore
public String getPassword() {
return password;
}
#JsonProperty
public void setPassword(final String password) {
this.password = password;
}
}
Since version 2.6: a more intuitive way is to use the com.fasterxml.jackson.annotation.JsonProperty annotation on the field:
#JsonProperty(access = Access.WRITE_ONLY)
private String myField;
Even if a getter exists, the field value is excluded from serialization.
JavaDoc says:
/**
* Access setting that means that the property may only be written (set)
* for deserialization,
* but will not be read (get) on serialization, that is, the value of the property
* is not included in serialization.
*/
WRITE_ONLY
In case you need it the other way around, just use Access.READ_ONLY.
In my case, I have Jackson automatically (de)serializing objects that I return from a Spring MVC controller (I am using #RestController with Spring 4.1.6). I had to use com.fasterxml.jackson.annotation.JsonIgnore instead of org.codehaus.jackson.annotate.JsonIgnore, as otherwise, it simply did nothing.
Another easy way to handle this is to use the argument allowSetters=truein the annotation. This will allow the password to be deserialized into your dto but it will not serialize it into a response body that uses contains object.
example:
#JsonIgnoreProperties(allowSetters = true, value = {"bar"})
class Pojo{
String foo;
String bar;
}
Both foo and bar are populated in the object, but only foo is written into a response body.
"user": {
"firstName": "Musa",
"lastName": "Aliyev",
"email": "klaudi2012#gmail.com",
"passwordIn": "98989898", (or encoded version in front if we not using https)
"country": "Azeribaijan",
"phone": "+994707702747"
}
#CrossOrigin(methods=RequestMethod.POST)
#RequestMapping("/public/register")
public #ResponseBody MsgKit registerNewUsert(#RequestBody User u){
root.registerUser(u);
return new MsgKit("registered");
}
#Service
#Transactional
public class RootBsn {
#Autowired UserRepository userRepo;
public void registerUser(User u) throws Exception{
u.setPassword(u.getPasswordIn());
//Generate some salt and setPassword (encoded - salt+password)
User u=userRepo.save(u);
System.out.println("Registration information saved");
}
}
#Entity
#JsonIgnoreProperties({"recordDate","modificationDate","status","createdBy","modifiedBy","salt","password"})
public class User implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String country;
#Column(name="CREATED_BY")
private String createdBy;
private String email;
#Column(name="FIRST_NAME")
private String firstName;
#Column(name="LAST_LOGIN_DATE")
private Timestamp lastLoginDate;
#Column(name="LAST_NAME")
private String lastName;
#Column(name="MODIFICATION_DATE")
private Timestamp modificationDate;
#Column(name="MODIFIED_BY")
private String modifiedBy;
private String password;
#Transient
private String passwordIn;
private String phone;
#Column(name="RECORD_DATE")
private Timestamp recordDate;
private String salt;
private String status;
#Column(name="USER_STATUS")
private String userStatus;
public User() {
}
// getters and setters
}
You can use #JsonIgnoreProperties at class level and put variables you want to igonre in json in "value" parameter.Worked for me fine.
#JsonIgnoreProperties(value = { "myVariable1","myVariable2" })
public class MyClass {
private int myVariable1;,
private int myVariable2;
}
You can also do like:
#JsonIgnore
#JsonProperty(access = Access.WRITE_ONLY)
private String password;
It's worked for me
I was looking for something similar. I still wanted my property serialized but wanted to alter the value using a different getter. In the below example, I'm deserializing the real password but serializing to a masked password. Here's how to do it:
public class User() {
private static final String PASSWORD_MASK = "*********";
#JsonIgnore
private String password;
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
public String setPassword(String password) {
if (!password.equals(PASSWORD_MASK) {
this.password = password;
}
}
public String getPassword() {
return password;
}
#JsonProperty("password")
public String getPasswordMasked() {
return PASSWORD_MASK;
}
}
The ideal solution would be to use DTO (data transfer object)

Categories