No binding res for object w/ thymeleaf - thymeleaf

Given:
reactive chain with controller methods
#PostMapping("/add")
public Mono<String> addSkill(#ModelAttribute Skill skil) {
log.info("skill "+ skill.getName() + " has been added!");
return service.add(skill)
.then(Mono.just(TEMPLATE));
#GetMapping("")
public Mono<String> getAll(Model model) {
IReactiveDataDriverContextVariable driverContextVariable = new ReactiveDataDriverContextVariable(service.findAll(), 100);
model.addAttribute("skills", driverContextVariable);
return Mono.just(TEMPLATE);}
form:
<div class="row">
<div id="title">
<h1>Reactive java skills</h1>
</div>
<table id="allSkills" class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Priority</th>
<th>Skill Group</th>
</tr>
</thead>
<tbody>
<tr class="skills" data-th-each="skill : ${skills}">
<td>[[${skill.name}]]</td>
<td>[[${skill.level}]]</td>
<td>[[${skill.priority}]]</td>
<td>[[${skill.skillGroupName}]]</td>
</tr>
</tbody>
</table>
</div>
<div>
<h4>add skill</h4>
<form th:action="#{/skill/add}" th:object="${skill}" method="post">
<input type="text" th:field="*{skill.name}" placeholder="choose skill name"/>
<input type="text" th:field="*{skill.level}" placeholder="choose skill level"/>
<input type="text" th:field="*{skill.priority}" placeholder="choose skill priority"/>
<input type="text" th:field="*{skill.skillGroupName}" placeholder="choose skill priority"/>
<input type="submit" value="Submit" /> <input type="reset" value="Reset" />
</form>
</div>
My goal is simple:to add a new entity by submitting form and render the same
html which shows all entities. As far as I understood concept of Reactive Thyme, here is no #PathVariable due to blocking code behind it, so I use #ModelAttribute to pass params for new Skill. However, when I request base path for the controller, it renders all the skills and throws :
java.lang.IllegalStateException: Neither BindingResult nor plain
target object for bean name 'skill' available as request attribute
I have no glue how to make thymeleaf ignore ${skill} param when I render the page and use it only on submitting form.
PS - I also haven't found official docs for reactive thymeleaf, if anyone shares link it would be awesome.

Basically, I am supposed to fullfil all attributes in reactive way. So, the problem was with my getAll() method, which should be capable of filling all thymeleaf object claimed in template html. The working version of method I put for better memorizing reason:
#GetMapping("")
public Mono<String> getAll(Model model) {
log.info("no attr =- no future");
return Mono.just(model)
.flatMap(m -> {
m.addAttribute("skills", new ReactiveDataDriverContextVariable(service.findAll(), 10));
m.addAttribute("skill", new Skill());
return Mono.just(TEMPLATE);
})
.doOnNext(sink -> System.out.println(sink));

Related

Pass one of many objects from view to controller

In an ASP.Net Core web app, I'm passing a List<Parameter> to a view via ViewBag.Parameters. The view also has a SelectParameterViewModel that consists of one property only, an int ParameterId. The objects are then displayed in a table like so (I skipped straight to tbody as the view works fine from a cosmetic perspective):
#model WebApp.Models.ReportViewModels.SelectParameterViewModel
[...]
<tbody>
#foreach (var item in ViewBag.Parameters)
{
<tr>
<td class="col-xs-1">
<form asp-controller="Report" asp-action="Launch">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input asp-for="#Model.ParameterId" type="hidden" value="#item.Id" />
<input type="submit" class="btn btn-primary btn-sm" value="Select" />
</form>
</td>
<td class="col-xs-8">#item.Description</td>
<td class="col-xs-3">
<a asp-action="Edit" asp-route-id="#item.Id">Edit</a> |
<a asp-action="Details" asp-route-id="#item.Id">Details</a> |
<a asp-action="Delete" asp-route-id="#item.Id">Delete</a>
</td>
</tr>
}
</tbody>
I would like the user to click on the button of the chosen table-row and submit either that row's Parameter (preferred) or the Parameter's Id, like I tried to do in this case. I would then do the same with the <a> tags on the third column. The point is that I don't want the user to simply type /Report/Launch/id and run the report, as each user would have its own sets of parameters and should not be allowed to use any of the others', and the ViewBag only contains the list of its Parameter. I can change the view model and/or the receiving controller's argument depending on the solution, both would work. I tried a few versions of the above html, but none would work, while the above returns ParameterId with value 0.
I couldn't find a similar scenario in other SO questions. There were some solutions that involved JavaScript and, correct me if I'm wrong, but that would still show the ParameterId value in the webpage source. While that would be sort-of-ok in this specific case, I have other cases where I definitely would not want that to happen.
What would be an elegant solution to achieve this? Thank you!

Dojo - Upload two files in one Form

I use Dojo and want to send two files and one String to a REST Service. The HTML for that is the following:
//...
<script>
dojo.require("dijit.form.Button");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.CheckBox");
dojo.require("dojox.form.Uploader");
dojo.require("dojox.embed.Flash");
if(dojox.embed.Flash.available){
dojo.require("dojox.form.uploader.plugins.Flash");
}else{
dojo.require("dojox.form.uploader.plugins.IFrame");
}
</script>
//..
<form action="http://localhost:8080/service" enctype="multipart/form-data" method="POST" name="inputDataForm" id="inputDataForm">
<table border="1" cellpadding="1" cellspacing="1" height="88" width="925">
<tbody>
<tr>
<td>Dataset1</td>
<td><input name="train" type="file" value="Browse" data-dojo-type="dojox/form/Uploader"/></td>
</tr>
<tr>
<td>Dataset2</td>
<td><input name="test" type="file" value="Browse" data-dojo-type="dojox/form/Uploader"/></td>
</tr>
<tr>
<td>Number of Customers</td>
<td><input name="numberCustomers" size="40" type="text" data-dojo-type="dijit/form/TextBox" /></td>
</tr>
</tbody>
</table>
<p><input name="runButton" type="submit" value="Run" data-dojo-type="dijit/form/Button" id="submitButton" /></p>
</form>
However: If I press the submit button, I can see via Firebug that there are sent TWO POST-Requests. One with the first file and the "Number of Customers" field and one with the second file and the "Number of Customers" field. However, my REST Service wants to have both files and the "Number of Customers" fields in one POST Request. How can i do that? What am I doing wrong?
Thanks a lot in advance
Natan

Spring Security UI - Cannot open register/forgot password page

I have put the ":spring-security-ui:1.0-RC1" into my BuildConfig and compiled it then I created the auth, register and securityInfo views and controller by using the spring ui command. I also put a user in my db to test it.
However, when I tested it I just get to the login page, after login in I get to the grails page back. However the button Register New User and Forgotten Passoword do not work, I only get redirected to the login page! Even though the file gets correctly rendered to *.html.
This is how the view structure looks like:
My ÙRLMappings look like that:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?(.${format})?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
}
}
I would appreciate your answer on my problem!
UPDATE
This is my auth.gsp:
<html>
<head>
<title><g:message code='spring.security.ui.login.title'/></title>
<meta name='layout' content='register'/>
</head>
<body>
<p/>
<div class="login s2ui_center ui-corner-all" style='text-align:center;'>
<div class="login-inner">
<form action='${postUrl}' method='POST' id="loginForm" name="loginForm" autocomplete='off'>
<div class="sign-in">
<h1><g:message code='spring.security.ui.login.signin'/></h1>
<table>
<tr>
<td><label for="username"><g:message code='spring.security.ui.login.username'/></label></td>
<td><input name="j_username" id="username" size="20" /></td>
</tr>
<tr>
<td><label for="password"><g:message code='spring.security.ui.login.password'/></label></td>
<td><input type="password" name="j_password" id="password" size="20" /></td>
</tr>
<tr>
<td colspan='2'>
<input type="checkbox" class="checkbox" name="${rememberMeParameter}" id="remember_me" checked="checked" />
<label for='remember_me'><g:message code='spring.security.ui.login.rememberme'/></label> |
<span class="forgot-link">
<g:link controller='register' action='forgotPassword'><g:message code='spring.security.ui.login.forgotPassword'/></g:link>
</span>
</td>
</tr>
<tr>
<td colspan='2'>
<s2ui:linkButton elementId='register' controller='register' messageCode='spring.security.ui.login.register'/>
<s2ui:submitButton elementId='loginButton' form='loginForm' messageCode='spring.security.ui.login.login'/>
</td>
</tr>
</table>
</div>
</form>
</div>
</div>
<script>
$(document).ready(function() {
$('#username').focus();
});
<s2ui:initCheckboxes/>
</script>
</body>
</html>
You probably need to add the following two rules in your grails.plugin.springsecurity.controllerAnnotations.staticRules. It is in the Config.groovy file.
'/register/index': ['permitAll'],
'/register/forgotPassword': ['permitAll'],
Otherwise, the spring security will bump your request back to the login/auth screen.
What about your controllers ?? I hear no mention of them you including them in your config file. Define your success handler and define a controller for successful login.
grails.plugin.springsecurity.successHandler.defaultTargetUrl = '/homePage'
Then if you already are being logged in then set access into the controllers using security annotations or using InterceptMapURL.
Looking at your problem you just haven't configured the security plugin well that's it. Well look at some other spring security implementation for grails in github, I think that will help you.
Simply add anonymous role to your RegisterController
import grails.plugin.springsecurity.annotation.Secured;
#Secured(['ROLE_ANONYMOUS'])
class RegisterController extends grails.plugin.springsecurity.ui.RegisterController {
}

