suportando aplicações multi-tenancy com java ee
DESCRIPTION
Apresentação realizada no evento The Developers Conference 2014 (TDC 2014).TRANSCRIPT
Globalcode – Open4education
Suportando Aplicações Multi-tenancy com Java EE
Rodrigo Cândido da Silva @rcandidosilva
Globalcode – Open4education
Agenda
! Modelos de Serviço ! SaaS Market ! Multi-tenancy
! Desafios ! Pros and Cons ! Tipos de Implementação
! Java EE + Multi-tenancy ! Segurança + Multi-tenancy ! Cloud + Multi-tenancy ! JVM Multi-tenancy
Globalcode – Open4education
Multi-tenancy
! Uma única instância da aplicação atendendo múltiplos clientes (tenant)
! Contrário da
arquitetura de múltiplas instâncias
Globalcode – Open4education
Desafios
! Separação dos dados ! Personalização ! Controle de acesso ! Provisionamento de recursos ! Integrações ! Atualização da aplicação ! Recuperação à falhas
Globalcode – Open4education
Pros and Cons
! Pros ! Reduz o custo de manutenção
! Único código para todos os clientes ! Aumenta a escalabilidade
! Beneficia compartilhamento recursos entre clientes
! Cons ! Aumenta a complexidade
! Separação por tenant-id ! Maior risco de falhas
! Quebra da aplicação compartilhada para todos clientes ! Reduz a flexibilidade para os clientes
Globalcode – Open4education
Multi-tenancy
! 4 possíveis níveis implementações ! Nível 1 (Personalizado)
! [N] aplicações e [N] databases ! Nível 2 (Configurável)
! [1] aplicação e [N] databases
! Nível 3 (Configurável e eficiente) ! [N] aplicações e [1] database
! Nível 4 (Escalável, configurável e eficiente) ! [1] aplicação e [1] database
Globalcode – Open4education
Java EE + Multi-tenancy
! Database ! JPA + Multi-tenancy
! Customização UI ! JSF + Multi-tenancy
! Segurança ! Java EE 8 com suporte Cloud
Globalcode – Open4education
JPA + Multi-tenancy
! EclipseLink ! Suporte a multi-tenancy @Multitenant ! Disponibiliza 3 estratégias
! @Multitenant(SINGLE_TABLE) – default ! @Multitenant(TABLE_PER_TENANT) ! @Multitenant(VPD)
! Shared Cache by tenant
Globalcode – Open4education
EclipseLink SINGLE_TABLE @Entity @Table(name=“EMP”) @Multitenant(SINGLE_TABLE) @TenantDiscriminatorColumn(name = “TENANT_ID”, contextProperty = “tenant-id”) public class Employee { ... }
HashMap properties = new HashMap(); properties.put("tenant.id", "707"); ... EntityManager em = Persistence .createEntityManagerFactory( "multi-tenant”,properties) .createEntityManager();
<persistence-unit name="multi-tenant"> ... <properties> <property name="tenant.id" value="707"/> ... </properties> </persistence-unit>
Globalcode – Open4education
EclipseLink TABLE_PER_TENANT <entity class="Employee"> <multitenant type="TABLE_PER_TENANT"> <tenant-table-discriminator type="SCHEMA" context-property="eclipselink.tenant-id"/> </multitenant> <table name="EMP"> ... </entity>
@Entity @Table(name=“EMP”) @Multitenant(TABLE_PER_TENANT) @TenantTableDiscriminator(type=SCHEMA, contextProperty="eclipselink.tenant-id") public class Employee { ... }
Globalcode – Open4education
EclipseLink VPD
@Entity @Multitenant @TenantDiscriminatorColumn(name = "USER_ID", contextProperty = "tenant.id") @Cacheable(false) public class Task implements Serializable { ...
CALL DBMS_RLS.ADD_POLICY ('SCOTT', 'TASK', 'todo_list_policy', 'SCOTT', 'ident_func', 'select, update, delete'));
<properties> <property name="eclipselink.session.customizer" value="example.VPDSessionCustomizer" /> <property name="eclipselink.session-event-listener" value="example.VPDSessionEventAdapter" /> <property name="eclipselink.jdbc.exclusive-connection.mode" value="Always" /> </properties>
Globalcode – Open4education
JSF + Multi-tenancy
! Arquitetura extensível ! Artefatos podem ser encapsulados em JARs ! Composição at runtime ! Templates ! Resource library ! Look-and-feel customization ! RenderKit ! Localization
Globalcode – Open4education
JSF Facelets
The Facelets Gazette
SiteNavigation
●Events
●Docs
●Forums
About Contact Site Map
Template File name _template.html
Insertion points
Resourcescss classes, scripts, images
Globalcode – Open4education
JSF Multi-templating
contractA
• Declared Templates• Declared Insertion Points• Declared Resources
contractB
• Declared Templates• Declared Insertion Points• Declared Resources
contractC
• Declared Templates• Declared Insertion Points• Declared Resources
<web-app-root>/contractscontractD
• Declared Templates• Declared Insertion Points• Declared Resources
contractE
• Declared Templates• Declared Insertion Points• Declared Resources
contractF
• Declared Templates• Declared Insertion Points• Declared Resources
JAR files in WEB-INF/lib
contractA
• Declared Templates• Declared Insertion Points• Declared Resources
contractB
• Declared Templates• Declared Insertion Points• Declared Resources
contractC
• Declared Templates• Declared Insertion Points• Declared Resources
<web-app-root>/contractscontractD
• Declared Templates• Declared Insertion Points• Declared Resources
contractE
• Declared Templates• Declared Insertion Points• Declared Resources
contractF
• Declared Templates• Declared Insertion Points• Declared Resources
JAR files in WEB-INF/lib
Set of available contracts
Facelet 1 Facelet 3Facelet 2
faces-config.xml
Globalcode – Open4education
JSF Multi-templating
<html xmlns="http://www.w3.org/1999/xhtml” xmlns:h="http://java.sun.com/jsf/html” xmlns:ui="http://java.sun.com/jsf/facelets"> <body> <ui:composition template="#{template}”> ... </ui:composition> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <web-app> <context-param> <param-name>javax.faces.view.TEMPLATE</param-name> <param-value>mybusiness</param-value> </context-param> </web-app>
Globalcode – Open4education
Segurança + Multi-tenancy
! PicketLink ! Java EE security framework ! Identity Management (IDM) ! Federation support (SAML, OAuth2, OpenID) ! Social Login support ! Multi-tenancy support
Globalcode – Open4education
Picketlink @Named public class RealmSelector implements Serializable { @Inject private PartitionManager partitionManager; private Realm realm; @Produces @PicketLink public Realm select() { return this.realm; } … }
@RequestScoped public class LoginController { @Inject private Identity identity; public String login() { this.identity.login(); … } public String logout() { this.identity.logout(); return "/home.xhtml"; } }
public class Resources { public enum REALM {acme, umbrella, wayne} @Produces @Named("supportedRealms") public Enum[] supportedRealms() { return REALM.values(); }
Globalcode – Open4education
Cloud + Multi-tenancy
! Namespace API ! com.google.appengine.api.NamespaceManager
! Suporte aos seguintes serviços
! Google Datastore ! Memcached ! Task Queue ! Search
Globalcode – Open4education
Namespace API
// Filter to set the Google Apps // domain as the namespace. public class NamespaceFilter implements javax.servlet.Filter { @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { // Make sure set() is only called if the current namespace is not already set. if (NamespaceManager.get() == null) { NamespaceManager.set(NamespaceManager.getGoogleAppsNamespace()); } } }
// Assuming there is a logged in user. namespace = UserServiceFactory.getUserService() .getCurrentUser().getUserId(); NamespaceManager.set(namespace);
<filter> <filter-name>NamespaceFilter</filter-name> <filter-class>package.NamespaceFilter</filter-class> </filter> <filter-mapping> <filter-name>NamespaceFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Globalcode – Open4education
Namespace API
! Search // Set the current namespace to "aSpace" NamespaceManager.set("aSpace"); // Create a SearchService with the namespace "aSpace" SearchService searchService = SearchServiceFactory.getSearchService();
// Create a MemcacheService that uses the namespace "abc". MemcacheService explicit = MemcacheServiceFactory.getMemcacheService("abc"); explicit.put("key", value); // stores value in namespace "abc"
// Increment the count for the current namespace asynchronously. QueueFactory.getDefaultQueue().add( TaskOptions.Builder.url("/_ah/update_count") .param("countName", "SomeRequest"));
! Memcached
! Task Queue
Globalcode – Open4education
JVM + Multi-tenancy
! Multi-tenancy no nível da JVM ! IBM SDK JVM
! Static field isolation ! Controle by tenant
! CPU time ! Heap size ! Thread count ! File IO, Socket IO
! Limitações ! Java Native Interface (JNI) ! JVMT (Tool interface) ! GUI Libraries (GWT, Swing, etc)
! EXPERIMENTAL !!!
Globalcode – Open4education
Referências ! http://msdn.microsoft.com/en-us/library/aa479086.aspx ! https://developers.google.com/appengine/docs/java/multitenancy/ ! http://www.ibm.com/developerworks/java/library/j-multitenant-java/index.html ! http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/
a_multitenant.htm ! http://2012.con-fess.com/sessions/-/details/122/JSF-and-JavaEE-7-for-multi-
tenant-applications ! http://jdevelopment.nl/jsf-22/ ! http://picketlink.org ! https://developers.google.com/appengine/docs/java/multitenancy/ ! http://www.jboss.org/quickstarts/picketlink/picketlink-authentication-idm-multi-
tenancy/ ! http://wiki.eclipse.org/EclipseLink/Examples/MySports