I am new to the Java Play Framework and I'm trying to get the authentication to work. So I am following this tutorial: https://www.playframework.com/documentation/2.1.0/JavaGuide4
Here is my code:
public static Result authenticate()
{
Form<Login> loginForm = form(Login.class).bindFromRequest();
return ok(loginForm.toString());
}
public static class Login
{
public String email;
public String password;
public String validate()
{
return "VALIDATE "+email+password;
}
}
In the method autheticate() I can see the submitted values of the form, but the method validate() in the Login class does not see them (the variables are always null).. The output of loginForm.toString() contains:
Form(of=class controllers.Application$Login, data={email=asdf#asdf, password=asdf}, value=None, errors={=[ValidationError(,[VALIDATE nullnull],[])]})
As you can see, the data is received.. But in the validate method the data suddenly is equal to null. So how do I fix this?
You don't mention how you are calling validate() however I think this might do the trick, do something along the lines of:
public static Result authenticate() {
Form<Login> form = form(Login.class).bindFromRequest();
// handle errors
if (!form.hasErrors()) {
Login login = form.get();
Logger.debug(login.validate());
} else {
// bad request
}
}
This works for me.
Method validate in your model should return null if you think that validation has passed, otherwise you should return error message text. Then you need to check form if it contains error by "hasGlobalError" method. globalError is filled when validate() method returns String instead of null. But in your case you should use some model field annotations - https://www.playframework.com/documentation/2.3.x/api/java/play/data/validation/Constraints.html.
If you want to check if form fails on those - then you use "hasErrors" method.
public static class Login {
#Constraints.Email
public String email;
#Constraints.MinLength(value = 6)
public String password;
}
Such model will check if provided emails is really email and if password is longer or equal 6 characters.
ps. Do not use toString on template, you should use render()
Related
I'm using Struts2 2.5.20 and have written a file upload action that almost works. I can see in the debugger that setReport(), setReportContentType() and setReportFileName() are being called and the parameter values are correct. However, the execute() method is never invoked. I tried following the call stack to see where it should have been called, but there's just layer after layer of interceptors that I can't find the bottom.
Does anyone know what the reason for execute() might be?
public class ImportReportAction extends CampaignerActionSupport implements ValidationAware
{
private File report;
private String reportContentType;
private String reportFileName;
#Override
public String execute() throws Exception
{
...
return SUCCESS;
}
public void setReport(
File report)
{
this.report = report;
}
public void setReportContentType(
String reportContentType)
{
this.reportContentType = reportContentType;
}
#RequiredFieldValidator(type = ValidatorType.FIELD, key = "errors.required", messageParams = { "getText('labels.report.file')" })
public void setReportFileName(
String reportFileName)
{
this.reportFileName = reportFileName;
}
}
Update: I've discovered that the problem is in having the RequiredFieldValidator annotation. When that is present, the validation always fails but the s:actionerror tag is not displaying any message. When the annotation is not present, it allows a user to not pick a file and still calls execute().
The new question is: how to I correctly annotate my class for validation of a file upload?
I had to remove the #RequiredFieldValidator annotation, make my action implement ValidationAware and then implement a validate() method and manually put the validations in there.
I am attempting to create a registration handler for my Play Framework application but I am running into some trouble. The goal of this code is to grab the data that was submitted and then check if the username or email is in use. This is done using methods built into my User class, which is a model.
The register method:
public static F.Promise<Result> register() {
// Get the POST data and turn it into something we can read from
DynamicForm form = Form.form().bindFromRequest();
// Get the email, username, and password
String email = form.get("email");
String username = form.get("username");
String password = form.get("password");
return User.findByUsername(username).map(user -> {
// For .map to run we must not have encountered an error, this means
// a user already has this username (otherwise the doc would not exist)
return redirect("/register");
}).recover(userCheckError -> {
// For .recover to run there must have been an error. This will happen
// if a doc was not found with the username (therefore it is not in use)
return User.findByEmail(email).map(option -> { // ERROR START
// We now have an F.Option object. If the email is already taken,
// then the Option is defined (has a value within it), if the email
// is free, the Option will be undefined (no value within it)
if (option.isDefined()) {
return redirect("/register");
} else {
return redirect("/register");
}
}); // ERROR END
});
}
The findByUsername and findByEmail methods (in the User class):
public static F.Promise<User> findByUsername(String username) {
return bucket.get(username.toLowerCase(), User.class);
}
public static F.Promise<F.Option<User>> findByEmail(String email) {
return bucket.find("users", "by_email", QueryHelper.findOne(email), User.class).map(result ->{
if (result.isEmpty()) {
return F.Option.None();
} else {
User user = result.iterator().next();
return F.Option.Some(user);
}
});
}
Edit: I have added comments to the register method and removed some unneeded code. I have also labeled where the error starts and ends (the lines that IntelliJ is highlighting. The exact error is "bad return type in lambda expression". The register method needs to return a Promise<Result> but that block of code is returning a Promise<B> (generic?).
Javadocs:
http://www.playframework.com/documentation/2.3.x/api/java/play/libs/F.Promise.html
http://www.playframework.com/documentation/2.3.x/api/java/play/libs/F.Option.html
I started a simple webapp based on play. After a bit of refactoring the login-form stopped working. I used an entity-bean with simple public fields. I moved it from one controller to another while refactoring and of cause corrected the references. It always told me I'm an invalid user.
During debugging I've found that the fields aren't set anymore. However, what really confused me: I manually added getters and setters to the public fields and suddenly it worked again. I've done now quite a bit of research why it works in the default-controller called "Application" but not in my own one called "Registration".
There isn't much code involved, here a few points:
public class RegistrationLogin extends Controller {
public static class Login {
#Required
public String email;
#Required
public String password;
public String validate() {
/* here is the interesting part, when I call "form.hasErrors" in
authenticateLogin and this validate-method gets called, email and
password both are null. If I create getters and setters they are set correctly */
if (User.authenticate(email, password) == null) {
return "Invalid user or password";
}
return null;
}
}
public static Result authenticateLogin() {
Form<Login> loginForm = form(Login.class).bindFromRequest("email", "password");
String title = "Login";
if (loginForm.hasErrors()) {
return badRequest(login.render(title,loginForm));
} else {
session().clear();
session("email", loginForm.get().email);
return redirect(
routes.Application.show(Ebean.find(User.class).where().ieq("email",loginForm.get().email).findUnique().getName())
);
}
}
When I had Login defined in Application (the default-controller which is generated when you start a project) it worked with just the fields.
Whats the origin of this behavior? Any hint might be helpful.
I have a spring controller that I want a method to handle a certain request and then redirect to another one with keeping some value attached, so I will use RedirectAttributes on the first one and #ModalAttribute on the second, but the thing is I will not always have this modal attribute existing so I want to add it only if it exists.
#RequestMapping("/main")
public String getMain(Model model,HttpSession session,#ModalAttribute List<Loans> loansList){
if(session.getAttribute("user") != null){
if(session.getAttribute("current_start")!=null){
model.addAttribute("loans",loanDao.findAll((Integer) session.getAttribute("current_start")));
} else {
model.addAttribute("loans",loanDao.findAll(0));
session.setAttribute("current_start",0);
}
model.addAttribute("loan",new Loan());
model.addAttribute("countries",countryDao.findAll());
model.addAttribute("types",typeDao.findAll());
session.setAttribute("total_loans_number", loanDao.findCount());
return "main";
} else {
return "redirect:index";
}
}
and the redirecting one one is
#RequestMapping(value = "/search")
public String searchLoans(Model model,RedirectAttributes redirectAttributes,
#RequestParam String keyword){
redirectAttributes.addAttribute("loansList",loanDao.findAll(keyword));
return "redirect:/main";
}
but here the #ModalAttribute fails because it sometimes does not exist,sometimes I request main with out the loansList, how to make a condition to add it only if it exists ? or how to do this correctly ?
you can let spring populate your model attributes using #ModalAttribute annotation on methods:
#ModalAttribute("results")
public List<Loans> populateLoans() {
return new ArrayList<Loans>();
}
#RequestMapping("/main")
public String getMain(Model model,HttpSession session,#ModalAttribute("results") List<Loans> loansList){
if (CollectionUtils.isNotEmpty(loanList)) {
// do something if the loan list is not empty.
}
}
This seems like a straightforward question, but I can't find it in the Restfulie documentation nor is Google coming up with an example.
I've got a Resource defined, the method is getting invoked, but I need to get to the query parameters on the URL that was used, which presumably means getting to the HttpRequest. Anyone know how you do that with Restfulie?
#Resource
public class Subscribers
{
private final Result result;
public Subscribers(Result result ){
this.result = result;
}
#Get
#Path("/subscribers")
public void get() {
// Need to get at the query parameters here...
result.use( json() ).from( "You got me" ).serialize();
}
}
Try this way
#Get
#Path("/subscribers")
public void get(#QueryParam("name") String name) {
}
your have to append the keys and values to the request URL. also you need to encode the values.
http://mydomain/subscribers?name=abcde