0

In Spring it's easy to autowire beans and have them available anywhere in the app context. Beans can be specialized to a scope such as session/request/web socket etc.

I have a rather unique scenario. I receive a message from a message broker which means the request is not received in a "Controller". Because of this, Spring is not creating @RequestScope beans (All of this logic in Spring is based on using the @Controller/@RequestMapping annotations / DispatchServlet handler). Is there a way to create a bean within the request scope with the Spring AutowireCapableBeanFactory or some other way?

I want to do something like the below in which the SomeService.handle will be able to access the getName() method of the RequestScopeBean. Currently it throws this exception.

Exception:

BeanCreationException: Error creating bean with name ' 
scopedTarget.getRequestUtils': Scope 'request' is not active for the 
current thread; consider defining a scoped proxy for this bean

Code

@Service
public class MyMessagingReceiver implements SomeMessageReceiver {

    private final SomeService someService;

    @Autowired
    public MyMessagingReceiver(final SomeService someService) {
        this.someService = someService;
    }

    public void onMessage(MessageObject messageObject) {
        //possible here to use AutowireCapableBeanFactory in inject the RequestScopeBean bean?
        someService.handle(messageObject);
    }
}

@Service
public class SomeService {

    private final RequestScopeBean requestScopeBean;

    @Autowired
    public SomeService(RequestScopeBean requestScopeBean) {
        this.requestScopeBean = requestScopeBean;
    }

    public void handle(MessageObject messageObject) {
        System.out.println(this.requestScopeBean.getName());
    }

}

@Configuration
public class BeanDeclarations {
    @Bean
    @RequestScope
    public RequestScopeBean requestScopeBean() {
        return new RequestScopeBean();
    }
}

public RequestScopeBean {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class Interceptor extends HandlerInterceptorAdapter {
    private RequestScopeBean requestScopeBean;

    @Autowired
    public Interceptor(RequestScopeBean requestScopeBean) {
        this.requestScopeBean = requestScopeBean;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String name = request.getHeader("name");
        this.requestScopeBean.setName(name);
    }


} 
M. Deinum
  • 115,695
  • 22
  • 220
  • 224
GSUgambit
  • 4,459
  • 6
  • 25
  • 31
  • Why not annotate your message broker client with @Controller and get access to the context that way? I'm unclear what the reason is for opting not to do that. – sofend Nov 19 '18 at 23:32
  • Wow, let me actually try that, no idea why this didn't occur to me – GSUgambit Nov 20 '18 at 02:58
  • that did not work, probably because there is no @RequestMapping – GSUgambit Nov 20 '18 at 03:32
  • The answer to this one might help: https://stackoverflow.com/questions/15415688/spring-bean-custom-scope-jms – moilejter Nov 20 '18 at 05:13
  • 1
    No you cannot. As `request` and `session` scopes are tied to the web (and not related to `@Controller` it is the web that is important here). There is no web notion for in incoming message so no that will not work. – M. Deinum Nov 20 '18 at 09:18
  • You obviously have to scope it to the context where you're using it. @Controller by it self just has app-wide scope – sofend Nov 20 '18 at 22:16
  • @m-deinum I definitely ended up having to create a different scope to handle it – GSUgambit Nov 21 '18 at 13:45
  • then why don't try `@Prototype`? – Ryuzaki L Nov 21 '18 at 22:36

0 Answers0