lightbringer
lightbringer

Reputation: 835

Spring mvc controller bean configuration

I am working on a project using Spring mvc and I counter a problem that a handler is auto generated when I start the server.

Here is the code:

Controller

@Controller
@RequestMapping(value="userstory/{projectid}/{sprintid}/")
@SessionAttributes(value = "user")
public class UserstoryController {
    private ISprintService sprintService;
    private IUserStoryService userStoryService;
    private IProjectService projectService;
    private IBurnDownChartService burnDownChartService;
    private ITaskService taskService;

    public void setSprintService(ISprintService sprintService) {
        this.sprintService = sprintService;
    }

    public void setUserStoryService(IUserStoryService userStoryService) {
        this.userStoryService = userStoryService;
    }

    public void setProjectService(IProjectService projectService) {
        this.projectService = projectService;
    }

    public void setBurnDownChartService(IBurnDownChartService burnDownChartService) {
        this.burnDownChartService = burnDownChartService;
    }

    public void setTaskService(ITaskService taskService) {
        this.taskService = taskService;
    }

    @RequestMapping(method=RequestMethod.GET)
    public String getUserstoryPage(@PathVariable("projectid") int pid, @PathVariable("sprintid") int sid,  @ModelAttribute("user") SerializablePerson user) {
        if (user.getId() != 0) {
            Project p = this.projectService.findProjectById(pid);
            if (p == null) {
                throw new ResourceNotFoundException(pid);
            }
            if (user.getRole().equals("User")) {
                return "userstory/user_userstory";
            }
            else {
                return "userstory/admin_userstory";
            }
        }
        return "redirect:../../../login";
    }

}

beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="personServiceImpl" class="ch.bsgroup.scrumit.service.impl.PersonServiceImpl" />
    <bean id="projectServiceImpl" class="ch.bsgroup.scrumit.service.impl.ProjectServiceImpl" />
    <bean id="sprintServiceImpl" class="ch.bsgroup.scrumit.service.impl.SprintServiceImpl" />
    <bean id="userStoryServiceImpl" class="ch.bsgroup.scrumit.service.impl.UserStoryServiceImpl" />
    <bean id="taskServiceImpl" class="ch.bsgroup.scrumit.service.impl.TaskServiceImpl" />

    <bean id="projectService" class="ch.bsgroup.scrumit.service.impl.ProjectServiceImpl" />
    <bean id="personService" class="ch.bsgroup.scrumit.service.impl.PersonServiceImpl" />

    <bean id="sprintService" class="ch.bsgroup.scrumit.service.impl.SprintServiceImpl" />
    <bean id="userStoryService" class="ch.bsgroup.scrumit.service.impl.UserStoryServiceImpl" />
    <bean id="burnDownChartService" class="ch.bsgroup.scrumit.service.impl.BurnDownChartServiceImpl" />
    <bean id="taskService" class="ch.bsgroup.scrumit.service.impl.TaskServiceImpl" />

    <bean id="sprintUserstoryController" class="ch.bsgroup.scrumit.controller.SprintUserstoryController">
        <property name="sprintService">
            <ref local="sprintService"/>
        </property>
        <property name="userStoryService">
            <ref local="userStoryService"/>
        </property>
        <property name="projectService">
            <ref local="projectService"/>
        </property>
        <property name="burnDownChartService">
            <ref local="burnDownChartService"/>
        </property>
        <property name="taskService">
            <ref local="taskService"/>
        </property>
    </bean>

    <bean id="boardController" class="ch.bsgroup.scrumit.controller.BoardController">
        <property name="sprintService">
            <ref local="sprintService"/>
        </property>
        <property name="projectService">
            <ref local="projectService"/>
        </property>
        <property name="userStoryService">
            <ref local="userStoryService"/>
        </property>
        <property name="taskService">
            <ref local="taskService"/>
        </property>
        <property name="burnDownChartService">
            <ref local="burnDownChartService"/>
        </property>
    </bean>

    <bean name="register.jsp" id="registerController" class="ch.bsgroup.scrumit.controller.RegisterController">
        <property name="personService">
            <ref local="personService"/>
        </property>
    </bean>

    <bean id="loginController" class="ch.bsgroup.scrumit.controller.LoginController" >
        <property name="personService">
            <ref local="personService"/>
        </property>
    </bean>

    <bean id="adminProjectController" class="ch.bsgroup.scrumit.controller.AdminProjectController">
        <property name="projectService">
            <ref local="projectService"/>
        </property>
        <property name="personService">
            <ref local="personService"/>
        </property>
    </bean>

    <bean id="userProjectController" class="ch.bsgroup.scrumit.controller.UserProjectController">
        <property name="projectService">
            <ref local="projectService"/>
        </property>
    </bean>

    <bean id="adminPersonController" class="ch.bsgroup.scrumit.controller.AdminPersonController">
        <property name="projectService">
            <ref local="projectService"/>
        </property>
        <property name="personService">
            <ref local="personService"/>
        </property>
    </bean>

    <bean id="manageProjectMemberController" class="ch.bsgroup.scrumit.controller.ManageProjectMemberController">
        <property name="projectService">
            <ref local="projectService"/>
        </property>
        <property name="personService">
            <ref local="personService"/>
        </property>
    </bean>

    <bean id="manageUserstoryController" class="ch.bsgroup.scrumit.controller.UserstoryController">
        <property name="sprintService">
            <ref local="sprintService"/>
        </property>
        <property name="userStoryService">
            <ref local="userStoryService"/>
        </property>
        <property name="projectService">
            <ref local="projectService"/>
        </property>
        <property name="burnDownChartService">
            <ref local="burnDownChartService"/>
        </property>
        <property name="taskService">
            <ref local="taskService"/>
        </property>
    </bean>
