You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by rm...@apache.org on 2016/12/04 11:01:44 UTC

svn commit: r1772522 [34/45] - in /tomee/site/trunk: content/ content/admin/ content/admin/cluster/ content/admin/configuration/ content/advanced/ content/advanced/applicationcomposer/ content/advanced/client/ content/advanced/setup/ content/advanced/s...

Added: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/deltaspike-i18n.adoc
URL: http://svn.apache.org/viewvc/tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/deltaspike-i18n.adoc?rev=1772522&view=auto
==============================================================================
--- tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/deltaspike-i18n.adoc (added)
+++ tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/deltaspike-i18n.adoc Sun Dec  4 11:01:40 2016
@@ -0,0 +1,9 @@
+= deltaspike-i18n
+:jbake-date: 2016-09-06
+:jbake-type: page
+:jbake-tomeepdf:
+:jbake-status: published
+
+Example deltaspike-i18n can be browsed at https://github.com/apache/tomee/tree/master/examples/deltaspike-i18n
+
+No README.md yet, be the first to contribute one!

Propchange: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/deltaspike-i18n.adoc
------------------------------------------------------------------------------
    svn:executable = *

Added: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-dao-implementation.adoc
URL: http://svn.apache.org/viewvc/tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-dao-implementation.adoc?rev=1772522&view=auto
==============================================================================
--- tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-dao-implementation.adoc (added)
+++ tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-dao-implementation.adoc Sun Dec  4 11:01:40 2016
@@ -0,0 +1,384 @@
+= Dynamic DAO Implementation
+:jbake-date: 2016-09-06
+:jbake-type: page
+:jbake-tomeepdf:
+:jbake-status: published
+
+Example dynamic-dao-implementation can be browsed at https://github.com/apache/tomee/tree/master/examples/dynamic-dao-implementation
+
+
+Many aspects of Data Access Objects (DAOs) are very repetitive and boiler plate.  As a fun and experimental feature, TomEE supports dynamically implementing an interface
+that is seen to have standard DAO-style methods.
+
+The interface has to be annotated with @PersistenceContext to define which EntityManager to use.
+
+Methods should respect these conventions:
+
+  * void save(Foo foo): persist foo
+  * Foo update(Foo foo): merge foo
+  * void delete(Foo foo): remove foo, if foo is detached it tries to attach it
+  * Collection<Foo>|Foo namedQuery(String name[, Map<String, ?> params, int first, int max]): run the named query called name, params contains bindings, first and max are used for magination. Last three parameters are optionnals
+  * Collection<Foo>|Foo nativeQuery(String name[, Map<String, ?> params, int first, int max]): run the native query called name, params contains bindings, first and max are used for magination. Last three parameters are optionnals
+  * Collection<Foo>|Foo query(String value [, Map<String, ?> params, int first, int max]): run the query put as first parameter, params contains bindings, first and max are used for magination. Last three parameters are optionnals
+  * Collection<Foo> findAll([int first, int max]): find all Foo, parameters are used for pagination
+  * Collection<Foo> findByBar1AndBar2AndBar3(<bar 1 type> bar1, <bar 2 type> bar2, <bar3 type> bar3 [, int first, int max]): find all Foo with specified field values for bar1, bar2, bar3.
+
+Dynamic finder can have as much as you want field constraints. For String like is used and for other type equals is used.
+
+=  Example
+
+==  User
+
+
+[source,java]
+----
+package org.superbiz.dynamic;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+
+@Entity
+@NamedQueries({
+        @NamedQuery(name = "dynamic-ejb-impl-test.query", query = "SELECT u FROM User AS u WHERE u.name LIKE :name"),
+        @NamedQuery(name = "dynamic-ejb-impl-test.all", query = "SELECT u FROM User AS u")
+})
+public class User {
+    @Id
+    @GeneratedValue
+    private long id;
+    private String name;
+    private int age;
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+}
+----
+
+
+==  UserDao
+
+
+[source,java]
+----
+package org.superbiz.dynamic;
+
+
+import javax.ejb.Stateless;
+import javax.persistence.PersistenceContext;
+import java.util.Collection;
+import java.util.Map;
+
+@Stateless
+@PersistenceContext(name = "dynamic")
+public interface UserDao {
+    User findById(long id);
+
+    Collection<User> findByName(String name);
+
+    Collection<User> findByNameAndAge(String name, int age);
+
+    Collection<User> findAll();
+
+    Collection<User> findAll(int first, int max);
+
+    Collection<User> namedQuery(String name, Map<String, ?> params, int first, int max);
+
+    Collection<User> namedQuery(String name, int first, int max, Map<String, ?> params);
+
+    Collection<User> namedQuery(String name, Map<String, ?> params);
+
+    Collection<User> namedQuery(String name);
+
+    Collection<User> query(String value, Map<String, ?> params);
+
+    void save(User u);
+
+    void delete(User u);
+
+    User update(User u);
+}
+----
+
+
+==  persistence.xml
+
+
+[source,xml]
+----
+<persistence version="2.0"
+             xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="
+      http://java.sun.com/xml/ns/persistence
+      http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
+  <persistence-unit name="dynamic" transaction-type="JTA">
+    <jta-data-source>jdbc/dynamicDB</jta-data-source>
+    <class>org.superbiz.dynamic.User</class>
+    <properties>
+      <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+    </properties>
+  </persistence-unit>
+</persistence>
+----
+
+    
+
+==  DynamicUserDaoTest
+
+
+[source,java]
+----
+package org.superbiz.dynamic;
+
+import junit.framework.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.ejb.EJBException;
+import javax.ejb.Stateless;
+import javax.ejb.embeddable.EJBContainer;
+import javax.naming.Context;
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceContext;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+public class DynamicUserDaoTest {
+    private static UserDao dao;
+    private static Util util;
+
+    @BeforeClass
+    public static void init() throws Exception {
+        final Properties p = new Properties();
+        p.put("jdbc/dynamicDB", "new://Resource?type=DataSource");
+        p.put("jdbc/dynamicDB.JdbcDriver", "org.hsqldb.jdbcDriver");
+        p.put("jdbc/dynamicDB.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+        p.put("jdbc/dynamicDB.UserName", "sa");
+        p.put("jdbc/dynamicDB.Password", "");
+
+        final Context context = EJBContainer.createEJBContainer(p).getContext();
+        dao = (UserDao) context.lookup("java:global/dynamic-dao-implementation/UserDao");
+        util = (Util) context.lookup("java:global/dynamic-dao-implementation/Util");
+
+        util.init(); // init database
+    }
+
+    @Test
+    public void simple() {
+        User user = dao.findById(1);
+        assertNotNull(user);
+        assertEquals(1, user.getId());
+    }
+
+    @Test
+    public void findAll() {
+        Collection<User> users = dao.findAll();
+        assertEquals(10, users.size());
+    }
+
+    @Test
+    public void pagination() {
+        Collection<User> users = dao.findAll(0, 5);
+        assertEquals(5, users.size());
+
+        users = dao.findAll(6, 1);
+        assertEquals(1, users.size());
+        assertEquals(7, users.iterator().next().getId());
+    }
+
+    @Test
+    public void persist() {
+        User u = new User();
+        dao.save(u);
+        assertNotNull(u.getId());
+        util.remove(u);
+    }
+
+    @Test
+    public void remove() {
+        User u = new User();
+        dao.save(u);
+        assertNotNull(u.getId());
+        dao.delete(u);
+        try {
+            dao.findById(u.getId());
+            Assert.fail();
+        } catch (EJBException ee) {
+            assertTrue(ee.getCause() instanceof NoResultException);
+        }
+    }
+
+    @Test
+    public void merge() {
+        User u = new User();
+        u.setAge(1);
+        dao.save(u);
+        assertEquals(1, u.getAge());
+        assertNotNull(u.getId());
+
+        u.setAge(2);
+        dao.update(u);
+        assertEquals(2, u.getAge());
+
+        dao.delete(u);
+    }
+
+    @Test
+    public void oneCriteria() {
+        Collection<User> users = dao.findByName("foo");
+        assertEquals(4, users.size());
+        for (User user : users) {
+            assertEquals("foo", user.getName());
+        }
+    }
+
+    @Test
+    public void twoCriteria() {
+        Collection<User> users = dao.findByNameAndAge("bar-1", 1);
+        assertEquals(1, users.size());
+
+        User user = users.iterator().next();
+        assertEquals("bar-1", user.getName());
+        assertEquals(1, user.getAge());
+    }
+
+    @Test
+    public void query() {
+        Map<String, Object> params = new HashMap<String, Object>();
+        params.put("name", "foo");
+
+        Collection<User> users = dao.namedQuery("dynamic-ejb-impl-test.query", params, 0, 100);
+        assertEquals(4, users.size());
+
+        users = dao.namedQuery("dynamic-ejb-impl-test.query", params);
+        assertEquals(4, users.size());
+
+        users = dao.namedQuery("dynamic-ejb-impl-test.query", params, 0, 2);
+        assertEquals(2, users.size());
+
+        users = dao.namedQuery("dynamic-ejb-impl-test.query", 0, 2, params);
+        assertEquals(2, users.size());
+
+        users = dao.namedQuery("dynamic-ejb-impl-test.all");
+        assertEquals(10, users.size());
+
+        params.remove("name");
+        params.put("age", 1);
+        users = dao.query("SELECT u FROM User AS u WHERE u.age = :age", params);
+        assertEquals(3, users.size());
+    }
+
+    @Stateless
+    public static class Util {
+        @PersistenceContext
+        private EntityManager em;
+
+        public void remove(User o) {
+            em.remove(em.find(User.class, o.getId()));
+        }
+
+        public void init() {
+            for (int i = 0; i < 10; i++) {
+                User u = new User();
+                u.setAge(i % 4);
+                if (i % 3 == 0) {
+                    u.setName("foo");
+                } else {
+                    u.setName("bar-" + i);
+                }
+                em.persist(u);
+            }
+        }
+    }
+}
+----
+
+
+=  Running
+
+    
+
+[source]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.dynamic.DynamicUserDaoTest
+Apache OpenEJB 4.0.0-beta-1    build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/dynamic-dao-implementation
+INFO - openejb.base = /Users/dblevins/examples/dynamic-dao-implementation
+INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=jdbc/dynamicDB, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/dynamic-dao-implementation/target/classes
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/dynamic-dao-implementation/target/test-classes
+INFO - Beginning load: /Users/dblevins/examples/dynamic-dao-implementation/target/classes
+INFO - Beginning load: /Users/dblevins/examples/dynamic-dao-implementation/target/test-classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/dynamic-dao-implementation
+INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container)
+INFO - Auto-creating a container for bean UserDao: Container(type=STATELESS, id=Default Stateless Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.dynamic.DynamicUserDaoTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=dynamic)
+INFO - Auto-creating a Resource with id 'jdbc/dynamicDBNonJta' of type 'DataSource for 'dynamic'.
+INFO - Configuring Service(id=jdbc/dynamicDBNonJta, type=Resource, provider-id=jdbc/dynamicDB)
+INFO - Adjusting PersistenceUnit dynamic <non-jta-data-source> to Resource ID 'jdbc/dynamicDBNonJta' from 'null'
+INFO - Enterprise application "/Users/dblevins/examples/dynamic-dao-implementation" loaded.
+INFO - Assembling app: /Users/dblevins/examples/dynamic-dao-implementation
+INFO - PersistenceUnit(name=dynamic, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 417ms
+INFO - Jndi(name="java:global/dynamic-dao-implementation/UserDao!org.superbiz.dynamic.UserDao")
+INFO - Jndi(name="java:global/dynamic-dao-implementation/UserDao")
+INFO - Jndi(name="java:global/dynamic-dao-implementation/Util!org.superbiz.dynamic.DynamicUserDaoTest$Util")
+INFO - Jndi(name="java:global/dynamic-dao-implementation/Util")
+INFO - Jndi(name="java:global/EjbModule346613126/org.superbiz.dynamic.DynamicUserDaoTest!org.superbiz.dynamic.DynamicUserDaoTest")
+INFO - Jndi(name="java:global/EjbModule346613126/org.superbiz.dynamic.DynamicUserDaoTest")
+INFO - Created Ejb(deployment-id=UserDao, ejb-name=UserDao, container=Default Stateless Container)
+INFO - Created Ejb(deployment-id=Util, ejb-name=Util, container=Default Stateless Container)
+INFO - Created Ejb(deployment-id=org.superbiz.dynamic.DynamicUserDaoTest, ejb-name=org.superbiz.dynamic.DynamicUserDaoTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=UserDao, ejb-name=UserDao, container=Default Stateless Container)
+INFO - Started Ejb(deployment-id=Util, ejb-name=Util, container=Default Stateless Container)
+INFO - Started Ejb(deployment-id=org.superbiz.dynamic.DynamicUserDaoTest, ejb-name=org.superbiz.dynamic.DynamicUserDaoTest, container=Default Managed Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/dynamic-dao-implementation)
+WARN - Meta class "org.superbiz.dynamic.User_" for entity class org.superbiz.dynamic.User can not be registered with following exception "java.security.PrivilegedActionException: java.lang.ClassNotFoundException: org.superbiz.dynamic.User_"
+WARN - Query "SELECT u FROM User AS u WHERE u.name LIKE :name" is removed from cache  excluded permanently. Query "SELECT u FROM User AS u WHERE u.name LIKE :name" is not cached because it uses pagination..
+Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.471 sec
+
+Results :
+
+Tests run: 9, Failures: 0, Errors: 0, Skipped: 0
+----
+
+    

Propchange: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-dao-implementation.adoc
------------------------------------------------------------------------------
    svn:executable = *

Added: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-datasource-routing.adoc
URL: http://svn.apache.org/viewvc/tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-datasource-routing.adoc?rev=1772522&view=auto
==============================================================================
--- tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-datasource-routing.adoc (added)
+++ tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-datasource-routing.adoc Sun Dec  4 11:01:40 2016
@@ -0,0 +1,473 @@
+= Dynamic Datasource Routing
+:jbake-date: 2016-09-06
+:jbake-type: page
+:jbake-tomeepdf:
+:jbake-status: published
+
+Example dynamic-datasource-routing can be browsed at https://github.com/apache/tomee/tree/master/examples/dynamic-datasource-routing
+
+
+The TomEE dynamic datasource api aims to allow to use multiple data sources as one from an application point of view.
+
+It can be useful for technical reasons (load balancing for example) or more generally
+functionnal reasons (filtering, aggregation, enriching...). However please note you can choose
+only one datasource by transaction. It means the goal of this feature is not to switch more than
+once of datasource in a transaction. The following code will not work:
+
+
+[source,java]
+----
+@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"); // same transaction -> this invocation doesn't work
+        em.persist(new MyEntity());
+    }
+}
+----
+
+
+In this example the implementation simply use a datasource from its name and needs to be set before using any JPA
+operation in the transaction (to keep the logic simple in the example).
+
+=  The implementation of the Router
+
+Our router has two configuration parameters:
+* a list of jndi names representing datasources to use
+* a default datasource to use
+
+==  Router implementation
+
+The interface Router (`org.apache.openejb.resource.jdbc.Router`) has only one method to implement, `public DataSource getDataSource()`
+
+Our `DeterminedRouter` implementation uses a ThreadLocal to manage the currently used datasource. Keep in mind JPA used more than once the getDatasource() method
+for one operation. To change the datasource in one transaction is dangerous and should be avoid.
+
+
+[source,java]
+----
+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 datasource resource name, separator is a space
+     */
+    public void setDataSourceNames(String datasourceList) {
+        dataSourceNames = datasourceList;
+    }
+
+    /**
+     * lookup datasource in openejb resources
+     */
+    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) {
+                // ignored
+            }
+        }
+    }
+
+    /**
+     * @return the user selected data source if it is set
+     *         or the default one
+     *  @throws IllegalArgumentException if the data source is not found
+     */
+    @Override
+    public DataSource getDataSource() {
+        // lazy init of routed datasources
+        if (dataSources == null) {
+            init();
+        }
+
+        // if no datasource is selected use the default one
+        if (currentDataSource.get() == null) {
+            if (dataSources.containsKey(defaultDataSourceName)) {
+                return dataSources.get(defaultDataSourceName);
+
+            } else {
+                throw new IllegalArgumentException("you have to specify at least one datasource");
+            }
+        }
+
+        // the developper set the datasource to use
+        return currentDataSource.get();
+    }
+
+    /**
+     *
+     * @param datasourceName data source name
+     */
+    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);
+    }
+
+    /**
+     * reset the data source
+     */
+    public void clear() {
+        currentDataSource.remove();
+    }
+
+    public void setDefaultDataSourceName(String name) {
+        this.defaultDataSourceName = name;
+    }
+}
+----
+
+
+==  Declaring the implementation
+
+To be able to use your router as a resource you need to provide a service configuration. It is done in a file
+you can find in META-INF/org.router/ and called service-jar.xml
+(for your implementation you can of course change the package name).
+
+It contains the following code:
+
+
+[source,xml]
+----
+<ServiceJar>
+  <ServiceProvider id="DeterminedRouter" <!-- the name you want to use -->
+      service="Resource"
+      type="org.apache.openejb.resource.jdbc.Router"
+      class-name="org.superbiz.dynamicdatasourcerouting.DeterminedRouter"> <!-- implementation class -->
+
+    # the parameters
+
+    DataSourceNames
+    DefaultDataSourceName
+  </ServiceProvider>
+</ServiceJar>
+----
+
+
+
+=  Using the Router
+
+Here we have a `RoutedPersister` stateless bean which uses our `DeterminedRouter`
+
+
+[source,java]
+----
+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));
+    }
+}
+----
+
+
+=  The test
+
+In test mode and using property style configuration the foolowing configuration is used:
+
+
+[source,java]
+----
+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());
+
+        // resources
+        // datasources
+        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++) {
+            // persisting a person on database db -> kind of manual round robin
+            String name = "record " + i;
+            String db = databases[i % 3];
+            ejb.persist(i, name, db);
+        }
+
+        // assert database records number using 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();
+    }
+}
+----
+
+
+=  Configuration via openejb.xml
+
+The testcase above uses properties for configuration.  The identical way to do it via the `conf/openejb.xml` is as follows:
+
+
+[source,xml]
+----
+<!-- Router and datasource -->
+<Resource id="My Router" type="org.apache.openejb.router.test.DynamicDataSourceTest$DeterminedRouter" provider="org.routertest:DeterminedRouter">
+    DatasourceNames = database1 database2 database3
+    DefaultDataSourceName = database1
+</Resource>
+----
+
+
+[source,xml]
+----
+<Resource id="Routed Datasource" type="org.apache.openejb.resource.jdbc.Router" provider="RoutedDataSource">
+    Router = My Router
+</Resource>
+----
+
+
+
+[source,xml]
+----
+<!-- real datasources -->
+<Resource id="database1" type="DataSource">
+    JdbcDriver = org.hsqldb.jdbcDriver
+    JdbcUrl = jdbc:hsqldb:mem:db1
+    UserName = sa
+    Password
+    JtaManaged = true
+</Resource>
+----
+
+
+[source,xml]
+----
+<Resource id="database2" type="DataSource">
+    JdbcDriver = org.hsqldb.jdbcDriver
+    JdbcUrl = jdbc:hsqldb:mem:db2
+    UserName = sa
+    Password
+    JtaManaged = true
+</Resource>
+----
+
+
+[source,xml]
+----
+<Resource id="database3" type="DataSource">
+    JdbcDriver = org.hsqldb.jdbcDriver
+    JdbcUrl = jdbc:hsqldb:mem:db3
+    UserName = sa
+    Password
+    JtaManaged = true
+</Resource>
+----
+
+
+
+
+
+==  Some hack for OpenJPA
+
+Using more than one datasource behind one EntityManager means the databases are already created. If it is not the case,
+the JPA provider has to create the datasource at boot time.
+
+Hibernate do it so if you declare your databases it will work. However with OpenJPA
+(the default JPA provider for OpenEJB), the creation is lazy and it happens only once so when you'll switch of database
+it will no more work.
+
+Of course OpenEJB provides @Singleton and @Startup features of Java EE 6 and we can do a bean just making a simple find,
+even on none existing entities, just to force the database creation:
+
+
+[source,java]
+----
+@Startup
+@Singleton
+public class BoostrapUtility {
+    // inject all real databases
+
+    @PersistenceContext(unitName = "db1")
+    private EntityManager em1;
+
+    @PersistenceContext(unitName = "db2")
+    private EntityManager em2;
+
+    @PersistenceContext(unitName = "db3")
+    private EntityManager em3;
+
+    // force database creation
+
+    @PostConstruct
+    @TransactionAttribute(TransactionAttributeType.SUPPORTS)
+    public void initDatabase() {
+        em1.find(Person.class, 0);
+        em2.find(Person.class, 0);
+        em3.find(Person.class, 0);
+    }
+}
+----
+
+
+==  Using the routed datasource
+
+Now you configured the way you want to route your JPA operation, you registered the resources and you initialized
+your databases you can use it and see how it is simple:
+
+
+[source,java]
+----
+@Stateless
+public class RoutedPersister {
+    // injection of the "proxied" datasource
+    @PersistenceContext(unitName = "router")
+    private EntityManager em;
+
+    // injection of the router you need it to configured the database
+    @Resource(name = "My Router", type = DeterminedRouter.class)
+    private DeterminedRouter router;
+
+    public void persist(int id, String name, String ds) {
+        router.setDataSource(ds); // configuring the database for the current transaction
+        em.persist(new Person(id, name)); // will use ds database automatically
+    }
+}
+----
+
+
+=  Running
+
+
+
+[source]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest
+Apache OpenEJB 4.0.0-beta-1    build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/dynamic-datasource-routing
+INFO - openejb.base = /Users/dblevins/examples/dynamic-datasource-routing
+INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=My Router, type=Resource, provider-id=DeterminedRouter)
+INFO - Configuring Service(id=database3, type=Resource, provider-id=Default JDBC Database)
+INFO - Configuring Service(id=database2, type=Resource, provider-id=Default JDBC Database)
+INFO - Configuring Service(id=Routed Datasource, type=Resource, provider-id=RoutedDataSource)
+INFO - Configuring Service(id=database1, type=Resource, provider-id=Default JDBC Database)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/dynamic-datasource-routing/target/classes
+INFO - Beginning load: /Users/dblevins/examples/dynamic-datasource-routing/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/dynamic-datasource-routing
+WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime.
+INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container)
+INFO - Auto-creating a container for bean BoostrapUtility: Container(type=SINGLETON, id=Default Singleton Container)
+INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container)
+INFO - Auto-creating a container for bean RoutedPersister: Container(type=STATELESS, id=Default Stateless Container)
+INFO - Auto-linking resource-ref 'java:comp/env/My Router' in bean RoutedPersister to Resource(id=My Router)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Configuring PersistenceUnit(name=router)
+INFO - Configuring PersistenceUnit(name=db1)
+INFO - Auto-creating a Resource with id 'database1NonJta' of type 'DataSource for 'db1'.
+INFO - Configuring Service(id=database1NonJta, type=Resource, provider-id=database1)
+INFO - Adjusting PersistenceUnit db1 <non-jta-data-source> to Resource ID 'database1NonJta' from 'null'
+INFO - Configuring PersistenceUnit(name=db2)
+INFO - Auto-creating a Resource with id 'database2NonJta' of type 'DataSource for 'db2'.
+INFO - Configuring Service(id=database2NonJta, type=Resource, provider-id=database2)
+INFO - Adjusting PersistenceUnit db2 <non-jta-data-source> to Resource ID 'database2NonJta' from 'null'
+INFO - Configuring PersistenceUnit(name=db3)
+INFO - Auto-creating a Resource with id 'database3NonJta' of type 'DataSource for 'db3'.
+INFO - Configuring Service(id=database3NonJta, type=Resource, provider-id=database3)
+INFO - Adjusting PersistenceUnit db3 <non-jta-data-source> to Resource ID 'database3NonJta' from 'null'
+INFO - Enterprise application "/Users/dblevins/examples/dynamic-datasource-routing" loaded.
+INFO - Assembling app: /Users/dblevins/examples/dynamic-datasource-routing
+INFO - PersistenceUnit(name=router, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 504ms
+INFO - PersistenceUnit(name=db1, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 11ms
+INFO - PersistenceUnit(name=db2, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 7ms
+INFO - PersistenceUnit(name=db3, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 6ms
+INFO - Jndi(name="java:global/dynamic-datasource-routing/BoostrapUtility!org.superbiz.dynamicdatasourcerouting.BoostrapUtility")
+INFO - Jndi(name="java:global/dynamic-datasource-routing/BoostrapUtility")
+INFO - Jndi(name="java:global/dynamic-datasource-routing/RoutedPersister!org.superbiz.dynamicdatasourcerouting.RoutedPersister")
+INFO - Jndi(name="java:global/dynamic-datasource-routing/RoutedPersister")
+INFO - Jndi(name="java:global/EjbModule1519652738/org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest!org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest")
+INFO - Jndi(name="java:global/EjbModule1519652738/org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest")
+INFO - Created Ejb(deployment-id=RoutedPersister, ejb-name=RoutedPersister, container=Default Stateless Container)
+INFO - Created Ejb(deployment-id=org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest, ejb-name=org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest, container=Default Managed Container)
+INFO - Created Ejb(deployment-id=BoostrapUtility, ejb-name=BoostrapUtility, container=Default Singleton Container)
+INFO - Started Ejb(deployment-id=RoutedPersister, ejb-name=RoutedPersister, container=Default Stateless Container)
+INFO - Started Ejb(deployment-id=org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest, ejb-name=org.superbiz.dynamicdatasourcerouting.DynamicDataSourceTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=BoostrapUtility, ejb-name=BoostrapUtility, container=Default Singleton Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/dynamic-datasource-routing)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.504 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+

Propchange: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-datasource-routing.adoc
------------------------------------------------------------------------------
    svn:executable = *

Added: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-implementation.adoc
URL: http://svn.apache.org/viewvc/tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-implementation.adoc?rev=1772522&view=auto
==============================================================================
--- tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-implementation.adoc (added)
+++ tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-implementation.adoc Sun Dec  4 11:01:40 2016
@@ -0,0 +1,155 @@
+= Dynamic Implementation
+:jbake-date: 2016-09-06
+:jbake-type: page
+:jbake-tomeepdf:
+:jbake-status: published
+
+Example dynamic-implementation can be browsed at https://github.com/apache/tomee/tree/master/examples/dynamic-implementation
+
+
+*Help us document this example! Click the blue pencil icon in the upper right to edit this page.*
+
+==  SocialBean
+
+
+[source,java]
+----
+package org.superbiz.dynamic;
+
+import org.apache.openejb.api.Proxy;
+
+import javax.ejb.Singleton;
+import javax.interceptor.Interceptors;
+
+@Singleton
+@Proxy(SocialHandler.class)
+@Interceptors(SocialInterceptor.class)
+public interface SocialBean {
+    public String facebookStatus();
+
+    public String twitterStatus();
+
+    public String status();
+}
+----
+
+
+==  SocialHandler
+
+
+[source,java]
+----
+package org.superbiz.dynamic;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class SocialHandler implements InvocationHandler {
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        String mtd = method.getName();
+        if (mtd.toLowerCase().contains("facebook")) {
+            return "You think you have a life!";
+        } else if (mtd.toLowerCase().contains("twitter")) {
+            return "Wow, you eat pop corn!";
+        }
+        return "Hey, you have no virtual friend!";
+    }
+}
+----
+
+
+==  SocialInterceptor
+
+
+[source,java]
+----
+packagenull
+}
+----
+
+
+==  SocialTest
+
+
+[source,java]
+----
+package org.superbiz.dynamic;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.ejb.embeddable.EJBContainer;
+
+import static junit.framework.Assert.assertTrue;
+
+public class SocialTest {
+    private static SocialBean social;
+    private static EJBContainer container;
+
+    @BeforeClass
+    public static void init() throws Exception {
+        container = EJBContainer.createEJBContainer();
+        social = (SocialBean) container.getContext().lookup("java:global/dynamic-implementation/SocialBean");
+    }
+
+    @AfterClass
+    public static void close() {
+        container.close();
+    }
+
+    @Test
+    public void simple() {
+        assertTrue(social.facebookStatus().contains("think"));
+        assertTrue(social.twitterStatus().contains("eat"));
+        assertTrue(social.status().contains("virtual"));
+    }
+}
+----
+
+
+=  Running
+
+    
+
+[source]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.dynamic.SocialTest
+Apache OpenEJB 4.0.0-beta-1    build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/dynamic-implementation
+INFO - openejb.base = /Users/dblevins/examples/dynamic-implementation
+INFO - Using 'javax.ejb.embeddable.EJBContainer=true'
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/dynamic-implementation/target/classes
+INFO - Beginning load: /Users/dblevins/examples/dynamic-implementation/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/dynamic-implementation
+INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container)
+INFO - Auto-creating a container for bean SocialBean: Container(type=SINGLETON, id=Default Singleton Container)
+INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container)
+INFO - Auto-creating a container for bean org.superbiz.dynamic.SocialTest: Container(type=MANAGED, id=Default Managed Container)
+INFO - Enterprise application "/Users/dblevins/examples/dynamic-implementation" loaded.
+INFO - Assembling app: /Users/dblevins/examples/dynamic-implementation
+INFO - Jndi(name="java:global/dynamic-implementation/SocialBean!org.superbiz.dynamic.SocialBean")
+INFO - Jndi(name="java:global/dynamic-implementation/SocialBean")
+INFO - Jndi(name="java:global/EjbModule236706648/org.superbiz.dynamic.SocialTest!org.superbiz.dynamic.SocialTest")
+INFO - Jndi(name="java:global/EjbModule236706648/org.superbiz.dynamic.SocialTest")
+INFO - Created Ejb(deployment-id=org.superbiz.dynamic.SocialTest, ejb-name=org.superbiz.dynamic.SocialTest, container=Default Managed Container)
+INFO - Created Ejb(deployment-id=SocialBean, ejb-name=SocialBean, container=Default Singleton Container)
+INFO - Started Ejb(deployment-id=org.superbiz.dynamic.SocialTest, ejb-name=org.superbiz.dynamic.SocialTest, container=Default Managed Container)
+INFO - Started Ejb(deployment-id=SocialBean, ejb-name=SocialBean, container=Default Singleton Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/dynamic-implementation)
+INFO - Undeploying app: /Users/dblevins/examples/dynamic-implementation
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.107 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+
+    

