Search code examples
javajspspring-mvcspring-annotations

ModelAttribute in abstract class with value from subclass


I want to have a common method annoted @ModelAttribute in an abstract class but with value from subclasses. The final goal is to retrieve the value of a variable in JSP. The value is different in each subclass controller but I don't want to duplicate the @ModelAttribute method.

The abstract class

public abstract class BaseController {

    protected String PATH = "";

    public void setPATH(String inPath) {
        PATH = inPath;
    }

    @PostConstruct
    private void init() {
        setPATH(PATH);      
    }

    @ModelAttribute("controllerPath")
    public String getControllerPath() {
        return PATH;
    }   
}

The sublass, a controller

@Controller
@RequestMapping(OneController.PATH)
public class OneController extends BaseController {

    protected static final String PATH = "/one";

    public OneController() {
        setPATH(PATH);      
    }
}

JSP

Value for controllerPath: ${controllerPath}

The value of ${controllerPath} is always empty with Spring version 4.0.9.RELEASE but works (the value is set with the value from the subclass controller) with Spring version 3.1.2.RELEASE. How do I update my code to work with Spring 4 ?


Solution

  • You need to declare abstract the ModelAttribute method in your abstract controller.

    public abstract class BaseController {
    
        protected String PATH = "";
    
        public void setPATH(String inPath) {
            PATH = inPath;
        }
    
        @PostConstruct
        private void init() {
            setPATH(PATH);      
        }
    
        @ModelAttribute("controllerPath")
        public abstract String getControllerPath();
    }
    

    And on each controller which extends the abstract controller:

    @Controller
    @RequestMapping(OneController.PATH)
    public class OneController extends BaseController {
    
        protected static final String PATH = "/one";
    
        @Override
        public String getControllerPath(){
            return PATH;
        }
    }
    

    UPDATE:

    If you dont want to repeat the new method in all Controllers:

    In your abstract controller

    @ModelAttribute("controllerPath")
     public String getControllerPath(){
         return "";
     }
    

    Where you want to override the value. Add Override annotation

    @Override
    public String getControllerPath(){
        return PATH;
    }