Jakub
Jakub

Reputation: 2141

Spring Social /connect return HTTP 404

Spring can't find html views and im getting 404 while i'm trying to open /connect/linkedin. In referece to that post I double checked my paths in webapp folder. Here is my SpringSocialConfig

@Configuration
@EnableSocial
public class SocialConfig implements SocialConfigurer {

    @Inject
    private DataSource dataSource;

    @Override
    public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
        connectionFactoryConfigurer.addConnectionFactory(new LinkedInConnectionFactory("xxxxxx", "xxxxxx"));
    }

    @Override
    public UserIdSource getUserIdSource() {
        return new UserIdSource() {
            @Override
            public String getUserId() {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication == null) {
                    throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
                }
                return authentication.getName();
            }
        };
    }

    @Bean
    public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
        return new ConnectController(connectionFactoryLocator, connectionRepository);
    }


    @Bean
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    public LinkedIn linkedin(ConnectionRepository repository) {
        Connection<LinkedIn> connection = repository.findPrimaryConnection(LinkedIn.class);
        return connection != null ? connection.getApi() : null;
    }

    @Override
    public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
        return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator, Encryptors.noOpText());
    }
}

My HomeController with /linkedin mapping handler

@Inject
private ConnectionRepository connectionRepository;

@Inject
private LinkedIn linkedIn;

@Inject
public HomeController(LinkedIn linkedIn) {
    this.linkedIn = linkedIn;
}

@RequestMapping(value = "/linkedin", method = RequestMethod.GET)
public String home(Principal currentUser, Model model) {
    Connection<LinkedIn> connection = connectionRepository.findPrimaryConnection(LinkedIn.class);
    if (connection == null) {
        return "redirect:/connect/linkedin";
    }
    model.addAttribute("profile", connection.getApi().profileOperations().getUserProfileFull());
    return "linkedin/profile";
}

And my WEBAPP folder with views enter image description here

As I see in logs, something happen and /connect/* mappings were discovered.

[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[POST]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.connect(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET]}" onto public java.lang.String org.springframework.social.connect.web.ConnectController.connectionStatus(java.lang.String,org.springframework.web.context.request.NativeWebRequest,org.springframework.ui.Model)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect],methods=[GET]}" onto public java.lang.String org.springframework.social.connect.web.ConnectController.connectionStatus(org.springframework.web.context.request.NativeWebRequest,org.springframework.ui.Model)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[oauth_token]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth1Callback(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[code]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth2Callback(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[GET],params=[error]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.oauth2ErrorCallback(java.lang.String,java.lang.String,java.lang.String,java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}],methods=[DELETE]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.removeConnections(java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[localhost-startStop-1] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/connect/{providerId}/{providerUserId}],methods=[DELETE]}" onto public org.springframework.web.servlet.view.RedirectView org.springframework.social.connect.web.ConnectController.removeConnection(java.lang.String,java.lang.String,org.springframework.web.context.request.NativeWebRequest)
[local

I'm using Thymeleaf 3.0

@Bean
public ViewResolver viewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    resolver.setTemplateEngine(templateEngine());
    resolver.setCharacterEncoding("UTF-8");
    resolver.setContentType("text/html; charset=UTF-8");
    return resolver;
}

@Bean
public TemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    engine.setEnableSpringELCompiler(true);
    engine.setTemplateResolver(templateResolver());
    engine.addDialect(new SpringSecurityDialect());
    return engine;
}

 private ITemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setApplicationContext(applicationContext);
        resolver.setPrefix("/views/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setCacheable(Boolean.parseBoolean(THYMELEAF_CACHE));
        return resolver;
    }

Dispatcher configuration

public class WebAppInitializer implements WebApplicationInitializer {

    private final String APP_SERVLET_NAME = "x";
    private final String DISPLAY_NAME = "App";

    @Override
    public void onStartup(ServletContext container) {
        container.addListener(new ContextLoaderListener(getContext()));
        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("utf-8");
        characterEncodingFilter.setForceEncoding(true);

        container.addFilter("charEncodingFilter", characterEncodingFilter).addMappingForUrlPatterns(null, false, "/*");
        container.addFilter("securityFilter", new DelegatingFilterProxy("springSecurityFilterChain")).addMappingForUrlPatterns(null, false, "/*");
        container.addFilter("apiFilter", new DelegatingFilterProxy("apiExceptionHandler"));
        container.addFilter("hidden", new HiddenHttpMethodFilter());

        AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
        dispatcherServlet.register(ServletConfig.class);

        ServletRegistration.Dynamic dispatcher = container.addServlet(APP_SERVLET_NAME, new DispatcherServlet(dispatcherServlet));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }

    private AnnotationConfigWebApplicationContext getContext() {
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(JPARepositoryConfig.class,
                ThymeleafConfig.class,
                WebSecurityConfig.class,
                SocialConfig.class,
                MailConfig.class,
                MongoRepositoryConfig.class,
                ServiceConfig.class,
                CacheConfig.class);

        rootContext.setDisplayName(DISPLAY_NAME);
        return rootContext;
    }

I set breakpoints in Connection Controller from Spring Social and non of mapped method was invoked. So I think that app configuration is mess up.

EDIT I had wrong spring servlet configuration. I registered spring social controllers as root servlet.

Upvotes: 3

Views: 616

Answers (3)

rpieniazek
rpieniazek

Reputation: 2370

I know it's been long time, but I think I found solution for this problem.

The issue is, that your spring configuration found 'ConnectController' as bean, but it was not mapped as Controller. Also, I've checked source of ConnectController class. It turned out that it builds view names based on prefix and providerId.

Following this answer: https://stackoverflow.com/a/19699607/4544269

I've inherited ConnectController, and overrided both 'connectView' and 'connectedView', now pointing to Freemarkers templates in WEB-INF folder.

@Controller
public class CustomConnectController extends ConnectController{

    @Autowired
    public CustomConnectController(
            ConnectionFactoryLocator connectionFactoryLocator,
            ConnectionRepository connectionRepository) {
        super(connectionFactoryLocator, connectionRepository);
    }

    @Override
    protected String connectedView(String providerId){
        return "connect/facebookConnected";
    }

    @Override
    protected String connectView(String providerId) {
        return "connect/facebookConnect";
    }

   }

Upvotes: -1

Sanjay Rawat
Sanjay Rawat

Reputation: 2364

I think the problem is the location of your views.

You have it under src/main/webapp and spring is searching for views under src/main/resources.

Either move all your html files to src/main/resources/views or change the config so that spring searches under src/main/webapp/views.

Check this Example the config is similar to what you have but the views are under src/main/resources folder.

Upvotes: 2

mklimasz
mklimasz

Reputation: 121

My guess is that you might need spring.social.auto-connection-views=true in your application.properties file

Upvotes: 0

Related Questions