I have a personal project that runs the backend under spring boot that implements websocket for real-time functionality and I apply it to a crud operations.
Although the code is working and work as expected I doubt if I do the correct implementation of spring websocket here.
I've used React as my frontend as call the crud function on their @MessageMapping
annotation.
The way I implement the backend to my frontend is.
- Fetching all
Person
records and store in an array state. - Then for create
Person
record I just append in to the new record to the persons state array
I doubt if I do it correctly because when I debug the websocket client, I found out that it.
@Autowired
private SimpMessagingTemplate template;
@Autowired
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@MessageMapping("/person/add")
public void createPerson(Person person) {
Person savePerson = new Person(person.getFirstName(), person.getLastName());
personRepository.save(savePerson);
this.template.convertAndSend("/topic/person", viewPersons());
}
@RequestMapping("/person")
@ResponseBody
public List<Person> viewPersons(){
List<Person> persons = personRepository.findAll();
return persons;
}
@MessageMapping("/person/delete")
public void deletePerson(@Payload PersonDeleteRequest request) {
Person person = personRepository.findById(request.getId()).orElseThrow(() -> new RuntimeException("No id found."));
personRepository.delete(person);
this.template.convertAndSend("/topic/person", viewPersons());
}
@MessageMapping("/person/update")
public void updatePerson(@Payload Person requestPerson) {
Person person = personRepository.findById(requestPerson.getId()).orElseThrow(() -> new RuntimeException("No id found."));
person.setFirstName(requestPerson.getFirstName());
person.setLastName(requestPerson.getLastName());
personRepository.save(person);
this.template.convertAndSend("/topic/person", viewPersons());
}
1 Answer 1
@Autowired
is not required on constructor in Spring over 4.3 (class has to be annotated as bean and have only one constructor).
Inject SimpMessagingTemplate template
in a constructor. Now you mix annotation and constructor injection.
IMHO you shouldn't put any business login in controller methods. I would move it all to separate service. For example I would write updatePerson()
like this:
@MessageMapping("/person/update")
public void updatePerson(@Payload Person requestPerson) {
personService.updatePerson(requestPerson);
this.template.convertAndSend("/topic/person", personService.viewPersons());
}
In updatePerson()
and createPerson()
you should have separate objects instead of Person class. E.g. CreatePersonRequest
and UpdatePersonRequest
I would change viewPersons()
to getAllPersons()
The rest look fine :)
Explore related questions
See similar questions with these tags.