Announcement Announcement Module
Collapse
No announcement yet.
Strange behavior in SignInInterceptor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Strange behavior in SignInInterceptor

    In my config class I define my Interceptor in the usual way:

    Code:
    @Bean
    public ProviderSignInController providerSignInController(RequestCache requestCache) {
        ProviderSignInController signInController = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository,
                new MySignInAdapter(requestCache, userRepository, userAliasRepository));
        signInController.addSignInInterceptor(new MyProviderSignInInterceptor());
        return signInController;
    }
    where my interceptor is defined this way:

    Code:
    public class MyProviderSignInInterceptor implements ProviderSignInInterceptor<Facebook> { .. }
    And everything works as expected.

    What I find strange is that if the interceptor class is defined using generics in this way:
    Code:
    public class MyProviderSignInInterceptor<T> implements ProviderSignInInterceptor<T> { .. }
    and instantiated with Facebook this way:

    Code:
    @Bean
    public ProviderSignInController providerSignInController(RequestCache requestCache) {
        ProviderSignInController signInController = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository,
                new MySignInAdapter(requestCache, userRepository, userAliasRepository));
        signInController.addSignInInterceptor(new MyProviderSignInInterceptor<Facebook>());
        return signInController;
    }
    then the interceptor methods are not called.

    Is that normal, and if yes, why? I could not get it

  • #2
    I've another, related problem, making the thing worse

    My interceptor does work on the database so I would like to be transactional as any other service class, so I added the @Transactional annotation and tried to define it as a bean in my SocialConfig class this way:

    Code:
    @Bean
    public ProviderSignInInterceptor<Facebook> providerSignInInterceptor() {
      return new MyProviderSignInInterceptor(userAliasRepository, userRepository, gruppoRepository);
    }
    And then modifying the method to build a ProviderSignInController this way:
    Code:
    @Bean
    public ProviderSignInController providerSignInController(RequestCache requestCache) {
        ProviderSignInController signInController = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository,
                new MySignInAdapter(requestCache, userRepository, userAliasRepository));
        signInController.addSignInInterceptor(providerSignInInterceptor());
        return signInController;
    }
    But as before, the interceptor is not being called.

    I digged a bit in the spring social sources and the problems seems that it uses GenericTypeResolver.resolveTypeArgument() to check the class type, but the call returns null if the class is defined as a bean.

    This is the code to check the problem:
    Code:
    ProviderSignInInterceptor<Facebook> signInInterceptor = new MyProviderSignInInterceptor(userAliasRepository, userRepository, gruppoRepository);
    Class<?> serviceApiType = GenericTypeResolver.resolveTypeArgument(signInInterceptor.getClass(), ProviderSignInInterceptor.class);
    logger.debug("serviceApiType: " + serviceApiType + " interceptor: " + signInInterceptor);
    that when executed gives:
    serviceApiType: interface org.springframework.social.facebook.api.Facebook
    interceptor: it.example.signin.MyProviderSignInInterceptor@5f1b 0fee
    Code:
    ProviderSignInInterceptor<Facebook> signInInterceptor = providerSignInInterceptor();
    Class<?> serviceApiType = GenericTypeResolver.resolveTypeArgument(signInInterceptor.getClass(), ProviderSignInInterceptor.class);
    logger.debug("serviceApiType: " + serviceApiType + " interceptor: " + signInInterceptor);
    that gives:
    serviceApiType: null
    interceptor: it.example.signin.MyProviderSignInInterceptor@1920 6bfb
    This goes deep into Spring code and I suspect a bug but I really don't know how to solve it.
    Any takers? Habema?

    Comment


    • #3
      [Bump]

      Any help with this?

      Is it better I open a bug report for this problem?

      Comment


      • #4
        Although I can see it desirable to have the interceptor behave in a transaction, it was never designed to be configured that way. Thus, I'm not terribly surprised that you get the problem that you're having.

        At the root of the problem is some code that determines if an interceptor should be run or not by considering whether the interceptor serves the provider for which a connection is being made. It does this by considering what generic type the interceptor is parameterized with. And, unfortunately, generics get a bit gnarled up when you declare a genericized class as a bean. I'm not saying that it's impossible to accomplish what you're trying to do...it's just not all that simple.

        That said, you bring up a good point. Perhaps you could open an improvement (not a bug) issue at https://jira.springsource.org/browse/SOCIAL to address this. I can't promise a timeframe on a resolution, but if you get it into the mix, then it can be considered.

        In the meantime, I don't see why you couldn't inject the interceptor with some other bean that is transactional. E.g.,

        Code:
        @Bean
        public ProviderSignInController providerSignInController(RequestCache requestCache, SomeTransactionalService service) {
            ProviderSignInController signInController = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository,
                    new MySignInAdapter(requestCache, userRepository, userAliasRepository));
            signInController.addSignInInterceptor(new MyProviderSignInInterceptor(service));
            return signInController;
        }
        And then make SomeTransactionalService a transactional bean. Yeah, it adds a bit of indirection to the mix, but I suspect it would work.

        Comment


        • #5
          Hello Craig, and thanks for the reply.
          Yes, I'm using a service now and it kind of works, even if it is suboptimal.

          I understand it can be difficult to use a bean since it is a proxy and all the rest, yet I suspect a problem on the GenericTypeResolver.resolveTypeArgument() function because it's able to use the class (a simple class, not a spring bean) if defined this way:

          public class MyProviderSignInInterceptor<T> implements ProviderSignInInterceptor<T> { .. }

          That should work, isn't?

          Comment

          Working...
          X