Should the shared variable inside the service that is in the mvc controller be volatile? - spring

Inside the MVC controller , I have a service that I access to get data:
#Controller
#AllArgsConstructor
public class DataController {
private SharedDataService sharedDataHolder;
#RequestMapping(value = "/testPoint", method = GET)
public String getData(#PathVariable String point, Model model){
Data data = sharedDataHolder.getData();
...
}
}
and SharedDataService :
#Service
public class SharedDataService {
private Data data;
public Data getData(){
if(isHourAgo()){
this.refreshData();
}
return data;
...
}
}
And actually the question is, should I make the data variable of the SharedDataService class volatile so that there is no conflict inside the controller?
Data :
public class Data {
private String title;
private Map<String,Double> characteristics;
}

Related

GET method: How to convert snake_case query string to camelCase DTO

I use snake_case DB columns and camelCase DTO.
And our team want to use snake_case when we code React component.
Because of it, I added #JsonNaming on DTO. But it works when I send Json data, as you know.
Is there any annotation or setting similar to #JsonNaming?
Here is my postman data and sample codes.
Debug data: sampleName=name, sampleDesc=null.
// Controller
#RestController
#RequestMapping("/sample")
public class SampleController {
#Autowired
private SampleService sampleService;
#GetMapping
public Result getSampleList(SampleDTO param) throws Exception {
return sampleService.getFolderList(param);
}
#PostMapping
public Result insertSample(#RequestBody SampleDTO param) throws Exception {
// this method works well with #JsonNaming
return sampleService.insertFolder(param);
}
}
// DTO
#Setter
#Getter
#NoArgsConstructor
#JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
#Alias("SampleDTO")
public class SampleDTO {
#NotNull
private Long sampleNo;
#NotBlank
private String sampleName;
private String sampleDesc;
#Builder
public SampleDTO(Long sampleNo, String sampleName, String sampleDesc) {
this.sampleNo = sampleNo;
this.sampleName = sampleName;
this.sampleDesc = sampleDesc;
}
}
I had the same problem and didn't find an annotation for this but maybe you can use #ConstructorProperties like this in your DTO's constructor:
#ConstructorProperties({"sample_no","sample_name","sample_desc"})
public SampleDTO(Long sampleNo, String sampleName, String sampleDesc) {
this.sampleNo = sampleNo;
this.sampleName = sampleName;
this.sampleDesc = sampleDesc;
}

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;
}

Sending #Value annotated fields to a DTO layer returns null