</beans>

I copy all the beans to show that there is no userstoryController mapped.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <filter>
    <filter-name>UrlRewriteFilter</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>UrlRewriteFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>scrumit</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/app-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>scrumit</servlet-name>
    <url-pattern>/app/*</url-pattern>
  </servlet-mapping>
</web-app>

app-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- Scans the classpath of this application for @Components to deploy as beans -->
    <context:component-scan base-package="ch.bsgroup.scrumit.controller" />

    <!-- Application Message Bundle -->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/messages/messages" />
        <property name="cacheSeconds" value="0" />
    </bean>

    <!-- Including beans -->
    <import resource="beans.xml" />

    <!-- Configures Spring MVC -->
    <import resource="mvc-config.xml" />

</beans>

And this is what I have when I start the server:

INFO : org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - Mapped URL path [/userstory/{projectid}/{sprintid}/] onto handler 'userstoryController'

The error is:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0': Initialization of bean failed; nested exception is java.lang.IllegalStateException: Cannot map handler 'manageUserstoryController' to URL path [/userstory/{projectid}/{sprintid}/]: There is already handler of type [class ch.bsgroup.scrumit.controller.UserstoryController] mapped.

The program does not allow me to map UserstoryController to manageUserstoryController because of the existence of userstoryController.

Could anyone explain to me why userstoryController is generated, and how to map it properly. Thanks in advance.

Upvotes: 3

Views: 41080

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 279890

The issue is the following. This element

<context:component-scan base-package="ch.bsgroup.scrumit.controller" />

already creates an instance of your UserstoryController controller because of @Controller. And then the <bean> elements in beans.xml creates another one.

When you annotate a class with @Controller and have an appropriate component-scan, you should not declare a separate bean element in your context.

The fact is, all of this

<bean id="boardController" class="ch.bsgroup.scrumit.controller.BoardController">
    <property name="sprintService">
        <ref local="sprintService"/>
    </property>
    <property name="projectService">
        <ref local="projectService"/>
    </property>
    <property name="userStoryService">
        <ref local="userStoryService"/>
    </property>
    <property name="taskService">
        <ref local="taskService"/>
    </property>
    <property name="burnDownChartService">
        <ref local="burnDownChartService"/>
    </property>
</bean>

can be replaced with appropriate @Autowired annotations on fields. You don't even need getters and setters. For example

@Controller
@RequestMapping(value="userstory/{projectid}/{sprintid}/")
@SessionAttributes(value = "user")
public class UserstoryController {
    @Autowired
    private ISprintService sprintService;

    @Autowired
    private IUserStoryService userStoryService;

    @Autowired
    private IProjectService projectService;

    @Autowired
    private IBurnDownChartService burnDownChartService;

    @Autowired
    private ITaskService taskService;

    @RequestMapping(method=RequestMethod.GET)
    public String getUserstoryPage(@PathVariable("projectid") int pid, @PathVariable("sprintid") int sid,  @ModelAttribute("user") SerializablePerson user) {
        if (user.getId() != 0) {
            Project p = this.projectService.findProjectById(pid);
            if (p == null) {
                throw new ResourceNotFoundException(pid);
            }
            if (user.getRole().equals("User")) {
                return "userstory/user_userstory";
            }
            else {
                return "userstory/admin_userstory";
            }
        }
        return "redirect:../../../login";
    }
}

Here's some related documentation:

Upvotes: 14

Related Questions