Struts2 и Hibernate - доступ к ActionContext.getContext (). GetSession () вне сервлета

Я пытаюсь получить доступ к ActionContext.getContext () вне действия Struts (Struts2) в двух разных ситуациях, и я получаю другой результат в зависимости от того, откуда я пытаюсь:

  1. Из CurrentTenantIdentifierResolverImpl (моя) реализация CurrentTenantIdentifierResolver, который является интерфейсом Hibernate -> KO (результат равен нулю)
  2. Из AbstractRoutingDataSource (моя) реализация AbstractDataSource, которая является интерфейсом Spring -> OK

Я нашел другое решение, чтобы мой CurrentTenantIdentifierResolverImpl работал с использованием ThreadLocal, но:

  1. Почему он работает для Spring, а не для Hibernate?
  2. Почему я не могу получить доступ к ActionContext (также ThreadLocal), где я могу получить доступ к MY ThreadLocal (который я установил точно так же, как ActionContext, в том же месте, с теми же данными)?

CurrentTenantIdentifierResolverImpl: должен предоставить используемый клиент, чтобы спящий режим мог предоставить соединение с хорошей базой данных.

import java.util.Map;
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
import com.opensymphony.xwork2.ActionContext;

public class CurrentTenantIdentifierResolverImpl implements CurrentTenantIdentifierResolver {

@Override
public String resolveCurrentTenantIdentifier() {

    if (ActionContext.getContext() != null) {

AbstractRoutingDataSource: то же самое, но обрабатывается Spring

import java.util.Map;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import com.opensymphony.xwork2.ActionContext;

public class RoutingDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {

        if (ActionContext.getContext() != null) {

Когда я смотрю на стек в обоих случаях, я вижу следующее:

  • AbstractRoutingDataSource имеет мой сервлет (HomeAction) в стеке
  • CurrentTenantIdentifierResolver не имеет моего сервлета (HomeAction) в стеке

Вот следы стека.

Спящий режим:

Daemon Thread [http-bio-8081-exec-4] (Suspended (breakpoint at line 24 in CurrentTenantIdentifierResolverImpl)) 
    owns: SocketWrapper<E>  (id=184)    
    CurrentTenantIdentifierResolverImpl.resolveCurrentTenantIdentifier() line: 24   
    SessionFactoryImpl$SessionBuilderImpl.<init>(SessionFactoryImpl) line: 1572 
    SessionFactoryImpl.withOptions() line: 1019 
    SessionFactoryImpl.openSession() line: 999  
    OpenSessionInViewFilter.openSession(SessionFactory) line: 203   
    OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 139    
    OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107  
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88 
    CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107  
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    StandardWrapperValve.invoke(Request, Response) line: 222    
    StandardContextValve.invoke(Request, Response) line: 123    
    NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502    
    StandardHostValve.invoke(Request, Response) line: 171   
    ErrorReportValve.invoke(Request, Response) line: 100    
    AccessLogValve.invoke(Request, Response) line: 953  
    StandardEngineValve.invoke(Request, Response) line: 118 
    CoyoteAdapter.service(Request, Response) line: 408  
    Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1041    
    Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 603   
    JIoEndpoint$SocketProcessor.run() line: 312 
    ThreadPoolExecutor(ThreadPoolExecutor).runWorker(ThreadPoolExecutor$Worker) line: 1145  
    ThreadPoolExecutor$Worker.run() line: 615   
    TaskThread(Thread).run() line: 722

Весна:

Daemon Thread [http-bio-8081-exec-2] (Suspended (breakpoint at line 20 in RoutingDataSource))   
    owns: SocketWrapper<E>  (id=562)    
    RoutingDataSource.determineCurrentLookupKey() line: 20  
    RoutingDataSource(AbstractRoutingDataSource).determineTargetDataSource() line: 196  
    RoutingDataSource(AbstractRoutingDataSource).getConnection() line: 164  
    DatasourceConnectionProviderImpl.getConnection() line: 139  
    AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection() line: 380  
    LogicalConnectionImpl.obtainConnection() line: 228  
    LogicalConnectionImpl.getConnection() line: 171 
    StatementPreparerImpl.connection() line: 63 
    StatementPreparerImpl$5.doPrepare() line: 162   
    StatementPreparerImpl$5(StatementPreparerImpl$StatementPreparationTemplate).prepareStatement() line: 186    
    StatementPreparerImpl.prepareQueryStatement(String, boolean, ScrollMode) line: 160  
    QueryLoader(Loader).prepareQueryStatement(String, QueryParameters, LimitHandler, boolean, SessionImplementor) line: 1885    
    QueryLoader(Loader).executeQueryStatement(String, QueryParameters, boolean, List<AfterLoadAction>, SessionImplementor) line: 1862   
    QueryLoader(Loader).executeQueryStatement(QueryParameters, boolean, List<AfterLoadAction>, SessionImplementor) line: 1839   
    QueryLoader(Loader).doQuery(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 910  
    QueryLoader(Loader).doQueryAndInitializeNonLazyCollections(SessionImplementor, QueryParameters, boolean, ResultTransformer) line: 355   
    QueryLoader(Loader).doList(SessionImplementor, QueryParameters, ResultTransformer) line: 2554   
    QueryLoader(Loader).listUsingQueryCache(SessionImplementor, QueryParameters, Set<Serializable>, Type[]) line: 2399  
    QueryLoader(Loader).list(SessionImplementor, QueryParameters, Set<Serializable>, Type[]) line: 2362 
    QueryLoader.list(SessionImplementor, QueryParameters) line: 497 
    QueryTranslatorImpl.list(SessionImplementor, QueryParameters) line: 387 
    HQLQueryPlan.performList(QueryParameters, SessionImplementor) line: 236 
    SessionImpl.list(String, QueryParameters) line: 1264    
    QueryImpl.list() line: 103  
    HibernateTemplate$29.doInHibernate(Session) line: 875   
    HibernateTemplate$29.doInHibernate(Session) line: 864   
    HibernateTemplate.doExecute(HibernateCallback<T>, boolean) line: 340    
    HibernateTemplate.executeWithNativeSession(HibernateCallback<T>) line: 308  
    HibernateTemplate.find(String, Object...) line: 864 
    AideGestionDaoImpl(GenericHibernateDAO<T,ID>).find(String, Object...) line: 92  
    AideGestionDaoImpl.findByGerantAndDate(Long, Date) line: 54 
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
    Method.invoke(Object, Object...) line: 597  
    AopUtils.invokeJoinpointUsingReflection(Object, Method, Object[]) line: 317 
    ReflectiveMethodInvocation.invokeJoinpoint() line: 190  
    ReflectiveMethodInvocation.proceed() line: 157  
    MethodInvocationProceedingJoinPoint.proceed() line: 85  
    DAOAudit.daoProfiling(ProceedingJoinPoint) line: 30 
    GeneratedMethodAccessor101.invoke(Object, Object[]) line: not available 
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
    Method.invoke(Object, Object...) line: 597  
    AspectJAroundAdvice(AbstractAspectJAdvice).invokeAdviceMethodWithGivenArgs(Object[]) line: 621  
    AspectJAroundAdvice(AbstractAspectJAdvice).invokeAdviceMethod(JoinPoint, JoinPointMatch, Object, Throwable) line: 610   
    AspectJAroundAdvice.invoke(MethodInvocation) line: 68   
    ReflectiveMethodInvocation.proceed() line: 168  
    ExposeInvocationInterceptor.invoke(MethodInvocation) line: 92   
    ReflectiveMethodInvocation.proceed() line: 179  
    JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 207   
    $Proxy108.findByGerantAndDate(Long, Date) line: not available   
    HomeAction.buildTabSyn() line: 241  
    NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]  
    NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39  
    DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25  
    Method.invoke(Object, Object...) line: 597  
    DefaultActionInvocation.invokeAction(Object, ActionConfig) line: 450    
    DefaultActionInvocation.invokeActionOnly() line: 289    
    DefaultActionInvocation.invoke() line: 252  
    ParametersInterceptor.doIntercept(ActionInvocation) line: 239   
    ParametersInterceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98 
    DefaultActionInvocation.invoke() line: 246  
    ActionMappingParametersInteceptor(ParametersInterceptor).doIntercept(ActionInvocation) line: 239    
    ActionMappingParametersInteceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98 
    DefaultActionInvocation.invoke() line: 246  
    MultiselectInterceptor.intercept(ActionInvocation) line: 73 
    DefaultActionInvocation.invoke() line: 246  
    CheckboxInterceptor.intercept(ActionInvocation) line: 91    
    DefaultActionInvocation.invoke() line: 246  
    PrepareInterceptor.doIntercept(ActionInvocation) line: 171  
    PrepareInterceptor(MethodFilterInterceptor).intercept(ActionInvocation) line: 98    
    DefaultActionInvocation.invoke() line: 246  
    ServletConfigInterceptor.intercept(ActionInvocation) line: 164  
    DefaultActionInvocation.invoke() line: 246  
    ExceptionLoggingInterceptor(ExceptionMappingInterceptor).intercept(ActionInvocation) line: 189  
    DefaultActionInvocation.invoke() line: 246  
    StrutsActionProxy.execute() line: 54    
    Dispatcher.serviceAction(HttpServletRequest, HttpServletResponse, ServletContext, ActionMapping) line: 563  
    ExecuteOperations.executeAction(HttpServletRequest, HttpServletResponse, ActionMapping) line: 77    
    StrutsPrepareAndExecuteFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 99   
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    ResponseOverrideFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 125 
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    SessionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 52   
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    UserLogFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 43   
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 330 
    FilterSecurityInterceptor.invoke(FilterInvocation) line: 118    
    FilterSecurityInterceptor.doFilter(ServletRequest, ServletResponse, FilterChain) line: 84   
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    ExceptionTranslationFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 113 
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    SessionManagementFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 103    
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    AnonymousAuthenticationFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 113  
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    SecurityContextHolderAwareRequestFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 150    
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    RequestCacheAwareFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 45 
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    UsernamePasswordAuthenticationFilter(AbstractAuthenticationProcessingFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 199   
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    LogoutFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 110   
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    WebAsyncManagerIntegrationFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 50    
    WebAsyncManagerIntegrationFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107 
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    ConcurrentSessionFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 125    
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    SecurityContextPersistenceFilter.doFilter(ServletRequest, ServletResponse, FilterChain) line: 87    
    FilterChainProxy$VirtualFilterChain.doFilter(ServletRequest, ServletResponse) line: 342 
    FilterChainProxy.doFilterInternal(ServletRequest, ServletResponse, FilterChain) line: 192   
    FilterChainProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 160   
    DelegatingFilterProxy.invokeDelegate(Filter, ServletRequest, ServletResponse, FilterChain) line: 344    
    DelegatingFilterProxy.doFilter(ServletRequest, ServletResponse, FilterChain) line: 261  
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 150    
    OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107  
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    OpenSessionInViewFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 150    
    OpenSessionInViewFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107  
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88 
    CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 107  
    ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243  
    ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210  
    StandardWrapperValve.invoke(Request, Response) line: 222    
    StandardContextValve.invoke(Request, Response) line: 123    
    NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 502    
    StandardHostValve.invoke(Request, Response) line: 171   
    ErrorReportValve.invoke(Request, Response) line: 100    
    AccessLogValve.invoke(Request, Response) line: 953  
    StandardEngineValve.invoke(Request, Response) line: 118 
    CoyoteAdapter.service(Request, Response) line: 408  
    Http11Processor(AbstractHttp11Processor<S>).process(SocketWrapper<S>) line: 1041    
    Http11Protocol$Http11ConnectionHandler(AbstractProtocol$AbstractConnectionHandler<S,P>).process(SocketWrapper<S>, SocketStatus) line: 603   
    JIoEndpoint$SocketProcessor.run() line: 312 
    ThreadPoolExecutor$Worker.runTask(Runnable) line: 895   
    ThreadPoolExecutor$Worker.run() line: 918   
    TaskThread(Thread).run() line: 662  

person Charles    schedule 01.04.2015    source источник
comment
Как вы думаете, почему контекст действия должен быть доступен вне вызова действия?   -  person Roman C    schedule 02.04.2015
comment
1 - Потому что это ThreadLocal, поэтому данные прикрепляются к текущему потоку, что, похоже, означает со Struts: для моего пользовательского сеанса. 2 - Потому что в одном случае я могу получить к нему доступ извне (случай Spring).   -  person Charles    schedule 02.04.2015
comment
Можете ли вы опубликовать трассировки стека для обоих случаев?   -  person Roman C    schedule 02.04.2015
comment
Думаю, запроса нет.   -  person Aleksandr M    schedule 02.04.2015
comment
Вот трассировки стека Roman C.   -  person Charles    schedule 03.04.2015
comment
StrutsPrepareAndExecuteFilter не выполняется в вашем первом случае.   -  person Aleksandr M    schedule 07.04.2015


Ответы (1)


Кажется, что ActionContext инициализирован фильтром StrutsPrepareAndExecuteFilter:

doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        try {
            prepare.setEncodingAndLocale(request, response);
            prepare.createActionContext(request, response);

И в моем случае "гибернации" этот фильтр не выполняется (см. Трассировку стека в моем вопросе) ==> ActionContext не инициализируется.

Итак, заключение: Да, вы можете получить доступ к ActionContext вне сервлета, но если ваш стек является «классическим». Будьте осторожны, если вы попытаетесь получить к нему доступ из фреймворка или трансверсального кода.

Вот мое решение моей проблемы с Hibernate: я создал свой собственный фильтр, который обращается к HttpSession (у нас есть доступ отсюда) и помещаю необходимую мне информацию в ThreadLocal.

Мой фильтр:

public class TenantIdentifierFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(
            HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        HttpSession session = request.getSession();
        String tenantCode = (String) session.getAttribute(WorkSession.CONNECTED_ENTITY);
        UserTenantContext.set(tenantCode);
        logger.debug("VPD-MultiTenancy - tenantCode : " + tenantCode);
        filterChain.doFilter(request, response);
    }

}

Моя тема

public class UserTenantContext {

    public static final ThreadLocal<String> userTenantCode = new ThreadLocal<String>();

    /**
     * Set user in the context of the ThreadLocal
     * @param user
     */
    public static void set(String tenantCode) {
        userTenantCode.set(tenantCode);
    }

    public static void unset() {
        userTenantCode.remove();
    }

    /**
     * @return get user in the context of the ThreadLocal
     */
    public static String get() {
        return userTenantCode.get();
    }
}

Мой web.xml (убедитесь, что ваш фильтр установлен ПЕРЕД фильтром гибернации, чтобы ваш ThreadLocal был инициализирован):

    ...
    <filter-mapping>
            <filter-name>characterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

        <!-- VPD-MultiTenancy-ADD-->
        <filter>
            <filter-name>tenantFilter</filter-name>
            <filter-class>
                amundi.sits.mgs.web.services.user.TenantIdentifierFilter
            </filter-class>
        </filter>
        <filter-mapping>
            <filter-name>tenantFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        <!-- VPD-MultiTenancy-ADD/ -->

        <filter>
            <filter-name>hibernateFilter</filter-name>
            <filter-class>
                org.springframework.orm.hibernate4.support.OpenSessionInViewFilter
            </filter-class>
        </filter>
        <filter-mapping>
            <filter-name>hibernateFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
  ...
person Charles    schedule 10.04.2015