6

I'm using spring 2.5, and am using annotations to configure my controllers. My controller works fine if I do not implement any additional interfaces, but the spring container doesn't recognize the controller/request mapping when I add interface implementations.

I can't figure out why adding an interface implementation messes up the configuration of the controller and the request mappings. Any ideas?

So, this works:

package com.shaneleopard.web.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.shaneleopard.model.User;
import com.shaneleopard.service.UserService;
import com.shaneleopard.validator.RegistrationValidator;
import com.shaneleopard.web.command.RegisterCommand;

@Controller
public class RegistrationController {

    @Autowired
    private UserService userService;

    @Autowired
    private Md5PasswordEncoder passwordEncoder;

    @Autowired
    private RegistrationValidator registrationValidator;

    @RequestMapping( method = RequestMethod.GET, value = "/register.html" )
    public void registerForm(@ModelAttribute RegisterCommand registerCommand) {
        // no op
    }

    @RequestMapping( method = RequestMethod.POST, value = "/register.html" )
    public String registerNewUser( @ModelAttribute RegisterCommand command,
            Errors errors ) {
        String returnView = "redirect:index.html";

        if ( errors.hasErrors() ) {
            returnView = "register";
        } else {
            User newUser = new User();
            newUser.setUsername( command.getUsername() );
            newUser.setPassword( passwordEncoder.encodePassword( command
                    .getPassword(), null ) );
            newUser.setEmailAddress( command.getEmailAddress() );
            newUser.setFirstName( command.getFirstName() );
            newUser.setLastName( command.getLastName() );

            userService.registerNewUser( newUser );
        }
        return returnView;

    }

    public Validator getValidator() {
        return registrationValidator;
    }
}

but this doesn't:

package com.shaneleopard.web.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.shaneleopard.model.User;
import com.shaneleopard.service.UserService;
import com.shaneleopard.validator.RegistrationValidator;
import com.shaneleopard.web.command.RegisterCommand;

@Controller
public class RegistrationController extends ValidatingController {

    @Autowired
    private UserService userService;

    @Autowired
    private Md5PasswordEncoder passwordEncoder;

    @Autowired
    private RegistrationValidator registrationValidator;

    @RequestMapping( method = RequestMethod.GET, value = "/register.html" )
    public void registerForm(@ModelAttribute RegisterCommand registerCommand) {
        // no op
    }

    @RequestMapping( method = RequestMethod.POST, value = "/register.html" )
    public String registerNewUser( @ModelAttribute RegisterCommand command,
            Errors errors ) {
        String returnView = "redirect:index.html";

        if ( errors.hasErrors() ) {
            returnView = "register";
        } else {
            User newUser = new User();
            newUser.setUsername( command.getUsername() );
            newUser.setPassword( passwordEncoder.encodePassword( command
                    .getPassword(), null ) );
            newUser.setEmailAddress( command.getEmailAddress() );
            newUser.setFirstName( command.getFirstName() );
            newUser.setLastName( command.getLastName() );

            userService.registerNewUser( newUser );
        }
        return returnView;

    }

    public Validator getValidator() {
        return registrationValidator;
    }
}
3
  • I should add that controllers are registered with the following in my spring context config: <context:component-scan base-package="com.shaneleopard.web" /> and using the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter Commented Sep 29, 2008 at 23:23
  • It doesn't look like you're importing the ValidatingController - what's the fully qualified class name? Commented Sep 29, 2008 at 23:37
  • I am importing it. It's in the same package as the controller example above. I should add the above code works when I extend the ValidatingController base class, but when I code ValidatingController as an interface and have RegistrationController implement it, then it breaks. Commented Sep 29, 2008 at 23:47

3 Answers 3

3

layne, you described the problem as happening when your controller class implements an interface, but in the code sample you provided, the problem occurs when your controller class extends another class of yours, ValidatingController.

Perhaps the parent class also defines some Spring annotations, and the Spring container noticed them first and classified the controller class as that type of managed object and did not bother to check for the @Controller annotation you also defined in the subclass. Just a guess, but if that pans out, I'd suggest reporting it to the Spring team, as it sounds like a bug.

Sign up to request clarification or add additional context in comments.

Comments

1

By default JDK proxy are created using interface and if controller implements an interface the RequestMapping annotation gets ignored as the targetClass is not being used

Add this in your servlet context config:

<aop:aspectj-autoproxy proxy-target-class="true"/>

Comments

0

I think you'll find that the problem is to do with inheritance and using annotations, they do not mix well.

Have you tried to implement the above using inheritance and SimpleFormController with all other details configured in your application context? This will at least narrow down the problem to an annotations and inheritance issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.