Spring controller method argument post init callback - spring

I have a controller method that takes a bean as an argument. This controller method accepts POST requests and the corresponding post body is populated inside the argument bean. I want to call the postInit method inside PasswordChange Object after this bean is initialized and the json has been deserialized but before the service call inside the controller method is made.I know there is the Spring's #PostConstruct but because I am using Jackson for json deserialization via the MappingJacksonJsonView I wasn't sure certain if this method would be reliably called. Can anybody tell me if this is infact a valid use of #PostConstruct.
I am using Spring 3.2.8 with Jackson-databind 2.3.2.
#RequestMapping(value = "/passwordChange", method = RequestMethod.POST)
public #ResponseBody PasswordInfo passwordInfo(#RequestBody #Valid PasswordChange passwordChange)
throws PasswordChangeException {
return passwordService.changePassword(passwordChange.getLoginKey(), passwordChange.getOldPassword(), passwordChange.getNewPassword());
}
PasswordChange Bean.
public class PasswordChange {
private String loginKey;
private String oldPassword;
private String newPassword;
#Autowired
private LoginDao loginDao;
private LoginEntity login;
private Person person;
public PasswordChange() {
}
public PasswordChange(String loginKey, String oldPassword, String newPassword) {
this.loginKey = loginKey;
this.oldPassword = oldPassword;
this.newPassword = newPassword;
}
#PostConstruct
public void postInit() {
login = loginDao.findByLogin(loginKey);
person = login.getCorePerson();
}
}

Related

How to send model attribute to spring controller using Postman

I want to test my controller using postman but don't know how to send a model attribute using postman.
I tried to send all attributes in row json fornamt and x-www-form-urlencoded in body but it is not working for me, I didn't understand where i'm getting wrong
My controller class looks like :
#RestController
public class DemoController {
#Autowired
private DemoService demoService;
#RequestMapping(value = "/userDetail", method = { RequestMethod.GET }, produces = { MediaType.APPLICATION_JSON })
public String testme(
ModelMap model,
#ModelAttribute("inputParameter") InputParameter inputParameter,
BindingResult result) {
return demoService.getDetail(inputParameter);
}
}
Model Class :
public class InputParameter {
private String id;
private String name;
private String number;
private String address;
private String pass;
}

#PreAuthorize how do i add a parameter into the expression

Maybe somebody has an idea
I have an abstract controller providing me the endpoints i need.
In the #PreAuthorized i would execute the check if the user has the required roles.
Problem is that i have only one function and i want to check which endpoint is currently evaluated.
This is the code:
public abstract class CoreController<T> {
private final JpaRepository repository;
private final CoreService service;
public String endpoint;
private String view;
public CoreController(CoreService service, JpaRepository repository, String endpoint, String view) {
this.service=service;
this.repository = repository;
this.endpoint=endpoint;
this.view=view;
}
#PreAuthorize("#checkAccess.isAllowedToGet(#endpoint)")
#RequestMapping(method = RequestMethod.GET, value = "/get")
public ResponseEntity<CrudPage<Map<String, Object>>> get(CoreCriteria criteria) {
criteria.setView(view);
CrudPage<Map<String, Object>> data = service.getPage(criteria);
return ResponseEntity.ok(data);
}
The problem is the endpoint is always null when the function is called.
How should i change the expression to make this work.

Springboot restinvokation with an non existing field

Suppose I have a model UserInfo which I used in my post service as #RequestBody and when I invoke the service with UserInfo payload it is working.
Class UserInfo {
Private String firstName;
Private String lastName
}
How do I restrict the post call if someone sends some additional fields in the payload which is not exists in UserInfo model (e.g. age)?
In this case, are you using this?
#Autowired
ServiceInterface serviceInterface;
#PostMapping(value = "/userSave")
#RequestBody
public RequestEntity saveUserInfo(**#ModelAttribute** UserInfo userInfo){
return new ResponseEntity(serviceInterface.saveUser(userInfo),HttpStatus.OK);
}
when we are using #ModelAttribute annotation this gets only attribute values in UeserInfo DTO (DATA TRANSFER OBJECT). Also, you can use validations in the UserInfo DTO Class. Like
Class UserInfo {
#NotNull
private String firstName;
#NotNull
private String lastName;
}
But However when using #RequestBody whatever user sends additional data that save only UserInfo Attribute data.
Try to add a property to application.properties:
spring.jackson.deserialization.fail-on-unknown-properties=true
Or create a component:
#Component
public class Jackson2ObjectMapperBuilderCustomizerImpl implements Jackson2ObjectMapperBuilderCustomizer {
#Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.featuresToEnable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
}
}

Spring Boot validation with Hibernate Validator

Anyone know if it`s possible to create one method in my entity, to execute when I put the annotation #Valid in my class?
Example:
I have this Object:
public class Area {
#NotEmpty
private String unidade;
#NotNull
private double tamanho;
public String getUnidade() {
return unidade;
}
public void setUnidade(String unidade) {
this.unidade = unidade;
}
public double getTamanho() {
return tamanho;
}
public void setTamanho(double tamanho) {
this.tamanho = tamanho;
}
}
And I have this method:
#RestController
#RequestMapping("/recolhimento")
public class RecolhimentoController {
#RequestMapping(method = RequestMethod.GET)
public boolean getRecolhimento(#Valid Area area){
...
}
}
so when I call this method the Spring Boot will validate my model Area( but I want to create one method that will be execute when I use #Valid.
it`s possible? how?
Yes, it is possible.
You can find examples in this project: https://github.com/malkusch/validation

#PathVariable not binding with #RequestBody

When I don't use #RequestBody the #PathVariable id is automatically set at my Entity class. But if I use #RequestBody it's not. I need that the id of Entity is set before my GenericValidator executes validation. Why does it work without #RequestBody and not with it?
The Entity class:
public class Entity {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
//...
}
The controller class:
#Controller
#RequestMapping(value = "/entity")
public class EntityController {
#Autowired
private GenericValidator validator;
#InitBinder
private void initBinder(WebDataBinder binder) {
binder.addValidators(validator);
}
#RequestMapping(value = "/{id}", method = RequestMethod.PUT)
public #ResponseBody Response update(
#PathVariable String id,
#Valid #RequestBody Entity entity)
{
//...
}
}
When used alone, #Valid works much like #ModelAttribute. The Entity method argument would be retrieved from the Model or instantiated, the WebDataBinder would handle the data binding process (this is when the id would be set), and then validation would occur.
#RequestBody arguments do not go through the data binding process like #ModelAttribute arguments. They're created via an HttpMessageConverter using the body of the request instead of matching the names of request parameters and path variables to the names of your object's fields. When combined with #Valid, the configured validator is run against the new object but #ModelAttribute style data binding still does not occur.

Resources