Error in autowiring a @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES) object

StackOverflow https://stackoverflow.com/questions/20924824

  •  24-09-2022
  •  | 
  •  

Question

I am trying to implement connection to service providers using spring social communication controllers as described in Spring Social reference doc here.

When initializing, the following service can not find the currentUser bean. I get the exception

 `Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.dynamease.serviceproviders.user.User com.dynamease.serviceproviders.SPResolver.currentUser; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.dynamease.serviceproviders.user.User] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

This happens when initializing the following service :

@Service
public class SPResolver {

public SPResolver() {
}

@Autowired
private User currentUser;

@Autowired
private ConnectionRepository connectionRepository;

 public void connectUser(String id) {
 currentUser.setId(id);
     }

public void disconnectUser() {
    this.currentUser = null;
}

And here is the configuration relevant configuration file part

@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public User currentUser() {
    return new User(null);
}

@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public ConnectionRepository connectionRepository() {
    String id = currentUser().getId();
    if (id == null) {
        throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
    }
    return usersConnectionRepository().createConnectionRepository(id);
}

I suspect that useing a "new User" for the bean definition might be the cause and the reason why in the spring sample they use static SecurityContext classes with user info encapsulated inside a threadlocal but did not find in the doc any convincing information about it. Thanks in advance for your help.

Était-ce utile?

La solution

Thanks to Sotirios answer and comments exchange, I read more carefully section 5.5 and 9.6 of Spring reference documentation and found out the problem :

It is ok to have singleton @Service (in my case the SPResolver) referencing session or request scoped beans if you ensure :

  1. that you use some kind of AOP proxy mechanism so that when the @Service is created initially and the scoped beans does not exist, a proxy is created that will then reference correctly the scoped beans during program execution. That is what I was actually doing in my initial code thru the @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES) line in the currentUser bean creation.
  2. The scoped beans needs to be referenced in the @Service thru an interface and not directly with a Java Class, which I was not doing for the User class. Actually, the copy-paste example I took for the ConnectionRepository Bean was working as ConnectionRepository is an Interface.

Here is the working configuration class code :

@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public CurrentUserContext currentUser() {
    return new CurrentUserContextImpl();
}

@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public ConnectionRepository connectionRepository() {
    String id = currentUser().getId();
    if (id == null) {
        throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
    }
    return usersConnectionRepository().createConnectionRepository(id);
}

and the @Service declarations :

@Service
public class SPResolver {

public SPResolver() {
}

@Autowired
private CurrentUserContext currentUser;

@Autowired
private ConnectionRepository connectionRepository;

Autres conseils

Your SPResolver class is a @Service with default singleton scope. As such, it will be initialized at startup.

Your User bean is request scope so a new instance can be created for each request.

However, at startup, there is no such request and therefore a User bean cannot be injected, because it does not exist.


That may not be the root cause here. It seems more likely that you're not scanning the right configs, but you will get the above problem eventually.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top