web-dev-qa-db-fra.com

Utilisation d'un bean à portée de requête en dehors d'une requête Web réelle

J'ai une application Web qui a une logique d'intégration Spring en cours d'exécution avec elle dans un thread séparé. Le problème est qu'à un moment donné, ma logique d'intégration Spring essaie d'utiliser un bean à portée de demande, puis j'obtiens les erreurs suivantes:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.tenantContext': 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.


Caused by: 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.

J'ai l'ensemble ContextLoaderListener:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

Mon Scoped Bean est annoté comme ça (puisque j'ai entendu que le proxy de mon bean aiderait):

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)  
public class TenantContext  implements Serializable {

Ce que je fais est-il possible? Si oui, que me manque-t-il ici? Si non, avez-vous d'autres suggestions sur la façon d'y parvenir?

21
Diego Urenia

Vous ne pouvez utiliser que des beans étendus par requête (et session) sur le thread du conteneur Web sur lequel la requête s'exécute.

Je suppose que le thread attend une réponse asynchrone de votre flux SI?

Si c'est le cas, vous pouvez lier le bean à portée de requête au message, peut-être dans un en-tête ou quelque part dans la charge utile.

10
Gary Russell

Pour les cadres Spring 4, ajoutez servletContext.addListener (new RequestContextListener ());

public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { RootConfiguration.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[] { WebMvcConfiguration.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] { new HiddenHttpMethodFilter() };
    }

    **@Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        servletContext.addListener(new RequestContextListener());
    }**
}
13
Deepak

Utilisez RequestContextFilter avec la propriété threadContextInheritable définie sur true. Cela fait que le thread enfant hérite du contexte du parent, qui contient l'objet de requête lui-même. Assurez-vous également que l'exécuteur ne réutilise pas les threads du pool, car l'objet de demande est très spécifique à cette demande et ne peut pas être partagé entre différentes demandes. Un tel exécuteur est SimpleAsyncTaskExecutor.

Pour plus d'informations, reportez-vous à la portée de la session n'est pas active pour le thread actuel; IllegalStateException: aucune demande liée au thread trouvée .

10
Thilak