marcoantoniobferreira commented on a change in pull request #598: 
TOMEE-2720-Translate dynamic-datasource-routing
URL: https://github.com/apache/tomee/pull/598#discussion_r339409901
 
 

 ##########
 File path: examples/dynamic-datasource-routing/README_pt.adoc
 ##########
 @@ -0,0 +1,429 @@
+:index-group: DataSources
+:jbake-type: page
+:jbake-status: status=published
+= Roteamento dinâmico de fonte de dados
+
+A API de fonte de dados dinâmica do TomEE visa permitir o uso de vários dados
+fontes como uma do ponto de vista do aplicativo.
+
+Pode ser útil por razões técnicas (balanceamento de carga, por exemplo) ou
+razões geralmente mais funcionais (filtragem, agregação, enriquecimento ...).
+No entanto, observe que você pode escolher apenas uma fonte de dados por 
transação.
+Isso significa que o objetivo desse recurso não é alternar mais de uma vez
+fonte de dados em uma transação. O código a seguir não funcionará:
+
+....
+@Stateless
+public class MyEJB {
+    @Resource private MyRouter router;
+    @PersistenceContext private EntityManager em;
+
+    public void workWithDataSources() {
+        router.setDataSource("ds1");
+        em.persist(new MyEntity());
+
+        router.setDataSource("ds2"); // mesma transação -> esta invocação não 
funciona
+        em.persist(new MyEntity());
+    }
+}
+....
+
+Neste exemplo, a implementação simplesmente usa uma fonte de dados de seu nome
+e precisa ser definido antes de usar qualquer operação JPA na transação
+(para manter a lógica simples no exemplo).
+
+== A implementação do roteador
+
+Nosso roteador possui dois parâmetros de configuração: *uma lista de nomes jndi
+representando fontes de dados para usar* uma fonte de dados padrão para usar
+
+=== Implementação de roteador
+
+A interface Router (`org.apache.openejb.resource.jdbc.Router`) tem
+somente um método para implementar, `public DataSource getDataSource()`
+
+Nossa implementação `DeterminedRouter` usa um ThreadLocal para gerenciar o
+fonte de dados usada atualmente. Lembre-se de que a JPA usou mais de uma vez o
+Método getDatasource() para uma operação. Para alterar a fonte de dados em
+uma transação é perigosa e deve ser evitada.
+
+....
+package org.superbiz.dynamicdatasourcerouting;
+
+import org.apache.openejb.resource.jdbc.AbstractRouter;
+
+import javax.naming.NamingException;
+import javax.sql.DataSource;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DeterminedRouter extends AbstractRouter {
+    private String dataSourceNames;
+    private String defaultDataSourceName;
+    private Map<String, DataSource> dataSources = null;
+    private ThreadLocal<DataSource> currentDataSource = new 
ThreadLocal<DataSource>();
+
+    /**
+     * @param datasourceList nome do recurso de origem de dados, separador é 
um espaço
+     */
+    public void setDataSourceNames(String datasourceList) {
+        dataSourceNames = datasourceList;
+    }
+
+    /**
+     * fonte de dados de pesquisa em recursos openejb
+     */
+    private void init() {
+        dataSources = new ConcurrentHashMap<String, DataSource>();
+        for (String ds : dataSourceNames.split(" ")) {
+            try {
+                Object o = getOpenEJBResource(ds);
+                if (o instanceof DataSource) {
+                    dataSources.put(ds, DataSource.class.cast(o));
+                }
+            } catch (NamingException e) {
+                // ignorado
+            }
+        }
+    }
+
+    /**
+     * @return o usuário selecionou a fonte de dados, se estiver definida
+      * ou o padrão
+     *  @throws IllegalArgumentException se a fonte de dados não for encontrada
+     */
+    @Override
+    public DataSource getDataSource() {
+        // lazy init of routed datasources
+        if (dataSources == null) {
+            init();
+        }
+
+        // se nenhuma fonte de dados estiver selecionada, use a fonte padrão
+        if (currentDataSource.get() == null) {
+            if (dataSources.containsKey(defaultDataSourceName)) {
+                return dataSources.get(defaultDataSourceName);
+
+            } else {
+                throw new IllegalArgumentException("você precisa especificar 
pelo menos uma fonte de dados");
+            }
+        }
+
+        // o desenvolvedor configurou a fonte de dados para usar
+        return currentDataSource.get();
+    }
+
+    /**
+     *
+     * @param datasourceName nome da fonte de dados
+     */
+    public void setDataSource(String datasourceName) {
+        if (dataSources == null) {
+            init();
+        }
+        if (!dataSources.containsKey(datasourceName)) {
+            throw new IllegalArgumentException("data source called " + 
datasourceName + " can't be found.");
+        }
+        DataSource ds = dataSources.get(datasourceName);
+        currentDataSource.set(ds);
+    }
+
+    /**
+     * redefinir a fonte de dados
+     */
+    public void clear() {
+        currentDataSource.remove();
+    }
+
+    public void setDefaultDataSourceName(String name) {
+        this.defaultDataSourceName = name;
+    }
+}
+....
+
+=== Declarando a implementação
+
+Para poder usar seu roteador como um recurso, você precisa fornecer um
+configuração de serviço. Isso é feito em um arquivo que você pode encontrar em
+META-INF/org.router/ e chamado service-jar.xml (para sua implementação
+é claro que você pode alterar o nome do pacote).
+
+Ele contém o seguinte código:
+
+....
+<ServiceJar>
+  <ServiceProvider id="DeterminedRouter" <!-- o nome que você deseja usar -->
+      service="Resource"
+      type="org.apache.openejb.resource.jdbc.Router"
+      class-name="org.superbiz.dynamicdatasourcerouting.DeterminedRouter"> 
<!-- classe de implementação -->
+
+    # os parametros
+
+    DataSourceNames
+    DefaultDataSourceName
+  </ServiceProvider>
+</ServiceJar>
+....
+
+== Usando o roteador
+
+Aqui temos um bean sem estado `RoutedPersister` que usa nosso
+`DeterminedRouter`
+
+....
+package org.superbiz.dynamicdatasourcerouting;
+
+import javax.annotation.Resource;
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Stateless
+public class RoutedPersister {
+    @PersistenceContext(unitName = "router")
+    private EntityManager em;
+
+    @Resource(name = "My Router", type = DeterminedRouter.class)
+    private DeterminedRouter router;
+
+    public void persist(int id, String name, String ds) {
+        router.setDataSource(ds);
+        em.persist(new Person(id, name));
+    }
+}
+....
+
+== O teste
+
+No modo de teste e usando a configuração de estilo de propriedade, o seguinte
+configuração é usada:
+
+....
+public class DynamicDataSourceTest {
+    @Test
+    public void route() throws Exception {
+        String[] databases = new String[]{"database1", "database2", 
"database3"};
+
+        Properties properties = new Properties();
+        properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, 
LocalInitialContextFactory.class.getName());
+
+        // Recursos
+        // fontes de dados
+        for (int i = 1; i <= databases.length; i++) {
+            String dbName = databases[i - 1];
+            properties.setProperty(dbName, "new://Resource?type=DataSource");
+            dbName += ".";
+            properties.setProperty(dbName + "JdbcDriver", 
"org.hsqldb.jdbcDriver");
+            properties.setProperty(dbName + "JdbcUrl", "jdbc:hsqldb:mem:db" + 
i);
+            properties.setProperty(dbName + "UserName", "sa");
+            properties.setProperty(dbName + "Password", "");
+            properties.setProperty(dbName + "JtaManaged", "true");
+        }
+
+        // router
+        properties.setProperty("My Router", 
"new://Resource?provider=org.router:DeterminedRouter&type=" + 
DeterminedRouter.class.getName());
+        properties.setProperty("My Router.DatasourceNames", "database1 
database2 database3");
+        properties.setProperty("My Router.DefaultDataSourceName", "database1");
+
+        // routed datasource
+        properties.setProperty("Routed Datasource", 
"new://Resource?provider=RoutedDataSource&type=" + Router.class.getName());
+        properties.setProperty("Routed Datasource.Router", "My Router");
+
+        Context ctx = EJBContainer.createEJBContainer(properties).getContext();
+        RoutedPersister ejb = (RoutedPersister) 
ctx.lookup("java:global/dynamic-datasource-routing/RoutedPersister");
+        for (int i = 0; i < 18; i++) {
+            // persistir uma pessoa no banco de dados db -> tipo de round 
robin manual
+            String name = "record " + i;
+            String db = databases[i % 3];
+            ejb.persist(i, name, db);
+        }
+
+        // afirmar o número de registros do banco de dados usando jdbc
+        for (int i = 1; i <= databases.length; i++) {
+            Connection connection = 
DriverManager.getConnection("jdbc:hsqldb:mem:db" + i, "sa", "");
+            Statement st = connection.createStatement();
+            ResultSet rs = st.executeQuery("select count(*) from PERSON");
+            rs.next();
+            assertEquals(6, rs.getInt(1));
+            st.close();
+            connection.close();
+        }
+
+        ctx.close();
+    }
+}
+....
+
+== Configuração via openejb.xml
+
+O testcase acima usa propriedades para configuração. O caminho idêntico
+fazê-lo através do `conf/openejb.xml` é o seguinte:
 
 Review comment:
   "idêntico para fazê-lo" instead of "idêntico fazê-lo"

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to