spring-attic / spring-social

Allows you to connect your applications with SaaS providers such as Facebook and Twitter.
http://projects.spring.io/spring-social
Apache License 2.0
619 stars 351 forks source link

Upgrade to thymeleaf 3.0 #207

Closed eddumelendez closed 7 years ago

eddumelendez commented 8 years ago

Upgrade is very important to allow to spring-boot move to that version too. See https://github.com/spring-projects/spring-boot/issues/4393

alek-sys commented 8 years ago

Any chances to move this forward? I.e. get this PR merged and new official release available any time soon? Currently with Spring Boot 1.4 and Spring Social 1.1.4 when Thymeleaf 3 is enabled the application fails on start with error when initialising SpringSocialDialect (see below).

java.lang.NoSuchMethodError: org.thymeleaf.dialect.AbstractDialect: method <init>()V not found at org.springframework.social.connect.web.thymeleaf.SpringSocialDialect.<init>(SpringSocialDialect.java:47) ~[spring-social-web-1.1.4.RELEASE.jar:1.1.4.RELEASE] at org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration$SpringSocialThymeleafConfig.springSocialDialect(SocialWebAutoConfiguration.java:172) ~[spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE] at org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration$SpringSocialThymeleafConfig$$EnhancerBySpringCGLIB$$fba6dc42.CGLIB$springSocialDialect$0(<generated>) ~[spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE] at org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration$SpringSocialThymeleafConfig$$EnhancerBySpringCGLIB$$fba6dc42$$FastClassBySpringCGLIB$$decb8df3.invoke(<generated>) ~[spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE] at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.2.RELEASE.jar:4.3.2.RELEASE] at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356) ~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE] at org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration$SpringSocialThymeleafConfig$$EnhancerBySpringCGLIB$$fba6dc42.springSocialDialect(<generated>) ~[spring-boot-autoconfigure-1.4.0.RELEASE.jar:1.4.0.RELEASE] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_92] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_92] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_92] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_92] at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] ... 97 common frames omitted

ptahchiev commented 8 years ago

Any news on this? We have a pull-request and it's clearly a blocker as spring-boot users cannot use thymeleaf3 with spring-boot 1.4 because of spring-social:

https://github.com/spring-projects/spring-boot/issues/4858

nee-raj commented 8 years ago

+1

leon commented 7 years ago

There is a dirty workaround which is to exclude the SocialWebAutoConfiguration class and create your own which removes the faulty SpringSocialDialect.

@SpringBootApplication(exclude = SocialWebAutoConfiguration.class)
public class MyApplication {

In my case I don't use the dialect, which means I simply removed it.

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.social.UserIdSource;
import org.springframework.social.config.annotation.EnableSocial;
import org.springframework.social.config.annotation.SocialConfigurerAdapter;
import org.springframework.social.connect.ConnectionFactoryLocator;
import org.springframework.social.connect.ConnectionRepository;
import org.springframework.social.connect.UsersConnectionRepository;
import org.springframework.social.connect.web.*;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.view.BeanNameViewResolver;

import java.util.List;

/**
 * Overridden Spring Social configuration
 * We exclude it in PortalApplication.java and include this one instead which doesn't have the thymeleaf dialect
 */
@Configuration
@ConditionalOnClass({ ConnectController.class, SocialConfigurerAdapter.class })
@ConditionalOnBean({ ConnectionFactoryLocator.class, UsersConnectionRepository.class })
@AutoConfigureBefore(ThymeleafAutoConfiguration.class)
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class SocialWebAutoConfigurationOverride {

    @Configuration
    @EnableSocial
    @ConditionalOnWebApplication
    protected static class SocialAutoConfigurationAdapter
        extends SocialConfigurerAdapter {

        private final List<ConnectInterceptor<?>> connectInterceptors;

        private final List<DisconnectInterceptor<?>> disconnectInterceptors;

        private final List<ProviderSignInInterceptor<?>> signInInterceptors;

        public SocialAutoConfigurationAdapter(
            ObjectProvider<List<ConnectInterceptor<?>>> connectInterceptorsProvider,
            ObjectProvider<List<DisconnectInterceptor<?>>> disconnectInterceptorsProvider,
            ObjectProvider<List<ProviderSignInInterceptor<?>>> signInInterceptorsProvider) {
            this.connectInterceptors = connectInterceptorsProvider.getIfAvailable();
            this.disconnectInterceptors = disconnectInterceptorsProvider.getIfAvailable();
            this.signInInterceptors = signInInterceptorsProvider.getIfAvailable();
        }

        @Bean
        @ConditionalOnMissingBean(ConnectController.class)
        public ConnectController connectController(
            ConnectionFactoryLocator factoryLocator,
            ConnectionRepository repository) {
            ConnectController controller = new ConnectController(factoryLocator,
                repository);
            if (!CollectionUtils.isEmpty(this.connectInterceptors)) {
                controller.setConnectInterceptors(this.connectInterceptors);
            }
            if (!CollectionUtils.isEmpty(this.disconnectInterceptors)) {
                controller.setDisconnectInterceptors(this.disconnectInterceptors);
            }
            return controller;
        }

        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnProperty(prefix = "spring.social", name = "auto-connection-views")
        public BeanNameViewResolver beanNameViewResolver() {
            BeanNameViewResolver viewResolver = new BeanNameViewResolver();
            viewResolver.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return viewResolver;
        }

        @Bean
        @ConditionalOnBean(SignInAdapter.class)
        @ConditionalOnMissingBean
        public ProviderSignInController signInController(
            ConnectionFactoryLocator factoryLocator,
            UsersConnectionRepository usersRepository, SignInAdapter signInAdapter) {
            ProviderSignInController controller = new ProviderSignInController(
                factoryLocator, usersRepository, signInAdapter);
            if (!CollectionUtils.isEmpty(this.signInInterceptors)) {
                controller.setSignInInterceptors(this.signInInterceptors);
            }
            return controller;
        }

    }

    @Configuration
    @EnableSocial
    @ConditionalOnWebApplication
    @ConditionalOnMissingClass("org.springframework.security.core.context.SecurityContextHolder")
    protected static class AnonymousUserIdSourceConfig extends SocialConfigurerAdapter {

        @Override
        public UserIdSource getUserIdSource() {
            return new UserIdSource() {
                @Override
                public String getUserId() {
                    return "anonymous";
                }
            };
        }

    }

    @Configuration
    @EnableSocial
    @ConditionalOnWebApplication
    @ConditionalOnClass(SecurityContextHolder.class)
    protected static class AuthenticationUserIdSourceConfig
        extends SocialConfigurerAdapter {

        @Override
        public UserIdSource getUserIdSource() {
            return new SecurityContextUserIdSource();
        }

    }

    /*
    // REMOVED because it's causing thymeleaf 3 to not work
    @Configuration
    @ConditionalOnClass(SpringTemplateEngine.class)
    protected static class SpringSocialThymeleafConfig {

        @Bean
        @ConditionalOnMissingBean
        public SpringSocialDialect springSocialDialect() {
            return new SpringSocialDialect();
        }

    }*/

    private static class SecurityContextUserIdSource implements UserIdSource {

        @Override
        public String getUserId() {
            SecurityContext context = SecurityContextHolder.getContext();
            Authentication authentication = context.getAuthentication();
            Assert.state(authentication != null,
                "Unable to get a " + "ConnectionRepository: no user signed in");
            return authentication.getName();
        }

    }

}
habuma commented 7 years ago

Addressed by (1) extracting Thymeleaf 2 support into a separate module and (2) creating a new module for Thymeleaf 3.