CodeIgnitier CSRF protection how submit form which is loaded via jquery tabs

I'm working on some backend project and want to load form via jQueryUI tabs
<div id="parameters_tabs" style="width:920px;">
<ul>
<li><?=$this->lang->line('tab_name')?></li>
</ul>
</div>
in response I produce few forms as in example below:
<?
for ($i = 0; $i < count($groups); $i++)
{
?>
<form id="group_form<?=$i?>" method="POST" action="<?=base_url()?>update_group">
<input type="hidden" name="<?=$this->config->item('csrf_token_name')?>" value="<?=$token?>" />
<input type="hidden" name="id" value="<?=$groups[$i]['id']?>" />
<tr>
<td>
<input type="text" value="<?=$groups[$i]['name']?>" name="name" />
</td>
<td>
<input type="text" value="<?=$groups[$i]['short_name']?>" name="short_name" />
</td>
<td>
<textarea cols="80" rows="4" name="desc"><?=$mgroups[$i]['desc']?></textarea>
</td>
<td style="width: 30px">
<a class="save" onclick="$('#group_form<?=$i?>').submit();"><?=$this->lang->line('save')?></a>
</td>
</tr>
</form>
<?
}
?>
when clicking on "save" I got standard error about CSRF protection:
"An Error Was Encountered
The action you have requested is not allowed."
Can anyone help me and tell where I made mistake? Of course in source I see proper csrf_token_name.
This article helped me when I was experiencing the same issue. Using the built-in form helper form_open() function might also help solve the problem (as it generates the hidden CSRF field for you).

