Search code examples
javaspringspring-bootjerseymybatis

Switch Schema based on call from rest controller


We have two products: Product A and Product B and both have different rest controllers. Both of these controllers are calling the same common service and the common service calling the common dao methods. I want to select the schema in the common daos methods based on which products the call has been made. So for example, if the call is coming from the Product A controller then select schema as A or else B.

I wanted to use the same database connection and change the schema based on which controller the call is made. One possible solution would be to pass the schema name from the controller layer to the service layer which in turn passes it to the dao layer. I want to avoid having two different data sources and then switching between them dynamically.

So is there any other better way that we could do this?

Note: We are using Mybatis as our persistence layer.

Please find the sample code :

Controller for ProductA

@Component
public class ProductA{

    private final CommonService commonService;

    public ProductA(CommonService commonService){

            this.commonService = commonService;
    }

    @GET
    @Path("/test/dbSchema")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getTotalProducts(){
        // Calling common service method here to get total products

    }
}

Controller for ProductB

@Component
public class ProductB{
     private final CommonService commonService;

    public ProductA(CommonService commonService){

            this.commonService = commonService;
    }

    @GET
    @Path("/test/dbSchema")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getTotalProducts(){
        // Calling common service method here to get total products

    }
}

FYI: We are using Jersey


Solution

  • Thank you @ave for the response. I am able to solve it by using ThreadLocal as you mentioned. By setting the tenant id in the controller, I am able to get the particular tenant in the common service.

    Please find the updated code below:

    Controller for Product A

        @Component
        public class ProductA{
        
            private final CommonService commonService;
        
            public ProductA(CommonService commonService){
        
                    this.commonService = commonService;
            }
            public void setSchema(){
            TenantContext.setCurrentTenant("ProductA");}
    @GET
            @Path("/test/dbSchema")
            @Produces(MediaType.APPLICATION_JSON)
            public Response getTotalProducts(){
                 setSchema();
                // Calling common service method here to get total products
        }}
    

    Controller for Product B

     @Component
        public class ProductB{
             private final CommonService commonService;
        
            public ProductA(CommonService commonService){
        
                    this.commonService = commonService;
            }
            public void setSchema(){
                TenantContext.setCurrentTenant("ProductA");}
        
            @GET
            @Path("/test/dbSchema")
            @Produces(MediaType.APPLICATION_JSON)
            public Response getTotalProducts(){
            setSchema();
                // Calling common service method here to get total products
        
            }
        }