0

I encounter this problem while I am trying to duplicate a simple spring OAuth project, sparklr2. source code here https://github.com/spring-projects/spring-security-oauth/tree/master/samples/oauth2/sparklr

the source code runs perfectly, when I debug it with tomcat, it initialize all @Bean inside WebMvcConfigurerAdapter, including controllers. but noted that @ComponentScan() is not being used.

then I create my own MVC project, copy almost 100% of code, but I am using WebApplicationInitializer instead of AbstractDispatcherServletInitializer. I use WebApllicationInitializer because I have only learned this way to code MVC.

then I run the project, @Bean initialized. then I check /login with my browser, get 404. this could be caused by spring not knowing I have controllers, then I add @ComponentScan to my configuration class, /login now shows up. but the weird thing is, all @Bean related to Controller, are not initialized. so, when I call any method to those controller, since their attributes are not initialized, gives me no object or null exception.

So, my point is, how does that sample works, I mean controller and jsp correctly handle and response without using @ComponentScan? and look at it from different angle, why does @ComponentScan stop @Bean from being initialize in my project?

my WebApplicationInitializer

@Configuration
@EnableWebMvc
@ComponentScan("umedia.test.oauth.controller")
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Bean
    public ContentNegotiatingViewResolver contentViewResolver()
            throws Exception {
        ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean();
        contentNegotiationManager.addMediaType("json",
                MediaType.APPLICATION_JSON);

        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        MappingJackson2JsonView defaultView = new MappingJackson2JsonView();
        defaultView.setExtractValueFromSingleKeyModel(true);

        ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver();
        contentViewResolver
                .setContentNegotiationManager(contentNegotiationManager
                        .getObject());
        contentViewResolver.setViewResolvers(Arrays
                .<ViewResolver> asList(viewResolver));
        contentViewResolver.setDefaultViews(Arrays.<View> asList(defaultView));
        return contentViewResolver;
    }



    @Bean
    public PhotoServiceImpl photoServices() {
        List<PhotoInfo> photos = new ArrayList<PhotoInfo>();
        photos.add(createPhoto("1", "marissa"));
        photos.add(createPhoto("2", "paul"));
        photos.add(createPhoto("3", "marissa"));
        photos.add(createPhoto("4", "paul"));
        photos.add(createPhoto("5", "marissa"));
        photos.add(createPhoto("6", "paul"));

        PhotoServiceImpl photoServices = new PhotoServiceImpl();
        photoServices.setPhotos(photos);
        return photoServices;
    }

    // N.B. the @Qualifier here should not be necessary (gh-298) but lots of
    // users report needing it.
    @Bean
    public AdminController adminController(
            TokenStore tokenStore,
            @Qualifier("consumerTokenServices") ConsumerTokenServices tokenServices,
            SparklrUserApprovalHandler userApprovalHandler) {
        AdminController adminController = new AdminController();
        adminController.setTokenStore(tokenStore);
        adminController.setTokenServices(tokenServices);
        adminController.setUserApprovalHandler(userApprovalHandler);
        return adminController;
    }

    // this url, do I need to change it?
    private PhotoInfo createPhoto(String id, String userId) {
        PhotoInfo photo = new PhotoInfo();
        photo.setId(id);
        photo.setName("photo" + id + ".jpg");
        photo.setUserId(userId);
        photo.setResourceURL("/org/springframework/security/oauth/examples/sparklr/impl/resources/"
                + photo.getName());
        return photo;
    }

    @Override
    public void configureDefaultServletHandling(
            DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    @Bean
    public PhotoServiceUserController photoServiceUserController(
            PhotoService photoService) {
        PhotoServiceUserController photoServiceUserController = new PhotoServiceUserController();
        return photoServiceUserController;
    }

    @Bean
    public PhotoController photoController(PhotoService photoService) {
        PhotoController photoController = new PhotoController();
        photoController.setPhotoService(photoService);
        return photoController;
    }

    @Bean
    public AccessConfirmationController accessConfirmationController(
            ClientDetailsService clientDetailsService,
            ApprovalStore approvalStore) {
        AccessConfirmationController accessConfirmationController = new AccessConfirmationController();
        accessConfirmationController
                .setClientDetailsService(clientDetailsService);
        accessConfirmationController.setApprovalStore(approvalStore);
        return accessConfirmationController;
    }

/*  @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }*/

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations(
                "/resources/");
    }

}
Maxi Wu
  • 1,274
  • 3
  • 20
  • 38

1 Answers1

0

so, you have @ComponentScan which interacts with @Controller on your controllers + still create @Bean's with those?

As a first step try to remove @Beans and try to inject dependencies using @Autowired on controllers' constructors. Then @ComponentScan should recognize @Controller, inject dependencies and use @RequestMapping without issues.

hi_my_name_is
  • 4,894
  • 3
  • 34
  • 50
  • freakman, thanks. you are probably right, I am new to java config mvc project. never use /@Bean before with /@Controller. I just use them because that sample code does it. after trying many combination, I think component scan is correctly working with /@Controller, but /@Bean is not. I didn't remove /@Bean, I am guessing it just tells spring that this is a bean. then I add /@Autowire to some related variable inside those controller classes, and it seems to work. don't fully understand how they work though. – Maxi Wu Jul 30 '15 at 10:46
  • there is nothing wrong with /@Bean itself. Usually it is used for things like services. But /@Controller requires /@RequestMapping to know on which path to work, which is not provided if you create controllers with @Bean as in your example. Seems you are mixing both solutions and confuse spring ; ) Would be great if you put your code to github so it would be easier to help you. – hi_my_name_is Jul 30 '15 at 11:05
  • it's here https://github.com/maxiwu/springexercise I think spring is confused by my mess up configuration. but don't know how to do it correctly. my goals are, use a spring MVC setup with WebMvcConfigurerAdapter & WebApplicationInitializer. support those initialization before any request could be made to those MVC controllers. clean up unnecessary configuration and annotation. – Maxi Wu Jul 31 '15 at 02:58
  • sorry to say, but copying everything around without understanding is not a solution to learn anything. I was trying to fix it for you, but there are just too many errors. Please follow some spring boot tutorial - they are really well structured :) – hi_my_name_is Jul 31 '15 at 06:44
  • I too think copying things around is not a good approach. there are so many things going on, annotation, security, oauth, spring boot. I have just finished reading some spring security materials and will move on to read about spring boot. thank you for looking into this for me, really appreciate that. – Maxi Wu Aug 03 '15 at 01:46
  • i did not say its easy, but trying to configure security/oauth + other let say 'more advanced' things when basic controllers are not working is not the best idea :) take baby steps from the beginning and you will understand it all – hi_my_name_is Aug 03 '15 at 06:22