Grails dynamic scaffold with hasMany: is it a bug or am I misconfiguring?

I'm a Grails noob and running into something that seems to be a bug, but it is entirely possible I'm not configuring everything correctly.
I've got two simple Domain Classes:
class Player {
String firstName
String lastName
static constraints = {
firstName(blank:false)
lastName(blank:false)
}
String toString() { lastName + ", " + firstName }
}
and
class Team {
String mascot;
static hasMany = [players:Player]
static constraints = {
mascot(blank:false)
}
}
I have controllers for both that do nothing beyond dynamic scaffold these two Domain Classes.
But even when I have a list of Players in my DB, I don't get a multi-select box for them when creating a new Team.
However, the multi-select shows up when I go to edit a Team
Is this a bug in the dynamic scaffolding for new items, do I misunderstand how this is supposed to work, or is there something else I need to declare here?
Any help is hugely appreciated! I've got screenshots that StackOverflow won't let me add because of my newness, but I'd be happy to show them another way if that'll help.
I finally figured this out and wanted to pass on what I did just in case someone else runs into it.
When I generated the views for Team, the form block in edit.gsp looks like this:
<input type="hidden" name="id" value="${teamInstance?.id}" />
<input type="hidden" name="version" value="${teamInstance?.version}" />
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="mascot">Mascot:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:teamInstance,field:'mascot','errors')}">
<input type="text" id="mascot" name="mascot" value="${fieldValue(bean:teamInstance,field:'mascot')}"/>
</td>
</tr>
<tr class="prop">
<td valign="top" class="name">
<label for="players">Players:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:teamInstance,field:'players','errors')}">
<g:select name="players"
from="${Player.list()}"
size="5" multiple="yes" optionKey="id"
value="${teamInstance?.players}" />
</td>
</tr>
</tbody>
</table>
</div>
<div class="buttons">
<span class="button"><g:actionSubmit class="save" value="Update" /></span>
<span class="button"><g:actionSubmit class="delete" onclick="return confirm('Are you sure?');" value="Delete" /></span>
</div>
</g:form>
but the form block in create.gsp looks like this:
<g:form action="save" method="post" >
<div class="dialog">
<table>
<tbody>
<tr class="prop">
<td valign="top" class="name">
<label for="mascot">Mascot:</label>
</td>
<td valign="top" class="value ${hasErrors(bean:teamInstance,field:'mascot','errors')}">
<input type="text" id="mascot" name="mascot" value="${fieldValue(bean:teamInstance,field:'mascot')}"/>
</td>
</tr>
</tbody>
</table>
</div>
<div class="buttons">
<span class="button"><input class="save" type="submit" value="Create" /></span>
</div>
</g:form>
In other words, for this corner case, the default Create view omits the widget to properly display the multi-select list. When I did a copy and paste of the missing code, the dynamically scaffolded controller picked it up and persisted it as expected. So, it's definitely a bug in the view generation code.
Yes, the default scaffolding puts a parent selector in the child class' create/edit page.
I'm guessing it was just easier for them this way. It shouldn't be a multi-select though, just a pull-down single-select, as it's a One-to-Many.
As you've explained you wanted more of a Many-to-Many relationship, you might try adding:
static hasMany = [teams:Team]
to your Player class. I've found that Grails does better with bi-directional relationships. It's also useful to have when building search queries, and shouldn't require more than the one relationship table you'd already need.
If you're using Grails pre-v1.1, Many-to-Many relationships aren't directly supported, so even adding the static hasMany above won't be the complete solution, as you'll need to manage adding to the other list when you add to one direction. I haven't used v1.1 yet, so I can't talk about what is needed to specify the Many-to-Many in it.
I encountered the same problem using current version (v1.3.4) of Grails. Had to manually modify the create.gsp

Resources