Propchange: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-implementation.adoc
------------------------------------------------------------------------------
    svn:executable = *

Added: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc
URL: http://svn.apache.org/viewvc/tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc?rev=1772522&view=auto
==============================================================================
--- tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc (added)
+++ tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc Sun Dec  4 11:01:40 2016
@@ -0,0 +1,460 @@
+= dynamic-proxy-to-access-mbean
+:jbake-date: 2016-09-06
+:jbake-type: page
+:jbake-tomeepdf:
+:jbake-status: published
+
+Example dynamic-proxy-to-access-mbean can be browsed at https://github.com/apache/tomee/tree/master/examples/dynamic-proxy-to-access-mbean
+
+
+*Help us document this example! Click the blue pencil icon in the upper right to edit this page.*
+
+==  Example
+
+Acessing MBean is something simple through the JMX API but it is often technical and not very interesting.
+
+This example simplify this work simply doing it generically in a proxy.
+
+So from an user side you simple declare an interface to access your MBeans.
+
+Note: the example implementation uses a local MBeanServer but enhancing the example API
+it is easy to imagine a remote connection with user/password if needed.
+
+==  ObjectName API (annotation)
+
+Simply an annotation to get the object
+
+
+[source,java]
+----
+package org.superbiz.dynamic.mbean;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Target({TYPE, METHOD})
+@Retention(RUNTIME)
+public @interface ObjectName {
+    String value();
+
+    // for remote usage only
+    String url() default "";
+    String user() default "";
+    String password() default "";
+}
+----
+
+
+==  DynamicMBeanHandler (thr proxy implementation)
+
+
+[source,java]
+----
+package org.superbiz.dynamic.mbean;
+
+import javax.annotation.PreDestroy;
+import javax.management.Attribute;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Need a @PreDestroy method to disconnect the remote host when used in remote mode.
+ */
+public class DynamicMBeanHandler implements InvocationHandler {
+    private final Map<Method, ConnectionInfo> infos = new ConcurrentHashMap<Method, ConnectionInfo>();
+
+    @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        final String methodName = method.getName();
+        if (method.getDeclaringClass().equals(Object.class) && "toString".equals(methodName)) {
+            return getClass().getSimpleName() + " Proxy";
+        }
+        if (method.getAnnotation(PreDestroy.class) != null) {
+            return destroy();
+        }
+
+        final ConnectionInfo info = getConnectionInfo(method);
+        final MBeanInfo infos = info.getMBeanInfo();
+        if (methodName.startsWith("set") && methodName.length() > 3 && args != null && args.length == 1
+            && (Void.TYPE.equals(method.getReturnType()) || Void.class.equals(method.getReturnType()))) {
+            final String attributeName = attributeName(infos, methodName, method.getParameterTypes()[0]);
+            info.setAttribute(new Attribute(attributeName, args[0]));
+            return null;
+        } else if (methodName.startsWith("get") && (args == null || args.length == 0) && methodName.length() > 3) {
+            final String attributeName = attributeName(infos, methodName, method.getReturnType());
+            return info.getAttribute(attributeName);
+        }
+        // operation
+        return info.invoke(methodName, args, getSignature(method));
+    }
+
+    public Object destroy() {
+        for (ConnectionInfo info : infos.values()) {
+            info.clean();
+        }
+        infos.clear();
+        return null;
+    }
+
+    private String[] getSignature(Method method) {
+        String[] args = new String[method.getParameterTypes().length];
+        for (int i = 0; i < method.getParameterTypes().length; i++) {
+            args[i] = method.getParameterTypes()[i].getName();
+        }
+        return args; // note: null should often work...
+    }
+
+    private String attributeName(MBeanInfo infos, String methodName, Class<?> type) {
+        String found = null;
+        String foundBackUp = null; // without checking the type
+        final String attributeName = methodName.substring(3, methodName.length());
+        final String lowerName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4, methodName.length());
+
+        for (MBeanAttributeInfo attribute : infos.getAttributes()) {
+            final String name = attribute.getName();
+            if (attributeName.equals(name)) {
+                foundBackUp = attributeName;
+                if (attribute.getType().equals(type.getName())) {
+                    found = name;
+                }
+            } else if (found == null && ((lowerName.equals(name) && !attributeName.equals(name))
+                || lowerName.equalsIgnoreCase(name))) {
+                foundBackUp = name;
+                if (attribute.getType().equals(type.getName())) {
+                    found = name;
+                }
+            }
+        }
+
+        if (found == null && foundBackUp == null) {
+            throw new UnsupportedOperationException("cannot find attribute " + attributeName);
+        }
+
+        if (found != null) {
+            return found;
+        }
+        return foundBackUp;
+    }
+
+    private synchronized ConnectionInfo getConnectionInfo(Method method) throws Exception {
+        if (!infos.containsKey(method)) {
+            synchronized (infos) {
+                if (!infos.containsKey(method)) { // double check for synchro
+                    org.superbiz.dynamic.mbean.ObjectName on = method.getAnnotation(org.superbiz.dynamic.mbean.ObjectName.class);
+                    if (on == null) {
+                        Class<?> current = method.getDeclaringClass();
+                        do {
+                            on = method.getDeclaringClass().getAnnotation(org.superbiz.dynamic.mbean.ObjectName.class);
+                            current = current.getSuperclass();
+                        } while (on == null && current != null);
+                        if (on == null) {
+                            throw new UnsupportedOperationException("class or method should define the objectName to use for invocation: " + method.toGenericString());
+                        }
+                    }
+                    final ConnectionInfo info;
+                    if (on.url().isEmpty()) {
+                        info = new LocalConnectionInfo();
+                        ((LocalConnectionInfo) info).server = ManagementFactory.getPlatformMBeanServer(); // could use an id...
+                    } else {
+                        info = new RemoteConnectionInfo();
+                        final Map<String, String[]> environment = new HashMap<String, String[]>();
+                        if (!on.user().isEmpty()) {
+                            environment.put(JMXConnector.CREDENTIALS, new String[]{ on.user(), on.password() });
+                        }
+                        // ((RemoteConnectionInfo) info).connector = JMXConnectorFactory.newJMXConnector(new JMXServiceURL(on.url()), environment);
+                        ((RemoteConnectionInfo) info).connector = JMXConnectorFactory.connect(new JMXServiceURL(on.url()), environment);
+
+                    }
+                    info.objectName = new ObjectName(on.value());
+
+                    infos.put(method, info);
+                }
+            }
+        }
+        return infos.get(method);
+    }
+
+    private abstract static class ConnectionInfo {
+        protected ObjectName objectName;
+
+        public abstract void setAttribute(Attribute attribute) throws Exception;
+        public abstract Object getAttribute(String attribute) throws Exception;
+        public abstract Object invoke(String operationName, Object params[], String signature[]) throws Exception;
+        public abstract MBeanInfo getMBeanInfo() throws Exception;
+        public abstract void clean();
+    }
+
+    private static class LocalConnectionInfo extends ConnectionInfo {
+        private MBeanServer server;
+
+        @Override public void setAttribute(Attribute attribute) throws Exception {
+            server.setAttribute(objectName, attribute);
+        }
+
+        @Override public Object getAttribute(String attribute) throws Exception {
+            return server.getAttribute(objectName, attribute);
+        }
+
+        @Override
+        public Object invoke(String operationName, Object[] params, String[] signature) throws Exception {
+            return server.invoke(objectName, operationName, params, signature);
+        }
+
+        @Override public MBeanInfo getMBeanInfo() throws Exception {
+            return server.getMBeanInfo(objectName);
+        }
+
+        @Override public void clean() {
+            // no-op
+        }
+    }
+
+    private static class RemoteConnectionInfo extends ConnectionInfo {
+        private JMXConnector connector;
+        private MBeanServerConnection connection;
+
+        private void before() throws IOException {
+            connection = connector.getMBeanServerConnection();
+        }
+
+        private void after() throws IOException {
+            // no-op
+        }
+
+        @Override public void setAttribute(Attribute attribute) throws Exception {
+            before();
+            connection.setAttribute(objectName, attribute);
+            after();
+        }
+
+        @Override public Object getAttribute(String attribute) throws Exception {
+            before();
+            try {
+                return connection.getAttribute(objectName, attribute);
+            } finally {
+                after();
+            }
+        }
+
+        @Override
+        public Object invoke(String operationName, Object[] params, String[] signature) throws Exception {
+            before();
+            try {
+                return connection.invoke(objectName, operationName, params, signature);
+            } finally {
+                after();
+            }
+        }
+
+        @Override public MBeanInfo getMBeanInfo() throws Exception {
+            before();
+            try {
+                return connection.getMBeanInfo(objectName);
+            } finally {
+                after();
+            }
+        }
+
+        @Override public void clean() {
+            try {
+                connector.close();
+            } catch (IOException e) {
+                // no-op
+            }
+        }
+    }
+}
+----
+
+
+==  Dynamic Proxies    
+
+===  DynamicMBeanClient (the dynamic JMX client)
+
+	package org.superbiz.dynamic.mbean;
+
+	import org.apache.openejb.api.Proxy;
+	import org.superbiz.dynamic.mbean.DynamicMBeanHandler;
+	import org.superbiz.dynamic.mbean.ObjectName;
+
+	import javax.ejb.Singleton;
+
+	/**
+	 * @author rmannibucau
+	 */
+	@Singleton
+	@Proxy(DynamicMBeanHandler.class)
+	@ObjectName(DynamicMBeanClient.OBJECT_NAME)
+	public interface DynamicMBeanClient {
+		static final String OBJECT_NAME = "test:group=DynamicMBeanClientTest";
+
+		int getCounter();
+		void setCounter(int i);
+		int length(String aString);
+	}
+
+===  DynamicMBeanClient (the dynamic JMX client)
+
+[source,java]
+----
+package org.superbiz.dynamic.mbean;
+
+import org.apache.openejb.api.Proxy;
+
+import javax.annotation.PreDestroy;
+import javax.ejb.Singleton;
+
+
+@Singleton
+@Proxy(DynamicMBeanHandler.class)
+@ObjectName(value = DynamicRemoteMBeanClient.OBJECT_NAME, url = "service:jmx:rmi:///jndi/rmi://localhost:8243/jmxrmi")
+public interface DynamicRemoteMBeanClient {
+    static final String OBJECT_NAME = "test:group=DynamicMBeanClientTest";
+
+    int getCounter();
+    void setCounter(int i);
+    int length(String aString);
+
+    @PreDestroy void clean();
+}
+----
+
+
+==  The MBean used for the test
+
+===  SimpleMBean
+
+	package org.superbiz.dynamic.mbean.simple;
+
+	public interface SimpleMBean {
+		int length(String s);
+
+		int getCounter();
+		void setCounter(int c);
+	}
+
+==  Simple
+
+	package org.superbiz.dynamic.mbean.simple;
+
+	public class Simple implements SimpleMBean {
+		private int counter = 0;
+
+		@Override public int length(String s) {
+		    if (s == null) {
+		        return 0;
+		    }
+		    return s.length();
+		}
+
+		@Override public int getCounter() {
+		    return counter;
+		}
+
+		@Override public void setCounter(int c) {
+		    counter = c;
+		}
+	}
+
+==  DynamicMBeanClientTest (The test)
+
+
+[source,java]
+----
+package org.superbiz.dynamic.mbean;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.superbiz.dynamic.mbean.simple.Simple;
+
+import javax.ejb.EJB;
+import javax.ejb.embeddable.EJBContainer;
+import javax.management.Attribute;
+import javax.management.ObjectName;
+import java.lang.management.ManagementFactory;
+
+import static junit.framework.Assert.assertEquals;
+
+public class DynamicMBeanClientTest {
+    private static ObjectName objectName;
+    private static EJBContainer container;
+
+    @EJB private DynamicMBeanClient localClient;
+    @EJB private DynamicRemoteMBeanClient remoteClient;
+
+    @BeforeClass public static void start() {
+        container = EJBContainer.createEJBContainer();
+    }
+
+    @Before public void injectAndRegisterMBean() throws Exception {
+        container.getContext().bind("inject", this);
+        objectName = new ObjectName(DynamicMBeanClient.OBJECT_NAME);
+        ManagementFactory.getPlatformMBeanServer().registerMBean(new Simple(), objectName);
+    }
+
+    @After public void unregisterMBean() throws Exception {
+        if (objectName != null) {
+            ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName);
+        }
+    }
+
+    @Test public void localGet() throws Exception {
+        assertEquals(0, localClient.getCounter());
+        ManagementFactory.getPlatformMBeanServer().setAttribute(objectName, new Attribute("Counter", 5));
+        assertEquals(5, localClient.getCounter());
+    }
+
+    @Test public void localSet() throws Exception {
+        assertEquals(0, ((Integer) ManagementFactory.getPlatformMBeanServer().getAttribute(objectName, "Counter")).intValue());
+        localClient.setCounter(8);
+        assertEquals(8, ((Integer) ManagementFactory.getPlatformMBeanServer().getAttribute(objectName, "Counter")).intValue());
+    }
+
+    @Test public void localOperation() {
+        assertEquals(7, localClient.length("openejb"));
+    }
+
+    @Test public void remoteGet() throws Exception {
+        assertEquals(0, remoteClient.getCounter());
+        ManagementFactory.getPlatformMBeanServer().setAttribute(objectName, new Attribute("Counter", 5));
+        assertEquals(5, remoteClient.getCounter());
+    }
+
+    @Test public void remoteSet() throws Exception {
+        assertEquals(0, ((Integer) ManagementFactory.getPlatformMBeanServer().getAttribute(objectName, "Counter")).intValue());
+        remoteClient.setCounter(8);
+        assertEquals(8, ((Integer) ManagementFactory.getPlatformMBeanServer().getAttribute(objectName, "Counter")).intValue());
+    }
+
+    @Test public void remoteOperation() {
+        assertEquals(7, remoteClient.length("openejb"));
+    }
+
+    @AfterClass public static void close() {
+        if (container != null) {
+            container.close();
+        }
+    }
+}
+----
+
+

