Thursday, October 27, 2022

 Multitenant fullstack application implementation using open source. 

This part of the book explores open source implementation of multi-tenant applications specifically, with Spring Boot, JPA, Hibernate, and Flyway.  Many open source implementations such as Atlassian, Jira, Confluence, Trello, or BitBucket are quite popular.  

With a Java based stack for frontend and backend, the following changes would be required. 

  1. JPA will need the appropriate repository class.  

  1. @Repository 

Interface ResourceRepository extends JPARepository<Resource, Long> 

{ 

} 

  1.  A corresponding service class change for transactionality 

  1. @Service 

@Transactional 

class AResourceService { 

private ResourceRepository resourceRepository; 

} 

  1. Since the above will be partitioned based on tenants, one service could connect to different databases or schemas with: 

  1. A request interceptor that sets the appropriate tenant in the context using Spring: 

public abstract class TenantContext { 

public static ThreadLocal<String> currentTenant = new ThreadLocal<String>(); 

public static void setCurrentTenant(String tenant) { 

currentTenant.set(tenant); 

} 

public static string getCurrentTenant() { 

return currentTenant.get(); 

} 

public static void clear() { 

return currentTenant.remove(); 

} 

} 

And with the corresponding: 

@Component 

public class TenantRequestInterceptor implements 

AsyncHandlerInterceptor { 

private SecurityDomain securityDomain; 

public TenantRequestInterceptor(SecurityDomain securityDomain) { 

this.securityDomain = securityDomain; 

} 

@Override 

Public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 

Return Optional.OfNullable(request) 

.map(req -> securityDomain.getTenantIdFromJwt(req)) 

.map(tenant->SetTenantContext(tenant)) 

.orElse(false); 

} 

 

@Override 

Public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { 

TenantContext.clear(); 

} 

 

private boolean setTenantContext(String tenant)  

{ 

TenantContext.setCurrentTenant(tenant); 

return true;  

} 

} 

 

Finally, we just need to register this: 

@Configuration 

public class WebConfiguration implements WebMvcConfigurer { 

  

      @Autowired 

 private TenantRequestInterceptor tenantInterceptor; 

         

      @Override 

 public void addInterceptors(InterceptorRegistry registry) { 

     registry.addInterceptor(tenantInterceptor).addPathPatterns("/**"); 

 } 

         

} 

No comments:

Post a Comment