I want to create a UUID that is unique in a request life cycle.
To do this, I create a UUID bean with the @Scope("request") annotation.
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST)
public UUID requestUUID() {
return UUID.randomUUID();
}
I want to access this bean in my controller. So I inject it with @Autowired.
This works fine.
@Controller
public class DashboardController {
@Autowired
UUID uuid;
@Autowired
WelcomeMessageService welcomeMessageService;
@Autowired
IssueNotificationService issueNotificationService;
@RequestMapping("/")
public String index(Model model) throws InterruptedException, ExecutionException {
System.out.println(uuid);
PortalUserDetails userLog = getPortalUserDetails();
BusinessObjectCollection<WelcomeMessage> welcomeMessages = welcomeMessageService.findWelcomeMessages(
20,
0,
userLog.getZenithUser(),
userLog.getConnectionGroup().getConnectionGroupCode(),
"FR");
if(welcomeMessages!=null) {
model.addAttribute("welcomeMessages", welcomeMessages.getItems());
}
BusinessObjectCollection<IssueNotification> issueNotifications =
issueNotificationService.findIssueNotifications(userLog.getZenithUser());
if(welcomeMessages!=null) {
model.addAttribute("welcomeMessages", welcomeMessages.getItems());
}
model.addAttribute("issueNotifications", issueNotifications);
return "index";
}
}
The controller call multiple services. Every service use a RestTemplate bean. In this RestTemplate bean, I want to get the UUID.
@Component
public class ZenithRestTemplate extends RestTemplate {
@Autowired
private UUID uuid;
public void buildRestTemplate() {
List restTemplateInterceptors = new ArrayList();
restTemplateInterceptors.add(new HeaderHttpRequestInterceptor("UUID", uuid.toString()));
this.setInterceptors(restTemplateInterceptors);
}
}
When I try to inject the UUID here, I have an error :
Error creating bean with name 'zenithRestTemplate': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.UUID com.geodis.rt.zenith.framework.webui.service.ZenithRestTemplate.uuid; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestUUID': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
What can I do to access my UUID bean inside the RestTemplate bean ?
My project use Spring-MVC, Spring-boot with java configuration.
I already tried to add a RequestContextListener but it doesn't solve the problem.
@Bean public RequestContextListener requestContextListener(){
return new RequestContextListener();
}
Best Answer
I think you need to mark your
UUID
request scoped bean like:Where controller is
singleton
scoped bean you are injectingrequest
scoped bean in it. As singleton beans are injected only once per their lifetime you need to provide scoped beans as proxies which takes care of that.Another option is to instead use the
org.springframework.web.context.annotation.RequestScope
annotation:@RequestScope
is a meta-annotation on@Scope
that 1) sets thescope
to"request"
and 2) sets theproxyMode
toScopedProxyMode.TARGET_CLASS
so you don't have to do it every time you want to define a request-scoped bean.Edit:
Note that you may need to add
@EnableAspectJAutoProxy
on your main configuration class.