I am using the auditing capabilities of Spring Data and have a class similar to this:
@Entity @Audited @EntityListeners(AuditingEntityListener.class) @Table(name="Student") public class Student { @Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; @CreatedBy private String createdBy; @CreatedDate private Date createdDate; @LastModifiedBy private String lastModifiedBy; @LastModifiedDate private Date lastModifiedDate; ...
Now, I believe I have configured auditing fine because I can see that createdBy, createdDate, lastModifiedBy and lastModifiedDate all are getting the correct values when I update the domain objects.
However, my problem is that when I update an object I am losing the values of createdBy and createdDate. So, when I first create the object I have all four values, but when I update it createdBy and createdDate are nullified ! I am also using the Hibernate envers to keep a history of the domain objects.
Do you know why do I get this behavior ? Why do createdBy and createdDate are empty when I update the domain object ?
Update: To answer @m-deinum 's questions: Yes spring data JPA is configured correctly - everything else works fine - I really wouldn't like to post the configuration because as you udnerstand it will need a lot of space.
My AuditorAwareImpl is this
@Component public class AuditorAwareImpl implements AuditorAware { Logger logger = Logger.getLogger(AuditorAwareImpl.class); @Autowired ProfileService profileService; @Override public String getCurrentAuditor() { return profileService.getMyUsername(); } }
Finally, here's my update controller implementation:
@Autowired private StudentFormValidator validator; @Autowired private StudentRepository studentRep; @RequestMapping(value="/edit/{id}", method=RequestMethod.POST) public String updateFromForm( @PathVariable("id")Long id, @Valid Student student, BindingResult result, final RedirectAttributes redirectAttributes) { Student s = studentRep.secureFind(id); if(student == null || s == null) { throw new ResourceNotFoundException(); } validator.validate(student, result); if (result.hasErrors()) { return "students/form"; } student.setId(id); student.setSchool(profileService.getMySchool()); redirectAttributes.addFlashAttribute("message", "Επιτυχής προσθήκη!"); studentRep.save(student); return "redirect:/students/list"; }
Update 2: Please take a look at a newer version
@RequestMapping(value="/edit/{id}", method=RequestMethod.GET) public ModelAndView editForm(@PathVariable("id")Long id) { ModelAndView mav = new ModelAndView("students/form"); Student student = studentRep.secureFind(id); if(student == null) { throw new ResourceNotFoundException(); } mav.getModelMap().addAttribute(student); mav.getModelMap().addAttribute("genders", GenderEnum.values()); mav.getModelMap().addAttribute("studentTypes", StudEnum.values()); return mav; } @RequestMapping(value="/edit/{id}", method=RequestMethod.POST) public String updateFromForm( @PathVariable("id")Long id, @Valid @ModelAttribute Student student, BindingResult result, final RedirectAttributes redirectAttributes, SessionStatus status) { Student s = studentRep.secureFind(id); if(student == null || s == null) { throw new ResourceNotFoundException(); } if (result.hasErrors()) { return "students/form"; } //student.setId(id); student.setSchool(profileService.getMySchool()); studentRep.save(student); redirectAttributes.addFlashAttribute("message", "Επιτυχής προσθήκη!"); status.setComplete(); return "redirect:/students/list"; }
This still leaves empty the createdBy and createdDate fields when I do an update :(
Also it does not get the School value (which is not contained in my form because it is related to the user currently editing) so I need to get it again from the SecurityContext... Have I done anything wrong ?
Update 3: For reference and to not miss it in the comments: The main problem was that I needed to include the @SessionAttributes annotation to my controller.
AuditorAware
implementation look like. Are you updating the object from the database or are you simply merging an entity created from a web-form (which doesn't have thecreated*
andlastModified*
fields). – M. Deinum