1

Hey I'm new to Spring MVC, and I need some advice/clarification. Currently I'm implementing an MVC application and I'm struggling with the scope of my controllers. I scan all my controller classes via <context:component-scan base-package="controller"/> which is IMHO a very comfortable way.

Is it correct, that controllers(by default or scanned in the above way), are singletons just like an ordinary bean? If so, all membervariables of my controller are shared between several requests right? Can I change this? I would like to have request-scoped controllers. Just like:

<bean id="infoController" class="controller.InfoController" scope="request">
    <constructor-arg ref="sessionFactory"/>
</bean>

Are there any side-effects with declaring my controllers as beans? Or is it an absolute no go to declare them like this? Or even declare them as request-scoped? Can I combine the two ways? something like:

<context:component-scan base-package="controller" scope="request"/>

How do you guys implement your controllers and make them "request-save"?

tereško
  • 58,060
  • 25
  • 98
  • 150
coR
  • 25
  • 2
  • 5

1 Answers1

3

See the following for a good summary:

Must Spring MVC Classes be Thread-Safe

Scope of a Spring-Controller and its instance-variables

I've never found any reason to consider having member variables in my controller.

Note that your Controller should typically be a thin wrapper around request handling. Logic should then be delegated to a Service which in turn might call a repository/DAO. You should then avoid passing your session factory directly to the controller and have transactions defined at the Service layer.

@Controller
public class MyController{

    @Autowired 
    private MyService service;

    public String handlePost(){
        service.saveEntity(...);
        return "success";
    }
}

@Service
public class MyService{

    @Autowired
    private MyRepository repository;

    @Transactional
    public void saveEntity(Entity e){
    repository.save(e);
    }

}

@Repository
public class MyRepository{

    public void save(Entity e){
    .....
    }

}

See here for an example (also using Spring Data which reduces a lot of the boiler plate code around JPA/Hibernate).

http://fruzenshtein.com/spring-jpa-data-hibernate-mysql/

Community
  • 1
  • 1
Alan Hay
  • 22,665
  • 4
  • 56
  • 110
  • Same here, I know no obvious case in which a controller would need a to have a state. As a component it has dependencies. Would be really curious to see such a case. – mwhs Oct 23 '13 at 20:14
  • Okay thanks for the explanation... I had not been aware that the controller is just a wrapper and you should call a service to do all the logic. Seems like I have to do some investigations on services and DAO-layer. – coR Oct 24 '13 at 06:46
  • Maybe I still missunderstand the above code, but if I autowire the service in the controller... isn't it the same service instance for every request? Shouldn't it be one service instance for every request? – coR Oct 24 '13 at 08:17
  • You are right. Service will by default be a Singleton which should be fine as long as it is Thread safe. – Alan Hay Oct 24 '13 at 08:47