Thiago Medeiros Thiago Medeiros - 5 months ago 13
Java Question

The method form(Class<T>) from Form class is deprecated in Play! Framework

I spent a lot of time trying so solve this problem, and searching the method to substitute this one, without success.

First, Play! obligates me to use and inject the FormFactory (that is explained in https://www.playframework.com/documentation/2.5.0/JavaForms).

But just for instantiate this FormFactory I had to pass 3 parameters for it's constructor, that is MessagesApi, Formatters and Validator. Including, I had to instantiate the Validator interface, and I'm no sure that is the right way to do it.

To make it more easy, I separated it in another class:

package controllers;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.executable.ExecutableValidator;
import javax.validation.metadata.BeanDescriptor;
import play.data.FormFactory;
import play.data.format.Formatters;
import play.i18n.MessagesApi;

class Validador implements Validator {

@Override
public ExecutableValidator forExecutables() {
// TODO Auto-generated method stub
return null;
}

@Override
public BeanDescriptor getConstraintsForClass(Class<?> arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public <T> T unwrap(Class<T> arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public <T> Set<ConstraintViolation<T>> validate(T arg0, Class<?>... arg1) {
// TODO Auto-generated method stub
return null;
}

@Override
public <T> Set<ConstraintViolation<T>> validateProperty(T arg0, String arg1, Class<?>... arg2) {
// TODO Auto-generated method stub
return null;
}

@Override
public <T> Set<ConstraintViolation<T>> validateValue(Class<T> arg0, String arg1, Object arg2, Class<?>... arg3) {
// TODO Auto-generated method stub
return null;
}
}

public class FormCreator {

MessagesApi msgAPI;
Formatters formatador;
Validador validador;
FormFactory factory;

public FormCreator() {
msgAPI = new MessagesApi(null);
formatador = new Formatters(msgAPI);
validador = new Validador();
factory = new FormFactory(msgAPI, formatador, validador);
}


// getters e setters
public MessagesApi getmsgAPI() {
return msgAPI;
}
public void setmsgAPI(MessagesApi msgAPI) {
this.msgAPI = msgAPI;
}
public Formatters getFormatador() {
return formatador;
}
public void setFormatador(Formatters formatador) {
this.formatador = formatador;
}
public Validador getValidador() {
return validador;
}
public void setValidador(Validador validador) {
this.validador = validador;
}
public FormFactory getFactory() {
return factory;
}
public void setFactory(FormFactory factory) {
this.factory = factory;
}
}


And in my controller I have to put something like this:

@Inject
FormCreator formCreator = new FormCreator();


althrough that I spent some hours to discover this, this question was solved.

Another one is, whatever I do, the method bindFromRequest() always returns null, and is no because the eclipse, and anything else, it's because I call it from a form created by this factory.

Example:

// never works
formCreator.getFactory().form(Diretor.class).bindFromRequest();

// works fine, but is deprecated
Form.form(Diretor.class).bindFromRequest();


What is the newest method to use instead this deprecated method?

Thanks in advance.

Answer

The Play 2.5.x documentation states it:

To wrap a class you have to inject a play.data.FormFactory into your Controller which then allows you to create the form:

Form userForm = formFactory.form(User.class);

So the first step is to inject the FormFactory into your controller. You do it like this:

package controllers;

import play.*;
import play.mvc.*;

public class Application extends Controller {

    @Inject FormFactory formFactory;

    ...
}

Then in the action where you handle the form-submission request you can use the FormFactory like this:

public Result handleFormSubmission() {
    formFactory.form(Director.class).bindFromRequest();
}