1
votes

I'm currently looking at the Play! Framework for Java, and I've run into a pretty curious error:

I've got a model with the following required fields (no other fields except an id)

@Lob
@Constraints.Required
private String content;

@Constraints.Email
@Constraints.Required
private String email;

@Constraints.Required
private String title;

I've got the following methods in my Controller:

public static Result createEntry() {
    Form<BlogEntry> filledForm = blogEntryForm.bindFromRequest();
    if (filledForm.hasErrors()) {
        Logger.debug(filledForm.data().toString());
        Logger.debug(filledForm.errors().toString());
        return badRequest(newentry.render(filledForm));
    }
    BlogEntry entry = filledForm.get();
    entry.save();
    return redirect(routes.BlogController.index());
}

public static Result newEntry() {
    return ok(newentry.render(blogEntryForm));
}

And the view looks like this:

@(blogform: Form[BlogEntry])
@import helper._

@main("New Blog Entry") {
    @form(routes.BlogController.createEntry()) {

        @if(blogform.hasErrors) {
            Errors in form
        }
        <fieldset>
            <div>
            @inputText(blogform("email"), '_label -> "Email")
            </div>
            <div>
            @inputText(blogform("title"), '_label -> "Title")
            </div>
            <div>
            @inputText(blogform("content"), '_label -> "Content")
            </div>
            <button type="submit">Submit</button>
        </fieldset>
    }
}

Now when I navigate to the form in my browser, and enter some data, then click "submit", I get redirected to the form, so the badRequest portion of the code was called. So I started logging the output of both form and validation errors, and this came out:

[debug] application - {content=test, title=test, [email protected]}

[debug] application - {content=[ValidationError(content,error.required,[])], title=[ValidationError(title,error.required,[])], email=[ValidationError(email,error.required,[])]}

The data is definitely there, and when I'm redirected to the form after submitting, the fields are still filled with the correct data. Am I missing something obvious here?

2

2 Answers

3
votes

Figured this out now: The reason was that I had no setters for the fields in my model. That way the form was unable to set the properties and failed silently.

0
votes

Hello I know it has been a year since you've looked at this but I have a little more information for anyone just coming to this now. In using 2.4.x and setting up ebeans I came across this page: Play Enhancer. The play enhancer is byte code magic that allows the use of public fields and direct access in the project but when built actually encapsulates the fields.

The enhancer looks for all fields on Java classes that:

  • are public

  • are non static

  • are non final

For each of those fields, it will generate a getter and a setter if they don’t already exist. If you wish to provide a custom getter or setter for a field, this can be done by just writing it, the Play enhancer will simply skip the generation of the getter or setter if it already exists.

In using the ebeans ORM, the Play Enhancer gets turned on by default. This is from the default plugins.sbt file that comes with a Play! application:

// Play enhancer - this automatically generates getters/setters for public fields
// and rewrites accessors of these fields to use the getters/setters. Remove this
// plugin if you prefer not to have this feature, or disable on a per project
// basis using disablePlugins(PlayEnhancer) in your build.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-play-enhancer" % "1.1.0")

// Play Ebean support, to enable, uncomment this line, and enable in your build.sbt using
// enablePlugins(SbtEbean). Note, uncommenting this line will automatically bring in
// Play enhancer, regardless of whether the line above is commented out or not.
addSbtPlugin("com.typesafe.sbt" % "sbt-play-ebean" % "1.0.0")

The options are to have public fields and use them without getters and let play alter it under the hood or use private fields and define your own getters and setters.