Let me lead with the fact that I don't understand Spring Web MVC well enough.
That said, I think I have some concerns with the CredentialsBinder API and its associated LoginController implementation.
LoginController extends Spring SimpleFormHandler and looks something like this:
protected ModelAndView processFormSubmission(final HttpServletRequest request, final HttpServletResponse response, final Object object, final BindException errors) throws Exception { final Credentials credentials = (Credentials)object; this.credentialsBinder.bind(request, credentials); final String ticketGrantingTicketId = this.centralAuthenticationService.createTicketGrantingTicket(credentials);
We need to look carefully at the "object" argument. The object here is a Command. LoginController extends SimpleFormController which extends AbstractFormController which extends BaseCommandController which extends AbstractController which extends WebContentGenerator which extends WebApplicationObjectSupport which extends ApplicationObjectSupport. In Spring Web MVC FormControllers, the forms play the role of "commands" in the more general CommandController model.
LoginController defaults this Command class:
public void afterPropertiesSet() throws Exception { if (this.getCommandClass() == null) { this.setCommandName("credentials"); this.setCommandClass(UsernamePasswordCredentials.class);
In BaseCommandController, we have:
/** * Retrieve a command object for the given request. * <p>Default implementation calls createCommand. Subclasses can override this. * @param request current HTTP request * @return object command to bind onto * @see #createCommand */ protected Object getCommand(HttpServletRequest request) throws Exception { return createCommand(); }
And the createCommand() method to which it delegates:
/** * Create a new command instance for the command class of this controller. * @return the new command instance * @throws InstantiationException if the command class could not be instantiated * @throws IllegalAccessException if the class or its constructor is not accessible */ protected final Object createCommand() throws InstantiationException, IllegalAccessException { if (this.commandClass == null) { throw new IllegalStateException("Cannot create command without commandClass being set - " + "either set commandClass or override formBackingObject"); } if (logger.isDebugEnabled()) { logger.debug("Creating new command of class [" + this.commandClass.getName() + "]"); } return this.commandClass.newInstance(); }
/** * Interface for a class that can bind items stored in the request to a particular * credentials implementation. This allows for binding beyond the basic * JavaBean/Request parameter binding that is handled by Spring automatically. */ public interface CredentialsBinder { /** * Method to allow manually binding attributes from the request object to properties of * the credentials. Useful when there is no mapping of attribute to property for the * usual Spring binding to handle. * * @param request The HttpServletRequest from which we wish to bind credentials to * @param credentials The credentials we will be doing custom binding to. */ void bind(HttpServletRequest request, Credentials credentials); /** * * Method to determine if a CredentialsBinder supports a specific class or not. * * @param clazz The class to determine is supported or not * @return true if this class is supported by the CredentialsBinder, false otherwise. */ boolean supports(Class clazz); }