I have a class which is composed of 2 different objects :
public class MyClass{
private OptionClass optionClass;
private ConstantClass constantClass;
public DocumentToSignRestRequest(OptionClass optionClass, ConstantClass constantClass) {
this.optionClass= optionClass;
this.constantClass= constantClass;
}
}
My first class is a classic POJO. My second class retrieve values from the application.properties file.
public class ConstantClass {
#Value("${api.url}")
private String hostName;
#Value("${sign.path}")
private String pathStart;
public ConstantClass () {
this.hostName= getHostName();
this.path = getPath();
}
I map MyClass with MyClassDto in order to call a service.
#PostMapping(
value="/sign",
consumes = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE },
produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE }
)
public MyClassRest prepareDocument(#RequestBody DocumentToPrepare documentToPrepare) throws Exception {
MyClassRest returnValue = new MyClassRest ();
ModelMapper modelMapper = new ModelMapper();
MyClassDto myClassDto = modelMapper.map(documentToPrepare, MyClassDto .class);
DocumentDto signedDocument = documentService.signDocument(documentDto);
returnValue = modelMapper.map(signedDocument, DocumentRest.class);
return returnValue;
}
My DTO class work fine and retrieve the OptionClass datas, but concerning the second Class, i obtain null as value, while i try to print it out in the service layer.
Your ConstantClass should be a Bean or a Component (as #cassiomolin says in comments)
#Component
public class ConstantClass {
private String hostName;
private String pathStart;
public ConstantClass (#Value("${api.url}") String url, #Value("${sign.path}") String path ) {
this.hostName = url;
this.pathStart = path;
}
// getters...
Then you can easily inject this component in your Controller and use it.
#Controller
public class YourController(){
private ConstantClass constantClass;
public YourController(ConstantClass constantClass){
this.constantClass = constantClass;
}
#PostMapping("...")
public MyClass post(.....){
.....
MyClass myclass = new MyClass(this.constantClass,...)
.....
}
}
note that Spring can autowire #Value and #Component, ... via the constructor; that can be very useful when you do unit-testing

Update database ManytoOne relationship (Spring Boot + MVC +Thymeleaf)

I have two entity class.one is PhaseEntity and another is TaskEntity. PhaseId will be the foreign key of TaskEntity class. I can create and save the value to the database but cannot update the database.
Portion of TaskEntity class:
#ManyToOne(optional=false)
#JoinColumn(name="phaseId")
private PhaseEntity phaseEntity;
Controller class:
public class TaskController {
#Autowired
private TaskService taskService;
#Autowired
private PhaseService phaseService;
#RequestMapping(value="/task/create",method=RequestMethod.GET)
public String createForm(Model model,Principal principal){
model.addAttribute(new TaskEntity());
model.addAttribute("body", "task/task-create");
model.addAttribute("generaltaskDto",new GeneralTaskDto());
model.addAttribute("phaseEntities", phaseService.phaseList());
return "layouts/default";
}
#RequestMapping(value="/task/create",method=RequestMethod.POST)
public String createFormPost(Model model,GeneralTaskDto generaltaskDto,BindingResult result){
TaskEntity taskAndPhase=generaltaskDto.getTaskEntity();
taskAndPhase.setPhaseEntity(phaseService.getPhaseByPhaseId(generaltaskDto.getPhaseId()));
taskService.saveTask(taskAndPhase);
return "redirect:/task/list";
}
#GetMapping(value="/task/update/{id}")
public String updateTask(Model model,#PathVariable String id){
TaskEntity taskEntity= taskService.getTaskId(Integer.parseInt(id));
model.addAttribute("body", "task/task-create");
model.addAttribute("phaseEntities", phaseService.phaseList());
return "layouts/default";
}
GeneraltaskDto class:
public class GeneralTaskDto {
private TaskEntity taskEntity=new TaskEntity();
private Integer phaseId;
public TaskEntity getTaskEntity() {
return taskEntity;
}
public void setTaskEntity(TaskEntity taskEntity) {
this.taskEntity = taskEntity;
}
public Integer getPhaseId() {
return phaseId;
}
public void setPhaseId(Integer phaseId) {
this.phaseId = phaseId;
}
}
here is the client page of the application
can anyone help plz how to update the database with controller request. Thanks in advance.
Please try adding these lines in your controller under updateTask method after TaskEntity taskEntity= taskService.getTaskId(Integer.parseInt(id)); line.
PhaseEntity phaseEntity=taskEntity.getPhaseEntity();
generaltaskDto.setTaskEntity(taskEntity);
generaltaskDto.setPhaseId(phaseEntity.getPhaseId());
model.addAttribute("generaltaskDto", generaltaskDto);

JAXB Error while using in SpringREST to return a ArrayList of a domain object

I am trying to use JAXB in Spring RESTful webservice.
My code is as follows:
#RequestMapping(value = "/countries",
method = RequestMethod.GET,
headers="Accept=application/xml, application/json")
public #ResponseBody CountryList getCountry() {
logger.debug("Provider has received request to get all persons");
// Call service here
CountryList result = new CountryList();
result.setData(countryService.getAll());
return result;
}
The CountryList.java class looks like:
#XmlRootElement(name="countries")
public class CountryList {
#XmlElement(required = true)
public List<Country> data;
#XmlElement(required = false)
public List<Country> getData() {
return data;
}
public void setData(List<Country> data) {
this.data = data;
}
}
The Country.java looks like:
#XmlRootElement(name="country")
public class Country {
private Calendar createdDt;
private String updatedBy;
private String createdBy;
private Long id;
private String countryName;
private Calendar updatedDt;
// getters and setters for all attributes goes here
}
Now, when I access the method getCountry(), I am getting the following exception
Caused by: com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
Class has two properties of the same name "data"
this problem is related to the following location:
at public java.util.List com.cisco.bic.services.model.CountryList.getData()
at com.cisco.bic.services.model.CountryList
this problem is related to the following location:
at public java.util.List com.cisco.bic.services.model.CountryList.data
at com.cisco.bic.services.model.CountryList
Would anyone has any idea why is this error coming. Am I doing anything wrong in the annotaion part ??
Please help.
Regards
Saroj
You can't annotate both the getter/setter and the field, you need to decide on one of them.

Resources