Get Userlist with rolename in spring boot - java

In My spring boot Application, I want to see total userlist like below:
username
role
admin
ADMIN
But i got like:
username
role
admin
[com.test.springCRUD.model.Role#3e39aaf6]
My User model:
#Entity
#Table(name = "users")
public class User {
#Id
#Column(name="user_id")
#GeneratedValue(strategy =GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private boolean enabled;
#ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
#JoinTable(name ="users_roles", joinColumns = #JoinColumn (name="user_id"), inverseJoinColumns = #JoinColumn (name="role_id"))
private Set<Role> roles=new HashSet<>();
Role model:
#Entity
#Table(name = "roles")
public class Role {
#Id
#Column(name="role_id")
#GeneratedValue(strategy =GenerationType.IDENTITY)
private Integer id;
private String name;
UserService Class:
#Service
public class UserServices {
#Autowired
private UserRepository userRepository;
public List<User> listAll(){
return (List<User>) userRepository.findAll();
}
Controller:
#RequestMapping("/userlist")
public String viewUserList(Model model) {
List<User> listUsers = userServices.listAll();
model.addAttribute("listUsers", listUsers);
return "userList";
}
thymleaf page:
<tbody>
<tr th:each="user : ${listUsers}">
<td th:text="${user.id}">User ID</td>
<td th:text="${user.username}">User Name</td>
<td th:text="${user.roles}">User Role</td>
<td>
</td>
</tr>
</tbody>
How to get userlist with rolename.

I am on a similar project.
'roles' is defined as a Set of Roles, so you are seeing the identifiers of that object, rather than the values.
You will need to iterate through the roles themselves if the intent is to display the list of names of roles.
Also remember, the role has a name and Id since it in itself is an entity/model, so you will want to iterate the roles and show role name, something like:
- <el th:each="role : ${user.getRoles()}"/>
- <el th:text="${role.getName()}"/>
If you are liking the Table, I would recommend a span for each role name.
There are alternatives depending on how you want it shown. You may also do this in your controller or UserDetails class depending on what the desired functionality/application or display is beyond verifying it within a thymeleaf page for users or Admins.

Related

How to store and display an SQL result where the columns do not match any of my entities

I am writing a spring boot application to perform certain jobs on a MySQL database. One of the things I am having trouble with is getting the average temperature per day from the database.
My #entity looks as follows:
#Entity
public class SensorData {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long sensorDataId;
#Column(
name = "timestamp"
)
private LocalDateTime timestamp;
#Column(
name = "temperature"
)
private Float temperature;
#Column(
name = "humidity"
)
private Float humidity;
#ManyToOne(
fetch = FetchType.LAZY,
optional = false,
cascade = CascadeType.ALL
)
#JoinColumn(
name = "department_id",
nullable = false
)
private Department department;
}
And department entity as follows. I am working with department (1)"A", (2)"B" and (3)"C".
#Entity
public class Department {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long departmentId;
#Column(
name = "department",
unique = true
)
private String department;
#OneToMany(
mappedBy = "department",
fetch = FetchType.LAZY
)
private List<SensorData> sensorData;
}
The problem I am facing is that I need to make a query that returns average temperature per day per department. In my attempts to do this I have written the following JpaRepository function:
#Query(value = "select round((dc.temperature),3) as temperature
,dc.department_id,dc.timestamp from db_uppg.sensor_data dc group by department_id,dc.timestamp",nativeQuery = true)
List<?> findTemperature();
And a controller function that returns a thymeleaf template averageTemperature.html:
#Controller
public class IndexController {
#Autowired
private SensorDataRepository sensorDataRepository;
#GetMapping("/averageHumidity")
public String avgHumidity(Model model) {
List<?> list = sensorDataRepository.findHumidity();
model.addAttribute("allHumidity", list);
return "averageHumidity";
}
}
And finally my thymeleaf template:
<table class="table table-dark table-hover">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Average Temperature</th>
<th scope="col">Date</th>
</tr>
</thead>
<tbody>
<tr th:each="humidityList : ${allHumidity}">
<th scope="row">-</th>
<td th:text="${humidityList.humidity}"></td>
<td th:text="${humidityList.datetime}"></td>
</tr>
</tbody>
</table>
My IDE warns me that it cannot resolve humidity and datetime in my thymeleaf template. I assume it's because I am using List<?>, and Java cannot understand the data this list contains?
I am not sure what other ways I can achieve displaying a result where the columns requested do not match any of my original entities.
That query returns List<Object[]> as the actual type, so use that instead of ?. Then in your service layer (or the controller if you don't have a service layer), convert the rows to suitable DTOs with those fields (humidity and datetime).
The resulting code could look something like
List<HumidityDTO> list = sensorDataRepository.findHumidity().stream()
.map(h -> new (HumidityDTO(h)))
.collect(Collectors.toList());
If HumidityDTO has a constructor taking an Object[] parameter.

Binding checkedboxes as objects to be added to a <List> as a field of parent object, to be passed to database

I am trying to make a Recipe Builder form using Thymeleaf.
The functionality I am trying to implement involves adding a List of selected objects (ingredients) to the bound recipe.
Here is a snippet of the Form from the Template file:
<form action="#" th:action="#{/recipes/userRecipes/new/save}" th:object="${userRecipe}"
method="post">
...
<td>Ingredients:</td>
<td>
<ul>
<li th:each="ingredient : ${allIngredients}">
<input type = "checkbox" th:name="sel_ingredients" th:value="${ingredient.id}" />
<label th:text="${ingredient.name}">Ingredient</label>
</li>
</ul>
</td>
</tr>
...
</table>
</form>
Here is a snippet from my controller:
#RequestMapping("/userRecipes/new")
public String createNewUserRecipe(Model model){
UserRecipe userRecipe = new UserRecipe();
model.addAttribute("userRecipe", userRecipe);
return "new-recipe";
}
#RequestMapping(value = "/userRecipes/new/save", method = RequestMethod.POST)
public String saveRecipe(
#ModelAttribute("userRecipe") UserRecipe userRecipe,
#RequestParam(value = "sel_ingredients", required = false) int[] sel_ingredients,
BindingResult bindingResult, Model model){
for(int i : sel_ingredients){
Ingredient ing = new Ingredient();
ing = ingredientRepo.getOne((long)i);
userRecipe.addIngredient(ing);
}
userRecipeRepo.save(userRecipe);
return "redirect:../";
}
Along with a #ModelAttribute to set Ingredients:
#ModelAttribute
public void populateIngredients(Model model){
List<Ingredient> ingredientList = this.ingredientRepo.findAll();
//Iterator<Ingredient> itr = ingredientList.iterator();
model.addAttribute("allIngredients", ingredientList);
}
Entities:
#Entity
#Table(name = "user_recipes")
public class UserRecipe extends AuditModel{
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Size(max = 100)
#Column(unique = true)
private String title;
#NotNull
#Size(max = 250)
private String description;
#ManyToMany
#JoinTable(
name = "used_ingred",
joinColumns = #JoinColumn(name = "user_recipe_id"),
inverseJoinColumns = #JoinColumn(name = "ingredientid")
)
private List<Ingredient> ingredients;
public void addIngredient(Ingredient i){
this.ingredients.add(i);
}
#NotNull
#Lob
private String preparation;
#Entity
#Table(name = "ingredients_master")
public class Ingredient extends AuditModel{
#Column(name = "ingredient")
private String name;
#Column(name="description")
private String description;
#Id
#GeneratedValue
private long id;
// public Ingredient(String n, String d){
// this.setName(n);
// this.setDescription(d);
// }
// public Ingredient(int id, String n, String d){
// this.setId(id);
// this.setName(n);
// this.setDescription(d);
// }
#ManyToMany(mappedBy = "ingredients")
Set<UserRecipe> recipes;
#ManyToMany
Set<Tag> tags;
Originally, I tried to grab the Ingredient objects directly, but couldn't figure out how to do that, so instead opted to grab the ids, and then reference them from the Repository; however,
I get the following error when I click the save button:
There was an unexpected error (type=Internal Server Error, status=500).
No message available
java.lang.NullPointerException
at com.donovanuy.mixmix.entities.UserRecipe.addIngredient(UserRecipe.java:85)
at com.donovanuy.mixmix.controllers.RecipeController.saveRecipe(RecipeController.java:103)
If possible, I'd like to be able to grab the Ingredient object directly, and add it to the List field of my userRecipe.
I am considering making a separate RecipeMakerForm, that I can instead pass into a service. Something like:
public class RecipeMakerForm{
String newTitle;
Long[] ingredientIds;
Long[] tagIds;
and the service would like like:
public class RecipeMaker{
void makeRecipe(RecipeMakerForm form){
Recipe r = new Recipe(form.getNewTitle());
if (ingredientIds != null){
for (Long id : ingredientIds){
r.addIngredient(ingredientRepo.getOne(l));
}
//etc
recipeRepo.save(r);
}
Even still, I suspect my errors have something to do with the way Thymeleaf is passing the model data back to the controller, so my new RecipeMaker & RecipeMakerForm methods wouldn't work. I'm still new to using Thymeleaf and working with Spring.data, so I expect my solution to be somewhere in my Thymeleaf or Controller methods.

Compare enum with list Thymeleaf

I have an enum inserted in an entity, with some default values. I want to compare this with the enums assigned to the entity.
I tried looking for the enum string in the list, but I don't get a result
public class Role{
#NotEmpty
#Enumerated(value = EnumType.STRING)
private Authority authority;
public static enum Authority {
ROLE_ADMIN,
ROLE_USER
}
}
public class UserCheck implements UserDetails {
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
}
the enum is traversed and compared to the list
<div class="form-group">
<label for="exampleSelectStore">Roles</label> <select class="form-control" id="exampleSelectStore" multiple="multiple">
<option th:each="authority : ${T(cl.tricotcorp.app.checklist.models.entity.Role.Authority).values()}" th:text="${authority}" th:value="${authority}" th:selected="${#lists.contains(userCheck.getRoles(), authority)}"> </select>
</div>
the expected result is to mark the matches as "checked"
getRoles() returns a List<Role>, and authority is an Authority, so you're basically asking if any Role.equals(Authority), which by definition is always false.
One way to fix it, so its easy to use, is to add a helper method to UserCheck:
public boolean hasAuthority(Authority authority) {
return this.roles.stream().anyMatch(r -> r.getAuthority() == authority);
}
Then your Thymeleaf code would be:
<option ... th:selected="${userCheck.hasAuthority(authority)}">

Select Java Object from Spring Form drop down menu

Is it possible to select whole Java Object from Spring Form's drop down menu? I used LinkedHashMap, but it doesn't work.
I have relation Many To One between table Agent and table Roles (every Agent has one role eg. user, admin). I use hibernate so I have to operate on Object, not Id's from database. My problem is that I want to create drop down menu with list of all roles from my database and when I pick one element, this Object goes to my Agent Object and save in my database.
I have List with my Roles Objects
List<Roles> rolesList = rolesService.getAllRoles();
Which comes from this:
public List<Roles> getAllRoles() {
return session().createQuery("from Roles").list();
}
and I tried something like this:
In my AgentController:
#RequestMapping("/createagent")
public String createAgent(Model model) {
Agent agent = new Agent();
List<Roles> rolesList = rolesService.getAllRoles();
Map<Roles, String> rolesMap = new LinkedHashMap<Roles,String>();
for (int i=0; i<rolesList.size(); i++){
rolesMap.put(rolesList.get(i), rolesList.get(i).getRole());
}
model.addAttribute("rolesMap", rolesMap);
model.addAttribute("agent", agent);
return "createagent";
}
In my jsp file:
<tr><td>Roles:</td><td>
<sf:select path="roles" multiple="false">
<sf:options items="${rolesMap}"></sf:options>
</sf:select>
</td></tr>
My Roles Object:
#Entity
#Table(name = "roles")
public class Roles {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "roles_seq_gen")
#SequenceGenerator(name = "roles_seq_gen", sequenceName = "roles_id_seq")
#Column(name = "id")
private long id;
#Column(name = "role")
private String role;
It shows excactly what I want but when I click position in my drop down menu and submit it, my form don't save my Object properly. It nested it ... I don't know how to subscribe this, maybe my toString() function output clear little bit.
Agent [id=0, username=TestUsername, password=TestPassword, roles=Roles[id=0, roles=Roles[id=0, roles=user]] ...
My Agent Object:
#Entity
#Table(name="agent")
public class Agent {
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="agent_seq_gen")
#SequenceGenerator(name="agent_seq_gen", sequenceName="agent_id_seq")
#Column(name="id")
private long id;
#Column(name="username")
private String username;
#Column(name="password")
private String password;
#ManyToOne
#JoinColumn(name="roles_id")
private Roles roles;
My jUnit test runs fine, it's something wrong with my Spring Form or with my controllers... I don't know.
I would suggest to use ModelAttribute and reference the form object to the said properties, like, agent.getRoles().
createAgent(#ModelAttribute("agent") Agent agent) should work in what you're trying to accomplish.

How to access attribute of attribute of object in thymeleaf?

Say I want to access an object that is called post. Post has a instance variable called Category of type Category.
In the Java controller class
model.addAttribute("posts", postRepository.findPostsByUser(user));
In the thymeleaf html file I have
<tr data-th-each="post : ${posts}">
I am wondering if it is it possible to access the below?
{post.category.name}
For clarification I have included the java classes below. Each instance has associated setters and getters.
#Entity
public class Post {
#ManyToOne
#JoinColumn(name = "category_id")
private Category category;
#Entity
public class Category {
private String name;
you have to make a condition:
<tr th:each="post:${posts}">
<td th:text="${post.category}!=null? ${post.category.name}:''"></td>
</tr>
:)
I think you need to change your entity code
#Entity
public class Post {
private Category category;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "category_id", nullable = false)
public Category getCategory () {
return this.category;
}
public void setCategory (Category category ) {
this.category = category ;
}
}
you need implement thymeleaf html page as per following
<tr th:each="post : ${posts}">
<td> <span th:utext="{post.category.name}" /></td>
</tr>
Hope its help to you!

Categories