1

I tried using the code from this answer to add multitenancy to my spring boot 1.2.5:

Setting up a MultiTenantConnectionProvider using Hibernate 4.2 and Spring 3.1.1

I get the following exception:

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.
        at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
        at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337)

The source code per the answer above is:

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestURITenantIdentifierResolver implements CurrentTenantIdentifierResolver {
    @Autowired
    private HttpServletRequest request;
    @Override
    public String resolveCurrentTenantIdentifier() {
        String[] pathElements = request.getRequestURI().split("/");
        String tenant = pathElements[1];
        return tenant;
    }
    @Override
    public boolean validateExistingCurrentSessions() {
        return true;
    }
}

I tried changing the scope value to prototype:

@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)

which works fine until I try to use @Query in my JpaRepository, e.g.:

@Query("From Order where orderId = :id")
public Order joinWithPurchaseItems(@Param("id") Integer id);

and it throws the same exception:

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.
        at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
        at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:337)

Interestingly using native queries doesn't throw this exception.

I also tried to use a RequestContextListener in my Application class with no success:

@SpringBootApplication
public class Application {

    @Bean
    @ConditionalOnMissingBean(RequestContextListener.class)
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    } 

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Any help is appreciated.

Community
  • 1
  • 1
Ali Wister
  • 11
  • 1
  • Request scope won't work. Remove the scope. Instead use `RequestContextHolder` to get the `RequestContext` and on the context do `getRequest`. Or use a `Filter` which puts something in a `ThreadLocal` and let your `CurrentTenantIdentifierResolver` use the `ThreadLocal`. Sample code can be found [here](https://github.com/mdeinum/spring-utils/tree/master/multi-tenant). Added advantage it is more generic and you can also use it for theming, resource loading etc. – M. Deinum Sep 20 '15 at 12:41
  • The filter approach worked fine. Thanks! I looked at the sample code and it has some interesting features that I think will be really useful if it had some more documentation.. – Ali Wister Sep 22 '15 at 07:54

1 Answers1

0

As suggested in the comment, I used a filter instead and captured the URL from there. The resolver captures the schema name from a static field set by the filter.

Ali Wister
  • 11
  • 1