Equivalent Spring custom Collection property editor when using JSF - java

I would like to know how to use Converters in Java Server Faces similar to Spring collection property editor
Suppose the following model
public class Group {
private String name;
List<User> users = new ArrayList<User>();
// getter's and setter's
}
And equivalent form
<form ...>
<h1>Group form</h1>
<label for="name">Enter name</label>
<input type="text" name="name"/>
<label for="users">Select users</label>
<!--value attribute stores userId-->
<input type="checkbox" value="1" name="users"/> User 1
<input type="checkbox" value="2" name="users"/> User 2
<input type="checkbox" value="3" name="users"/> User 3
</form>
If i use Spring to bind users property in Group class, i call
binder.registerCustomEditor(List.class, new CustomCollectionEditor() {
protected Object convertElement(Object userId) {
return new User((Integer) userId);
}
});
How do i get the same effect when using Java Server Faces ?
regards,

For that you can implement javax.faces.convert.Converter. Its API is pretty self-explaining: write the getAsString() method accordingly that it returns the String representation of the Object, which can be under each the technical ID such as userId. Then, to get JSF set the right Object during apply request parameters phase, you need to implement getAsObject() that it returns the Object associated with the given String value.
Basically:
public class UserConverter implements Converter {
private UserDAO userDAO = SomeDAOManager.getUserDAO();
public String getAsString(FacesContext context, UIComponent component, Object value) {
return String.valueOf(((User) value).getId());
}
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return userDAO.find(Long.valueOf(value));
}
}
Register it in faces-config.xml as follows:
<converter>
<converter-for-class>com.example.model.User</converter-for-class>
<converter-class>com.example.converter.UserConverter</converter-class>
</converter>
That should be it. For more insights you may this or this article useful.

Related

How can I give a List of objects as parameter with MockMvcBuilder

