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.
JPA will need the appropriate repository class.
@Repository
Interface ResourceRepository extends JPARepository<Resource, Long>
{
}
A corresponding service class change for transactionality
@Service
@Transactional
class AResourceService {
private ResourceRepository resourceRepository;
}
Since the above will be partitioned based on tenants, one service could connect to different databases or schemas with:
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