Propchange: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc
------------------------------------------------------------------------------
    svn:executable = *

Added: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/ear-testing.adoc
URL: http://svn.apache.org/viewvc/tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/ear-testing.adoc?rev=1772522&view=auto
==============================================================================
--- tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/ear-testing.adoc (added)
+++ tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/ear-testing.adoc Sun Dec  4 11:01:40 2016
@@ -0,0 +1,244 @@
+= EAR Testing
+:jbake-date: 2016-09-06
+:jbake-type: page
+:jbake-tomeepdf:
+:jbake-status: published
+
+Example ear-testing can be browsed at https://github.com/apache/tomee/tree/master/examples/ear-testing
+
+
+The goal of this example is to demonstrate how maven projects might be organized in a more real world style and how testing with OpenEJB can fit into that structure.
+
+This example takes the basic moviefun code we us in many of examples and splits it into two modules:
+
+ - `business-logic`
+ - `business-model`
+
+As the names imply, we keep our `@Entity` beans in the `business-model` module and our session beans in the `business-logic` model.  The tests located and run from the business logic module.
+
+    ear-testing
+    ear-testing/business-logic
+    ear-testing/business-logic/pom.xml
+    ear-testing/business-logic/src/main/java/org/superbiz/logic/Movies.java
+    ear-testing/business-logic/src/main/java/org/superbiz/logic/MoviesImpl.java
+    ear-testing/business-logic/src/main/resources
+    ear-testing/business-logic/src/main/resources/META-INF
+    ear-testing/business-logic/src/main/resources/META-INF/ejb-jar.xml
+    ear-testing/business-logic/src/test/java/org/superbiz/logic/MoviesTest.java
+    ear-testing/business-model
+    ear-testing/business-model/pom.xml
+    ear-testing/business-model/src/main/java/org/superbiz/model/Movie.java
+    ear-testing/business-model/src/main/resources/META-INF/persistence.xml
+    ear-testing/pom.xml
+
+=  Project configuration
+
+The parent pom, trimmed to the minimum, looks like so:
+
+
+[source,xml]
+----
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.superbiz</groupId>
+  <artifactId>myear</artifactId>
+  <version>1.1.0-SNAPSHOT</version>
+
+  <packaging>pom</packaging>
+
+  <modules>
+    <module>business-model</module>
+    <module>business-logic</module>
+  </modules>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.openejb</groupId>
+        <artifactId>javaee-api</artifactId>
+        <version>6.0-2</version>
+      </dependency>
+      <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>4.8.1</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+</project>
+----
+
+
+The `business-model/pom.xml` as follows:
+
+
+[source,xml]
+----
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.superbiz</groupId>
+    <artifactId>myear</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>business-model</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.openejb</groupId>
+      <artifactId>javaee-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+</project>
+----
+
+
+And finally, the `business-logic/pom.xml` which is setup to support embedded testing with OpenEJB:
+
+
+[source,xml]
+----
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <groupId>org.superbiz</groupId>
+    <artifactId>myear</artifactId>
+    <version>1.1.0-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>business-logic</artifactId>
+  <packaging>jar</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.superbiz</groupId>
+      <artifactId>business-model</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openejb</groupId>
+      <artifactId>javaee-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <!--
+    The <scope>test</scope> guarantees that non of your runtime
+    code is dependent on any OpenEJB classes.
+    -->
+    <dependency>
+      <groupId>org.apache.openejb</groupId>
+      <artifactId>openejb-core</artifactId>
+      <version>7.0.0-SNAPSHOT</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
+----
+
+
+=  TestCode
+
+The test code is the same as always:
+
+
+[source,java]
+----
+public class MoviesTest extends TestCase {
+
+    public void test() throws Exception {
+        Properties p = new Properties();
+        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.core.LocalInitialContextFactory");
+
+        p.put("openejb.deployments.classpath.ear", "true");
+
+        p.put("movieDatabase", "new://Resource?type=DataSource");
+        p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
+        p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+
+        p.put("movieDatabaseUnmanaged", "new://Resource?type=DataSource");
+        p.put("movieDatabaseUnmanaged.JdbcDriver", "org.hsqldb.jdbcDriver");
+        p.put("movieDatabaseUnmanaged.JdbcUrl", "jdbc:hsqldb:mem:moviedb");
+        p.put("movieDatabaseUnmanaged.JtaManaged", "false");
+
+        Context context = new InitialContext(p);
+
+        Movies movies = (Movies) context.lookup("MoviesLocal");
+
+        movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
+        movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
+        movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));
+
+        List<Movie> list = movies.getMovies();
+        assertEquals("List.size()", 3, list.size());
+
+        for (Movie movie : list) {
+            movies.deleteMovie(movie);
+        }
+
+        assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
+    }
+}
+----
+
+
+
+=  Running
+
+
+
+[source]
+----
+-------------------------------------------------------
+ T E S T S
+-------------------------------------------------------
+Running org.superbiz.logic.MoviesTest
+Apache OpenEJB 7.0.0-SNAPSHOT    build: 20111002-04:06
+http://tomee.apache.org/
+INFO - openejb.home = /Users/dblevins/examples/ear-testing/business-logic
+INFO - openejb.base = /Users/dblevins/examples/ear-testing/business-logic
+INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
+INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
+INFO - Configuring Service(id=movieDatabaseUnmanaged, type=Resource, provider-id=Default JDBC Database)
+INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
+INFO - Found PersistenceModule in classpath: /Users/dblevins/examples/ear-testing/business-model/target/business-model-1.0.jar
+INFO - Found EjbModule in classpath: /Users/dblevins/examples/ear-testing/business-logic/target/classes
+INFO - Using 'openejb.deployments.classpath.ear=true'
+INFO - Beginning load: /Users/dblevins/examples/ear-testing/business-model/target/business-model-1.0.jar
+INFO - Beginning load: /Users/dblevins/examples/ear-testing/business-logic/target/classes
+INFO - Configuring enterprise application: /Users/dblevins/examples/ear-testing/business-logic/classpath.ear
+INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
+INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
+INFO - Configuring PersistenceUnit(name=movie-unit)
+INFO - Enterprise application "/Users/dblevins/examples/ear-testing/business-logic/classpath.ear" loaded.
+INFO - Assembling app: /Users/dblevins/examples/ear-testing/business-logic/classpath.ear
+INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 415ms
+INFO - Jndi(name=MoviesLocal) --> Ejb(deployment-id=Movies)
+INFO - Jndi(name=global/classpath.ear/business-logic/Movies!org.superbiz.logic.Movies) --> Ejb(deployment-id=Movies)
+INFO - Jndi(name=global/classpath.ear/business-logic/Movies) --> Ejb(deployment-id=Movies)
+INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
+INFO - Deployed Application(path=/Users/dblevins/examples/ear-testing/business-logic/classpath.ear)
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.393 sec
+
+Results :
+
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
+----
+

Propchange: tomee/site/trunk/generators/site-tomee-ng/src/main/jbake/content/examples/ear-testing.adoc
------------------------------------------------------------------------------
    svn:executable = *