In my Spring Boot project, i have a controller called AdminGameController which methods I want to test using Springs MockMvcBuilder. This works fine for methods which handles the GET request, but for the POST methods, a Game object is needed as parameter, see the handler method:
#RequestMapping(value = "/admin/game/save", method = RequestMethod.POST)
public String saveOrUpdate(#Valid Game game,
BindingResult bindingResult,
Model model,
RedirectAttributes redirectAttributes) {
if (bindingResult.hasErrors()){
model.addAttribute("message","Please fill in all necessary fields");
addAttributes(model);
return (game.getId()==0) ?
"admin/games/newGameForm" : "admin/games/editGameForm";
}
if(game.getTeams().size()>0 &&
game.getTeams().get(0)!=null &&
game.getTeams().get(1)!=null &&
(game.getTeams().get(0).getId() ==
game.getTeams().get(1).getId())) {
model.addAttribute("message", "Teams cannot be the same. Try again");
addAttributes(model);
return (game.getId()==0) ?
"admin/games/newGameForm" : "admin/games/editGameForm";
}
if(game.getDate()!=null && game.getDate().before(new Date())) {
model.addAttribute("message", "Date must be in the future. Try again");
addAttributes(model);
return (game.getId()==0) ?
"admin/games/newGameForm" : "admin/games/editGameForm";
}
redirectAttributes.addFlashAttribute("message",
(game.getId()==0) ?
"New game was created succesfully" : "Game was updated succesfully");
gameService.save(game);
return "redirect:/admin/games/page/1/date/asc";
}
To test this method, i wrote the following test:
#Test
public void saveNewGame() throws Exception{
mockMvc.perform(post("/admin/game/save")
.param("date", "01/10/2018")
.param("teams", "1"))
.andExpect(status().is3xxRedirection())
.andExpect(view().name("redirect:/admin/games/page/1/date/asc"))
.andExpect(
MockMvcResultMatchers.
flash().
attribute("message", "New game was created succesfully"));
ArgumentCaptor<Game> boundGame = ArgumentCaptor.forClass(Game.class);
verify(gameService).save(boundGame.capture());
Assert.assertEquals(DataLoader.parseDate("01/10/2018"),
boundGame.getValue().getDate());
}
Spring automatically creates this Game object and maps the values which i add to the MockMvcBuilder as parameters with the fields of the game object. This all works fine with primitive data types and the Data object i used above (the String value is perfectly transformed into a Date object because i annotated the Date attribute with a pattern, see the code below of the Game bean:
#Entity
public class Game {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#NotNull
#ManyToMany (fetch = FetchType.EAGER)
private List<Team> teams = new ArrayList<>();
private Integer scoreTeamA;
private Integer scoreTeamB;
#ManyToOne
private Location location;
#ManyToOne
private Competition competition;
#NotNull
#DateTimeFormat(pattern="dd/MM/yyyy")
private Date date;
public Game(){}
//getters and setters and more
}
But when a want to give a List of team objects, which is also attribute of the game objects, I get a BindingResultError which says:
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'game' on field 'teams': rejected value [1];
codes
[typeMismatch.game.teams,typeMismatch.teams,typeMismatch.java.util.List,typeMismatch];
arguments
[org.springframework.context.support.DefaultMessageSourceResolvable:
codes [game.teams,teams]; arguments []; default message [teams]];
default message [Failed to convert property value of type
'java.lang.String' to required type 'java.util.List' for property
'teams'; nested exception is java.lang.IllegalStateException: Cannot
convert value of type 'java.lang.String' to required type
'com.davidstranders.sportclub.model.Team' for property 'teams[0]': no
matching editors or conversion strategy found]
Above i tried to set a teamId as value for the teams object because this is also what happens when a user selects a team when he creates a game object, see the template (uses Thymeleaf):
<div th:class="form-group" th:classappend="${#fields.hasErrors('teams')}? 'has-error'">
<label class="col-md-3 control-label">
Teams <span class="required">*</span>
</label>
<div class="col-md-9">
<div class="col-md-5">
<select class="form-control" th:field="*{teams}">
<option value="">Select team</option>
<option th:each="team : ${teams}"
th:value="${team.id}"
th:text="${team.name}">teams
</option>
</select>
<span th:if="${#fields.hasErrors('teams')}"
th:errors="*{teams}"
th:class="help-block">Team Errors</span>
</div>
<div class="col-md-1"><label>vs</label></div>
<div class="col-md-5">
<select class="form-control" th:field="*{teams}">
<option value="">Select team</option>
<option th:each="team : ${teams}"
th:value="${team.id}"
th:text="${team.name}">teams
</option>
</select>
<span th:if="${#fields.hasErrors('teams')}"
th:errors="*{teams}"
th:class="help-block">Team Errors</span>
</div>
</div>
</div>
Have anyone any idea how to deal with this? I tried to give a List with teams as String, or team instances as String, but this didn't work.
Thanks for your help!!

How do I pass the dropdown select value to a button click in the controller and search against the value in data base?

here is the controller
#RequestMapping(value = "/submitrule", method = RequestMethod.POST)
public String addruleSerch(#ModelAttribute("SpringWeb") Rule obj2, ModelMap model) {
model.addAttribute("Select", obj2.getId());
System.out.println("********" + obj2.getId());
ruleApi.getRule(obj2.getId());
model.addAttribute("listrule", ruleApi.getRule(obj2.getId()));
return "redirect:/hello";
}
here is the html....
<form action="/CommissionTool/submitrule" method="post">
<table>
<tr>
<td><select name="Select"><c:forEach items="${listRules}" var="rule">
<option value="${rule.id}">
<c:out value="${rule.id}" />
</option>
</c:forEach>
</select>
</td>
<td><input type="submit" onClick="addRow('in_tbl_name')" VALUE="Add New"></td>
</tr>
</table>
</form>
How could i fix this.. please help me
Thanks in Advance...
Well you need to do several changes in your code, but is pretty near.
You need to send the object you want to use as modelAttribute to the view the first time.
In your html you need to say to the form which is the object to render, your model attribute
Create a POST method in your controller to retrieve the object
Lets put all together in this this example. I have a class called RuleForm, which contains an attribute of type Rule.
public class RuleForm {
...
#Getter #Setter //here use lombok, but you could create your getters-setters methods
private Rule rule;
...
}
Now in the controller, into the GET method, we set the view resolver(JSP) and the object we will send to there. In this case an object of type FormRule
#RequestMapping(value = "/submitrule", method = RequestMethod.GET)
public ModelAndView addruleSerch() {
ModelAndView model = new ModelAndView("yourView");
//here you choose the name you will use in your view, is up to you the name to choose
model.addObject("formRule", new FormRule());
return model;
}
Now we need to pick up that object we sent to the view and use it into our form tag.
<form action="/CommissionTool/submitrule" method="post" model="formRule">
...
<select name="rule.id"><c:forEach items="${listRules}" var="rule">
<option value="${rule.id}">
<c:out value="${rule.id}" />
</option>
</c:forEach>
</select>
In this point when we send the form to the Controller, we will send the RuleForm object with a value into rule.id object, then in the controller we have to get that id value and add out business logic.
#RequestMapping(value = "/submitrule", method = RequestMethod.POST)
public String addruleSerch(#ModelAttribute RuleForm ruleForm) {
//Here you will have access to your object
ruleForm.getRule().getId();// rule selected in the form
... your business logic
return "redirect:/someUrl";
}

How to use Model object returned from spring mvc in jsp

Hi I am new to Spring mvc. I am using ModelAndViewas return object in one of my controllers.
I am not understanding how to access the Model object returned to the jsp for display.
This is my code :
#Controller
public class GetSongServlet extends HttpServlet {
#RequestMapping(value = "/getSong", method = RequestMethod.GET)
public ModelAndView getSong(#RequestParam(value = "songTitle", required = false) String
title) {
MusicPlayerService service = MusicPlayerServiceImpl2.getInstance();
try {
Song song = service.getSong(title);
System.out.println(song.getSongId());
// request.setAttribute("song", song);
/*
* RequestDispatcher requestDispatcher = request
* .getRequestDispatcher("viewSong");
* requestDispatcher.forward(request, response);
*/
return new ModelAndView("viewsong", "song", song);
}
}
<input type="text" class="form-control focusedInput" id="title"
value=<%="${song.title}"%> name="title" disabled />
<input type="text" class="form-control focusedInput" id="album"
value=<%= "${song.album.albumName}"%> name="album" disabled />
<input type="text" class="form-control focusedInput" id="artist"
value=<%= "${song.artist}"%> name="artist" disabled />.........
public class Song{
private int songId;
private Album album;
private String title;
private int rating;
private String artist;
private String composer;
private Genre genre;
}
You don't access the model through the JSP. Model (and all corresponding types: ModelAndView, ModelMap, etc.) is a Spring abstraction around HttpServletRequest attributes.
When Spring has finished invoking your handler method, it will move all model attributes it has collected to the HttpServletRequest attributes.
You can access these in JSP with the EL expression
${some.attribute}
but don't try to put EL within a scriptlet like you do here
<%= "${song.artist}"%>
In order to your JSP page be able to display the property of your object you need to implement a public getter of it.
In your case, your class Song has an attribute title but as it's a private attribute you gonna need a public method called getTitle() returning the title attribute. Your JSP will be able to render title if you write something like that:
<input type="text" value="${song.title}" name="title" disabled />

Spring: mapping string and numbers with RequestMapping

I have the following form in Spring:
<form:form method="post" action="addprice.html" commandName="addprice">
<form:input path="name" />
<form:input path="price" />
<input type="submit" value="<spring:message code="Add price"/>"/>
</form:form>
And I need to pass the parameters to the following function:
#RequestMapping("/addprice")
public String addPrice(
// WHAT I NEED TO WRITE HERE?
)
{
// function code
}
What I need to write between parentesys in the previous function in order to retrieve "name" and "price"?
I tried using #ModelAttribute but it seems to work only with entities and I don't have a unique entity in this case but just two simple parameters.
Use the #RequestParam annotation :
#RequestMapping("/addprice")
public String addPrice(#RequestParam String name, #RequestParam double price)
{
// function code
}

list of string not displayed

I use spring 3. I'm trying to display a value of an object in a jsp.
public class UserForm implements Serializable {
private List<String> values;
private String date;
...
}
Here is my controller:
#Controller
#RequestMapping("/user.htm")
public class UserController {
#Autowired
private IUserService userService;
#RequestMapping(method = RequestMethod.GET)
public String userStat(Model model) {
UserForm stat = userService.populateStatistique();
stat.setDate("today");
model.addAttribute("statistiqueForm", stat);
return "userStat";
}
}
Here is my jsp:
<form:form commandName="userForm" name="userForm">
Date: <form:input path="date"></form:input>
<br/>
Expediteur:
<form:select path="values" items="${values}" />
<br/>
<input type="submit" value="create" />
</form:form>
In the jsp I can see the today value for the date field, but the listbox is empty.
any idea?
thanks
Well, use addAttribute("values", list) if you want it accessible in the jsp. You are currently not setting it and so it is empty.
If that list is contained in the statistiqueForm object, then use items="${statistiqueForm.values}".
You're correctly passing the form object to the jsp page. In that page you have a list box, which has a list of potential values and a list of selected values. The object form contains the list of selected values, but you should also setup the list with all potential values. In fact you reference ${values} in the jsp, but you don't pass it to the jsp. You should add this code to your controller:
model.addAttribute("values", potentialValueList);
I also suggest you to change the name of that list to avoid confusion, so it will be easy to understand the difference from selected values to potential values.

Categories

Resources