Reputation: 91
I'm develop an application JAVA + Spring Boot+ ThymeLeaf(easy and simple front just for test). I have got simple domain class Player:
@Entity
@Setter
@Getter
@EqualsAndHashCode(exclude = {"events"})
public class Player {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String playerName;
private String playerLastName;
private String playerNickname;
private String playerEmailAddress;
private String playerTelephoneNumber;
@ManyToMany(mappedBy = "players", fetch = FetchType.EAGER)
private Set<Event> events = new HashSet<>();
@Enumerated(value = EnumType.STRING)
private FavouritePosition favouritePosition;
private LocalDate birthdayDate;
}
I would like to calculate player age in "service" class.
The question is: how to tranfer this information to the frontend?
Controller method look like this:
@RequestMapping("/event/{eventId}/player/{playerId}/show")
public String showPlayerForSpecificTeam(Model model, @PathVariable String eventId, @PathVariable String playerId) {
model.addAttribute("player", playerService.getPlayerByEventIdAndPlayerId(Long.valueOf(eventId), Long.valueOf(playerId)));
return "event/player/showPlayerForSpecifiedEvent";
}
Where method getPlayerByEventIdAndPlayerId(Long.valueOf(eventId), Long.valueOf(playerId))
return the Player object (there are no age just the birthday date).
I don't want to store in the database age value for each player - it is obvious.
Should I add to the controller another: model.addAttribute(); with information about age? (it doesnt looks good even for me)
I'm looking for smart solution, comply with the rules of clean code and MVC. I would be glad if you will help me find good solution, thank you.
EDIT: I just create class AgeCalculator:
@Component
@Data
public class AgeCalculator {
public Integer calculateAge(Player player) {
return Years.yearsBetween(player.getBirthdayDate(), new LocalDate()).getYears();
}
}
Modified controller:
@RequestMapping({"player/{playerId}/show"})
public String getPlayerById(Model model, @PathVariable String playerId) {
model.addAttribute("player", playerService.getPlayerById(Long.valueOf(playerId)));
model.addAttribute("ageCalculator", new AgeCalculator());
return "event/player/showPlayerById";
}
And in thymeleaf I use:
<p th:text="${ageCalculator.calculateAge(player)}">Here will be a Player age</p>
But I receive an error: org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating SpringEL expression: "ageCalculator.calculateAge(player.birthdayDate)"
Whats wrong with my code?
Upvotes: 0
Views: 822
Reputation: 91
Ok thanks for all replays. The complete resolution for this problem.
Controller:
@RequestMapping({"player/{playerId}/show"})
public String getPlayerById(Model model, @PathVariable String playerId) {
model.addAttribute("player", playerService.getPlayerById(Long.valueOf(playerId)));
model.addAttribute("ageCalculator", new AgeCalculator());
return "event/player/showPlayerById";
}
Age calculator:
@Component
@Data
public class AgeCalculator {
private LocalDate fromStringToLocalDate(String localDateString) {
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy");
return LocalDate.parse(localDateString, inputFormat);
}
public int calculateAge(String birthDate) {
if (birthDate != null) {
return Period.between(fromStringToLocalDate(birthDate), LocalDate.now()).getYears();
} else {
return 0;
}
}
}
Player Domain Class:
@Entity
@Setter
@Getter
@EqualsAndHashCode(exclude = {"events"})
public class Player {
(...)
private String birthdayDate;
}
Thymeleaf code:
<p th:text="${ageCalculator.calculateAge(player.birthdayDate)}">Here will be a player age</p>
Upvotes: 0
Reputation: 921
You could add just full object or part of it in javascript and work with it like pure value:
<script type="text/javascript" th:inline="javascript">
/*<![CDATA[*/
var some_data =/*[[${data}]]*/;
/*]]>*/
</script>
It just good way to pass parameter from spring controller to frontend.
Upvotes: 1
Reputation: 20487
My preferred method would be to add a getAge()
method to the Player
class. Then in the front end, it would look like this:
<span th:text="${player.age}" />
If you don't want to modify the Player
class, you could create a helper object with a calculateAge(LocalDate birthday)
method, and then add it to the model and call it like this:
Java: model.addAttribute("helper", new BirthdayHelper());
Thymeleaf: <span th:text="${helper.calculateAge(player.birthdayDate)}" />
Upvotes: 1