http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/dynamic-datasource-routing.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/dynamic-datasource-routing.adoc b/src/main/jbake/content/examples/dynamic-datasource-routing.adoc new file mode 100755 index 0000000..8b7a76e --- /dev/null +++ b/src/main/jbake/content/examples/dynamic-datasource-routing.adoc @@ -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 +---- + +
http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/dynamic-implementation.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/dynamic-implementation.adoc b/src/main/jbake/content/examples/dynamic-implementation.adoc new file mode 100755 index 0000000..0ffff9c --- /dev/null +++ b/src/main/jbake/content/examples/dynamic-implementation.adoc @@ -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 +---- + + http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc b/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc new file mode 100755 index 0000000..ae03587 --- /dev/null +++ b/src/main/jbake/content/examples/dynamic-proxy-to-access-mbean.adoc @@ -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(); + } + } +} +---- + + http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/ear-testing.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/ear-testing.adoc b/src/main/jbake/content/examples/ear-testing.adoc new file mode 100755 index 0000000..eac0b6d --- /dev/null +++ b/src/main/jbake/content/examples/ear-testing.adoc @@ -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 +---- + http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/ejb-examples.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/ejb-examples.adoc b/src/main/jbake/content/examples/ejb-examples.adoc new file mode 100755 index 0000000..64262f1 --- /dev/null +++ b/src/main/jbake/content/examples/ejb-examples.adoc @@ -0,0 +1,1188 @@ += EJB Examples +:jbake-date: 2016-09-06 +:jbake-type: page +:jbake-tomeepdf: +:jbake-status: published + +Example ejb-examples can be browsed at https://github.com/apache/tomee/tree/master/examples/ejb-examples + + +*Help us document this example! Click the blue pencil icon in the upper right to edit this page.* + +== AnnotatedEJB + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.annotation.Resource; +import javax.ejb.LocalBean; +import javax.ejb.Stateless; +import javax.sql.DataSource; + +@Stateless +@LocalBean +public class AnnotatedEJB implements AnnotatedEJBLocal, AnnotatedEJBRemote { + @Resource + private DataSource ds; + + private String name = "foo"; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public DataSource getDs() { + return ds; + } + + public void setDs(DataSource ds) { + this.ds = ds; + } + + public String toString() { + return "AnnotatedEJB[name=" + name + "]"; + } +} +---- + + +== AnnotatedEJBLocal + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.ejb.Local; +import javax.sql.DataSource; + +@Local +public interface AnnotatedEJBLocal { + String getName(); + + void setName(String name); + + DataSource getDs(); + + void setDs(DataSource ds); +} +---- + + +== AnnotatedEJBRemote + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.ejb.Remote; + +@Remote +public interface AnnotatedEJBRemote { + String getName(); + + void setName(String name); +} +---- + + +== AnnotatedServlet + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.annotation.Resource; +import javax.ejb.EJB; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; +import java.io.IOException; + +public class AnnotatedServlet extends HttpServlet { + @EJB + private AnnotatedEJBLocal localEJB; + + @EJB + private AnnotatedEJBRemote remoteEJB; + + @EJB + private AnnotatedEJB localbeanEJB; + + @Resource + private DataSource ds; + + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + ServletOutputStream out = response.getOutputStream(); + + out.println("LocalBean EJB"); + out.println("@EJB=" + localbeanEJB); + if (localbeanEJB != null) { + out.println("@EJB.getName()=" + localbeanEJB.getName()); + out.println("@EJB.getDs()=" + localbeanEJB.getDs()); + } + out.println("JNDI=" + lookupField("localbeanEJB")); + out.println(); + + out.println("Local EJB"); + out.println("@EJB=" + localEJB); + if (localEJB != null) { + out.println("@EJB.getName()=" + localEJB.getName()); + out.println("@EJB.getDs()=" + localEJB.getDs()); + } + out.println("JNDI=" + lookupField("localEJB")); + out.println(); + + out.println("Remote EJB"); + out.println("@EJB=" + remoteEJB); + if (localEJB != null) { + out.println("@EJB.getName()=" + remoteEJB.getName()); + } + out.println("JNDI=" + lookupField("remoteEJB")); + out.println(); + + + out.println("DataSource"); + out.println("@Resource=" + ds); + out.println("JNDI=" + lookupField("ds")); + } + + private Object lookupField(String name) { + try { + return new InitialContext().lookup("java:comp/env/" + getClass().getName() + "/" + name); + } catch (NamingException e) { + return null; + } + } +} +---- + + +== ClientHandler + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.xml.ws.handler.Handler; +import javax.xml.ws.handler.MessageContext; + +public class ClientHandler implements Handler { + public boolean handleMessage(MessageContext messageContext) { + WebserviceServlet.write(" ClientHandler handleMessage"); + return true; + } + + public void close(MessageContext messageContext) { + WebserviceServlet.write(" ClientHandler close"); + } + + public boolean handleFault(MessageContext messageContext) { + WebserviceServlet.write(" ClientHandler handleFault"); + return true; + } +} +---- + + +== HelloEjb + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.jws.WebService; + +@WebService(targetNamespace = "http://examples.org/wsdl") +public interface HelloEjb { + String hello(String name); +} +---- + + +== HelloEjbService + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.ejb.Stateless; +import javax.jws.HandlerChain; +import javax.jws.WebService; + +@WebService( + portName = "HelloEjbPort", + serviceName = "HelloEjbService", + targetNamespace = "http://examples.org/wsdl", + endpointInterface = "org.superbiz.servlet.HelloEjb" +) +@HandlerChain(file = "server-handlers.xml") +@Stateless +public class HelloEjbService implements HelloEjb { + public String hello(String name) { + WebserviceServlet.write(" HelloEjbService hello(" + name + ")"); + if (name == null) name = "World"; + return "Hello " + name + " from EJB Webservice!"; + } +} +---- + + +== HelloPojo + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.jws.WebService; + +@WebService(targetNamespace = "http://examples.org/wsdl") +public interface HelloPojo { + String hello(String name); +} +---- + + +== HelloPojoService + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.jws.HandlerChain; +import javax.jws.WebService; + +@WebService( + portName = "HelloPojoPort", + serviceName = "HelloPojoService", + targetNamespace = "http://examples.org/wsdl", + endpointInterface = "org.superbiz.servlet.HelloPojo" +) +@HandlerChain(file = "server-handlers.xml") +public class HelloPojoService implements HelloPojo { + public String hello(String name) { + WebserviceServlet.write(" HelloPojoService hello(" + name + ")"); + if (name == null) name = "World"; + return "Hello " + name + " from Pojo Webservice!"; + } +} +---- + + +== JndiServlet + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NameClassPair; +import javax.naming.NamingException; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; + +public class JndiServlet extends HttpServlet { + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + ServletOutputStream out = response.getOutputStream(); + + Map<String, Object> bindings = new TreeMap<String, Object>(String.CASE_INSENSITIVE_ORDER); + try { + Context context = (Context) new InitialContext().lookup("java:comp/"); + addBindings("", bindings, context); + } catch (NamingException e) { + throw new ServletException(e); + } + + out.println("JNDI Context:"); + for (Map.Entry<String, Object> entry : bindings.entrySet()) { + if (entry.getValue() != null) { + out.println(" " + entry.getKey() + "=" + entry.getValue()); + } else { + out.println(" " + entry.getKey()); + } + } + } + + private void addBindings(String path, Map<String, Object> bindings, Context context) { + try { + for (NameClassPair pair : Collections.list(context.list(""))) { + String name = pair.getName(); + String className = pair.getClassName(); + if ("org.apache.naming.resources.FileDirContext$FileResource".equals(className)) { + bindings.put(path + name, "<file>"); + } else { + try { + Object value = context.lookup(name); + if (value instanceof Context) { + Context nextedContext = (Context) value; + bindings.put(path + name, ""); + addBindings(path + name + "/", bindings, nextedContext); + } else { + bindings.put(path + name, value); + } + } catch (NamingException e) { + // lookup failed + bindings.put(path + name, "ERROR: " + e.getMessage()); + } + } + } + } catch (NamingException e) { + bindings.put(path, "ERROR: list bindings threw an exception: " + e.getMessage()); + } + } +} +---- + + +== JpaBean + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class JpaBean { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id") + private int id; + + @Column(name = "name") + private String name; + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + + public String toString() { + return "[JpaBean id=" + id + ", name=" + name + "]"; + } +} +---- + + +== JpaServlet + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.EntityTransaction; +import javax.persistence.PersistenceUnit; +import javax.persistence.Query; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class JpaServlet extends HttpServlet { + @PersistenceUnit(name = "jpa-example") + private EntityManagerFactory emf; + + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + ServletOutputStream out = response.getOutputStream(); + + out.println("@PersistenceUnit=" + emf); + + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + JpaBean jpaBean = new JpaBean(); + jpaBean.setName("JpaBean"); + em.persist(jpaBean); + + transaction.commit(); + transaction.begin(); + + Query query = em.createQuery("SELECT j FROM JpaBean j WHERE j.name='JpaBean'"); + jpaBean = (JpaBean) query.getSingleResult(); + out.println("Loaded " + jpaBean); + + em.remove(jpaBean); + + transaction.commit(); + transaction.begin(); + + query = em.createQuery("SELECT count(j) FROM JpaBean j WHERE j.name='JpaBean'"); + int count = ((Number) query.getSingleResult()).intValue(); + if (count == 0) { + out.println("Removed " + jpaBean); + } else { + out.println("ERROR: unable to remove" + jpaBean); + } + + transaction.commit(); + } +} +---- + + +== ResourceBean + + +[source,java] +---- +package org.superbiz.servlet; + +public class ResourceBean { + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String toString() { + return "[ResourceBean " + value + "]"; + } +} +---- + + +== RunAsServlet + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.ejb.EJB; +import javax.ejb.EJBAccessException; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.security.Principal; + +public class RunAsServlet extends HttpServlet { + @EJB + private SecureEJBLocal secureEJBLocal; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + ServletOutputStream out = response.getOutputStream(); + + out.println("Servlet"); + Principal principal = request.getUserPrincipal(); + if (principal != null) { + out.println("Servlet.getUserPrincipal()=" + principal + " [" + principal.getName() + "]"); + } else { + out.println("Servlet.getUserPrincipal()=<null>"); + } + out.println("Servlet.isCallerInRole(\"user\")=" + request.isUserInRole("user")); + out.println("Servlet.isCallerInRole(\"manager\")=" + request.isUserInRole("manager")); + out.println("Servlet.isCallerInRole(\"fake\")=" + request.isUserInRole("fake")); + out.println(); + + out.println("@EJB=" + secureEJBLocal); + if (secureEJBLocal != null) { + principal = secureEJBLocal.getCallerPrincipal(); + if (principal != null) { + out.println("@EJB.getCallerPrincipal()=" + principal + " [" + principal.getName() + "]"); + } else { + out.println("@EJB.getCallerPrincipal()=<null>"); + } + out.println("@EJB.isCallerInRole(\"user\")=" + secureEJBLocal.isCallerInRole("user")); + out.println("@EJB.isCallerInRole(\"manager\")=" + secureEJBLocal.isCallerInRole("manager")); + out.println("@EJB.isCallerInRole(\"fake\")=" + secureEJBLocal.isCallerInRole("fake")); + + try { + secureEJBLocal.allowUserMethod(); + out.println("@EJB.allowUserMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.allowUserMethod() DENIED"); + } + + try { + secureEJBLocal.allowManagerMethod(); + out.println("@EJB.allowManagerMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.allowManagerMethod() DENIED"); + } + + try { + secureEJBLocal.allowFakeMethod(); + out.println("@EJB.allowFakeMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.allowFakeMethod() DENIED"); + } + + try { + secureEJBLocal.denyAllMethod(); + out.println("@EJB.denyAllMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.denyAllMethod() DENIED"); + } + } + out.println(); + } +} +---- + + +== SecureEJB + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.annotation.Resource; +import javax.annotation.security.DeclareRoles; +import javax.annotation.security.DenyAll; +import javax.annotation.security.RolesAllowed; +import javax.ejb.SessionContext; +import javax.ejb.Stateless; +import java.security.Principal; + +@Stateless +@DeclareRoles({"user", "manager", "fake"}) +public class SecureEJB implements SecureEJBLocal { + @Resource + private SessionContext context; + + public Principal getCallerPrincipal() { + return context.getCallerPrincipal(); + } + + public boolean isCallerInRole(String role) { + return context.isCallerInRole(role); + } + + @RolesAllowed("user") + public void allowUserMethod() { + } + + @RolesAllowed("manager") + public void allowManagerMethod() { + } + + @RolesAllowed("fake") + public void allowFakeMethod() { + } + + @DenyAll + public void denyAllMethod() { + } + + public String toString() { + return "SecureEJB[userName=" + getCallerPrincipal() + "]"; + } +} +---- + + +== SecureEJBLocal + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.ejb.Local; +import java.security.Principal; + +@Local +public interface SecureEJBLocal { + Principal getCallerPrincipal(); + + boolean isCallerInRole(String role); + + void allowUserMethod(); + + void allowManagerMethod(); + + void allowFakeMethod(); + + void denyAllMethod(); +} +---- + + +== SecureServlet + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.ejb.EJB; +import javax.ejb.EJBAccessException; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.security.Principal; + +public class SecureServlet extends HttpServlet { + @EJB + private SecureEJBLocal secureEJBLocal; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + ServletOutputStream out = response.getOutputStream(); + + out.println("Servlet"); + Principal principal = request.getUserPrincipal(); + if (principal != null) { + out.println("Servlet.getUserPrincipal()=" + principal + " [" + principal.getName() + "]"); + } else { + out.println("Servlet.getUserPrincipal()=<null>"); + } + out.println("Servlet.isCallerInRole(\"user\")=" + request.isUserInRole("user")); + out.println("Servlet.isCallerInRole(\"manager\")=" + request.isUserInRole("manager")); + out.println("Servlet.isCallerInRole(\"fake\")=" + request.isUserInRole("fake")); + out.println(); + + out.println("@EJB=" + secureEJBLocal); + if (secureEJBLocal != null) { + principal = secureEJBLocal.getCallerPrincipal(); + if (principal != null) { + out.println("@EJB.getCallerPrincipal()=" + principal + " [" + principal.getName() + "]"); + } else { + out.println("@EJB.getCallerPrincipal()=<null>"); + } + out.println("@EJB.isCallerInRole(\"user\")=" + secureEJBLocal.isCallerInRole("user")); + out.println("@EJB.isCallerInRole(\"manager\")=" + secureEJBLocal.isCallerInRole("manager")); + out.println("@EJB.isCallerInRole(\"fake\")=" + secureEJBLocal.isCallerInRole("fake")); + + try { + secureEJBLocal.allowUserMethod(); + out.println("@EJB.allowUserMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.allowUserMethod() DENIED"); + } + + try { + secureEJBLocal.allowManagerMethod(); + out.println("@EJB.allowManagerMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.allowManagerMethod() DENIED"); + } + + try { + secureEJBLocal.allowFakeMethod(); + out.println("@EJB.allowFakeMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.allowFakeMethod() DENIED"); + } + + try { + secureEJBLocal.denyAllMethod(); + out.println("@EJB.denyAllMethod() ALLOWED"); + } catch (EJBAccessException e) { + out.println("@EJB.denyAllMethod() DENIED"); + } + } + out.println(); + } +} +---- + + +== ServerHandler + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.xml.ws.handler.Handler; +import javax.xml.ws.handler.MessageContext; + +public class ServerHandler implements Handler { + public boolean handleMessage(MessageContext messageContext) { + WebserviceServlet.write(" ServerHandler handleMessage"); + return true; + } + + public void close(MessageContext messageContext) { + WebserviceServlet.write(" ServerHandler close"); + } + + public boolean handleFault(MessageContext messageContext) { + WebserviceServlet.write(" ServerHandler handleFault"); + return true; + } +} +---- + + +== WebserviceClient + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.xml.ws.Service; +import java.io.PrintStream; +import java.net.URL; + +public class WebserviceClient { + /** + * Unfortunately, to run this example with CXF you need to have a HUGE class path. This + * is just what is required to run CXF: + * <p/> + * jaxb-api-2.0.jar + * jaxb-impl-2.0.3.jar + * <p/> + * saaj-api-1.3.jar + * saaj-impl-1.3.jar + * <p/> + * <p/> + * cxf-api-2.0.2-incubator.jar + * cxf-common-utilities-2.0.2-incubator.jar + * cxf-rt-bindings-soap-2.0.2-incubator.jar + * cxf-rt-core-2.0.2-incubator.jar + * cxf-rt-databinding-jaxb-2.0.2-incubator.jar + * cxf-rt-frontend-jaxws-2.0.2-incubator.jar + * cxf-rt-frontend-simple-2.0.2-incubator.jar + * cxf-rt-transports-http-jetty-2.0.2-incubator.jar + * cxf-rt-transports-http-2.0.2-incubator.jar + * cxf-tools-common-2.0.2-incubator.jar + * <p/> + * geronimo-activation_1.1_spec-1.0.jar + * geronimo-annotation_1.0_spec-1.1.jar + * geronimo-ejb_3.0_spec-1.0.jar + * geronimo-jpa_3.0_spec-1.1.jar + * geronimo-servlet_2.5_spec-1.1.jar + * geronimo-stax-api_1.0_spec-1.0.jar + * jaxws-api-2.0.jar + * axis2-jws-api-1.3.jar + * <p/> + * wsdl4j-1.6.1.jar + * xml-resolver-1.2.jar + * XmlSchema-1.3.1.jar + */ + public static void main(String[] args) throws Exception { + PrintStream out = System.out; + + Service helloPojoService = Service.create(new URL("http://localhost:8080/ejb-examples/hello?wsdl"), null); + HelloPojo helloPojo = helloPojoService.getPort(HelloPojo.class); + out.println(); + out.println("Pojo Webservice"); + out.println(" helloPojo.hello(\"Bob\")=" + helloPojo.hello("Bob")); + out.println(" helloPojo.hello(null)=" + helloPojo.hello(null)); + out.println(); + + Service helloEjbService = Service.create(new URL("http://localhost:8080/HelloEjbService?wsdl"), null); + HelloEjb helloEjb = helloEjbService.getPort(HelloEjb.class); + out.println(); + out.println("EJB Webservice"); + out.println(" helloEjb.hello(\"Bob\")=" + helloEjb.hello("Bob")); + out.println(" helloEjb.hello(null)=" + helloEjb.hello(null)); + out.println(); + } +} +---- + + +== WebserviceServlet + + +[source,java] +---- +package org.superbiz.servlet; + +import javax.jws.HandlerChain; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.ws.WebServiceRef; +import java.io.IOException; + +public class WebserviceServlet extends HttpServlet { + + @WebServiceRef + @HandlerChain(file = "client-handlers.xml") + private HelloPojo helloPojo; + + @WebServiceRef + @HandlerChain(file = "client-handlers.xml") + private HelloEjb helloEjb; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("text/plain"); + ServletOutputStream out = response.getOutputStream(); + + OUT = out; + try { + out.println("Pojo Webservice"); + out.println(" helloPojo.hello(\"Bob\")=" + helloPojo.hello("Bob")); + out.println(); + out.println(" helloPojo.hello(null)=" + helloPojo.hello(null)); + out.println(); + out.println("EJB Webservice"); + out.println(" helloEjb.hello(\"Bob\")=" + helloEjb.hello("Bob")); + out.println(); + out.println(" helloEjb.hello(null)=" + helloEjb.hello(null)); + out.println(); + } finally { + OUT = out; + } + } + + private static ServletOutputStream OUT; + + public static void write(String message) { + try { + ServletOutputStream out = OUT; + out.println(message); + } catch (Exception e) { + e.printStackTrace(); + } + } +} +---- + + + +== persistence.xml + + +[source,xml] +---- +<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> + <persistence-unit transaction-type="RESOURCE_LOCAL" name="jpa-example"> + <jta-data-source>java:openejb/Connector/Default JDBC Database</jta-data-source> + <non-jta-data-source>java:openejb/Connector/Default Unmanaged JDBC Database</non-jta-data-source> + <class>org.superbiz.servlet.JpaBean</class> + + <properties> + <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/> + </properties> + </persistence-unit> +</persistence> +---- + + +== client-handlers.xml + + +[source,xml] +---- +<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee"> + <jws:handler-chain> + <jws:handler> + <jws:handler-name>ClientHandler</jws:handler-name> + <jws:handler-class>org.superbiz.servlet.ClientHandler</jws:handler-class> + </jws:handler> + </jws:handler-chain> +</jws:handler-chains> +---- + + + +== server-handlers.xml + + +[source,xml] +---- +<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee"> + <jws:handler-chain> + <jws:handler> + <jws:handler-name>ServerHandler</jws:handler-name> + <jws:handler-class>org.superbiz.servlet.ServerHandler</jws:handler-class> + </jws:handler> + </jws:handler-chain> +</jws:handler-chains> +---- + + + +== context.xml + + +[source,xml] +---- +<Context> + <!-- This only works if the context is installed under the correct name --> + <Realm className="org.apache.catalina.realm.MemoryRealm" + pathname="webapps/ejb-examples-1.0-SNAPSHOT/WEB-INF/tomcat-users.xml"/> + + <Environment + name="context.xml/environment" + value="ContextString" + type="java.lang.String"/> + <Resource + name="context.xml/resource" + auth="Container" + type="org.superbiz.servlet.ResourceBean" + factory="org.apache.naming.factory.BeanFactory" + value="ContextResource"/> + <ResourceLink + name="context.xml/resource-link" + global="server.xml/environment" + type="java.lang.String"/> + + <!-- web.xml resources --> + <Resource + name="web.xml/resource-env-ref" + auth="Container" + type="org.superbiz.servlet.ResourceBean" + factory="org.apache.naming.factory.BeanFactory" + value="ContextResourceEnvRef"/> + <Resource + name="web.xml/resource-ref" + auth="Container" + type="org.superbiz.servlet.ResourceBean" + factory="org.apache.naming.factory.BeanFactory" + value="ContextResourceRef"/> + <ResourceLink + name="web.xml/resource-link" + global="server.xml/environment" + type="java.lang.String"/> +</Context> +---- + + + +== jetty-web.xml + + +[source,xml] +---- +<Configure class="org.eclipse.jetty.webapp.WebAppContext"> + <Get name="securityHandler"> + <Set name="loginService"> + <New class="org.eclipse.jetty.security.HashLoginService"> + <Set name="name">Test Realm</Set> + <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties + </Set> + </New> + </Set> + </Get> +</Configure> +---- + + +== tomcat-users.xml + + +[source,xml] +---- +<tomcat-users> + <user name="manager" password="manager" roles="manager,user"/> + <user name="user" password="user" roles="user"/> +</tomcat-users> +---- + + + +== web.xml + + +[source,xml] +---- +<web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + metadata-complete="false" + version="2.5"> + + <display-name>OpenEJB Servlet Examples</display-name> + + <servlet> + <servlet-name>AnnotatedServlet</servlet-name> + <servlet-class>org.superbiz.servlet.AnnotatedServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>AnnotatedServlet</servlet-name> + <url-pattern>/annotated/*</url-pattern> + </servlet-mapping> + + <servlet> + <servlet-name>JpaServlet</servlet-name> + <servlet-class>org.superbiz.servlet.JpaServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>JpaServlet</servlet-name> + <url-pattern>/jpa/*</url-pattern> + </servlet-mapping> + + <servlet> + <servlet-name>JndiServlet</servlet-name> + <servlet-class>org.superbiz.servlet.JndiServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>JndiServlet</servlet-name> + <url-pattern>/jndi/*</url-pattern> + </servlet-mapping> + + <servlet> + <servlet-name>RunAsServlet</servlet-name> + <servlet-class>org.superbiz.servlet.RunAsServlet</servlet-class> + <run-as> + <role-name>fake</role-name> + </run-as> + </servlet> + + <servlet-mapping> + <servlet-name>RunAsServlet</servlet-name> + <url-pattern>/runas/*</url-pattern> + </servlet-mapping> + + <servlet> + <servlet-name>SecureServlet</servlet-name> + <servlet-class>org.superbiz.servlet.SecureServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>SecureServlet</servlet-name> + <url-pattern>/secure/*</url-pattern> + </servlet-mapping> + + <security-constraint> + <web-resource-collection> + <web-resource-name>Secure Area</web-resource-name> + <url-pattern>/secure/*</url-pattern> + <url-pattern>/runas/*</url-pattern> + </web-resource-collection> + <auth-constraint> + <role-name>user</role-name> + </auth-constraint> + </security-constraint> + + <servlet> + <servlet-name>WebserviceServlet</servlet-name> + <servlet-class>org.superbiz.servlet.WebserviceServlet</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>WebserviceServlet</servlet-name> + <url-pattern>/webservice/*</url-pattern> + </servlet-mapping> + + + <servlet> + <servlet-name>HelloPojoService</servlet-name> + <servlet-class>org.superbiz.servlet.HelloPojoService</servlet-class> + </servlet> + + <servlet-mapping> + <servlet-name>HelloPojoService</servlet-name> + <url-pattern>/hello</url-pattern> + </servlet-mapping> + + <login-config> + <auth-method>BASIC</auth-method> + </login-config> + + <security-role> + <role-name>manager</role-name> + </security-role> + + <security-role> + <role-name>user</role-name> + </security-role> + + <env-entry> + <env-entry-name>web.xml/env-entry</env-entry-name> + <env-entry-type>java.lang.String</env-entry-type> + <env-entry-value>WebValue</env-entry-value> + </env-entry> + + <resource-ref> + <res-ref-name>web.xml/Data Source</res-ref-name> + <res-type>javax.sql.DataSource</res-type> + <res-auth>Container</res-auth> + </resource-ref> + + <resource-env-ref> + <resource-env-ref-name>web.xml/Queue</resource-env-ref-name> + <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type> + </resource-env-ref> + + <ejb-ref> + <ejb-ref-name>web.xml/EjbRemote</ejb-ref-name> + <ejb-ref-type>Session</ejb-ref-type> + <remote>org.superbiz.servlet.AnnotatedEJBRemote</remote> + </ejb-ref> + + <ejb-local-ref> + <ejb-ref-name>web.xml/EjLocal</ejb-ref-name> + <ejb-ref-type>Session</ejb-ref-type> + <local>org.superbiz.servlet.AnnotatedEJBLocal</local> + </ejb-local-ref> + + <persistence-unit-ref> + <persistence-unit-ref-name>web.xml/PersistenceUnit</persistence-unit-ref-name> + <persistence-unit-name>jpa-example</persistence-unit-name> + </persistence-unit-ref> + + <persistence-context-ref> + <persistence-context-ref-name>web.xml/PersistenceContext</persistence-context-ref-name> + <persistence-unit-name>jpa-example</persistence-unit-name> + <persistence-context-type>Transactional</persistence-context-type> + </persistence-context-ref> +</web-app> +---- + + http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/ejb-webservice.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/ejb-webservice.adoc b/src/main/jbake/content/examples/ejb-webservice.adoc new file mode 100755 index 0000000..0d21d16 --- /dev/null +++ b/src/main/jbake/content/examples/ejb-webservice.adoc @@ -0,0 +1,52 @@ += EJB Webservice +:jbake-date: 2016-09-06 +:jbake-type: page +:jbake-tomeepdf: +:jbake-status: published + +Example ejb-webservice can be browsed at https://github.com/apache/tomee/tree/master/examples/ejb-webservice + + +*Help us document this example! Click the blue pencil icon in the upper right to edit this page.* + +== Calculator + + +[source,java] +---- +package org.superbiz.ws; + +import javax.ejb.Stateless; +import javax.jws.WebService; + +@Stateless +@WebService(portName = "CalculatorPort", + serviceName = "CalculatorWebService", + targetNamespace = "http://superbiz.org/wsdl") +public class Calculator { + public int sum(int add1, int add2) { + return add1 + add2; + } + + public int multiply(int mul1, int mul2) { + return mul1 * mul2; + } +} +---- + + +== web.xml + + +[source,xml] +---- +<web-app xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + metadata-complete="false" + version="2.5"> + +</web-app> +---- + + http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/groovy-cdi.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/groovy-cdi.adoc b/src/main/jbake/content/examples/groovy-cdi.adoc new file mode 100755 index 0000000..0e0a6a0 --- /dev/null +++ b/src/main/jbake/content/examples/groovy-cdi.adoc @@ -0,0 +1,9 @@ += groovy-cdi +:jbake-date: 2016-09-06 +:jbake-type: page +:jbake-tomeepdf: +:jbake-status: published + +Example groovy-cdi can be browsed at https://github.com/apache/tomee/tree/master/examples/groovy-cdi + +No README.md yet, be the first to contribute one! http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/groovy-jpa.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/groovy-jpa.adoc b/src/main/jbake/content/examples/groovy-jpa.adoc new file mode 100755 index 0000000..91f9218 --- /dev/null +++ b/src/main/jbake/content/examples/groovy-jpa.adoc @@ -0,0 +1,9 @@ += groovy-jpa +:jbake-date: 2016-09-06 +:jbake-type: page +:jbake-tomeepdf: +:jbake-status: published + +Example groovy-jpa can be browsed at https://github.com/apache/tomee/tree/master/examples/groovy-jpa + +No README.md yet, be the first to contribute one! http://git-wip-us.apache.org/repos/asf/tomee-site-generator/blob/972cc356/src/main/jbake/content/examples/groovy-spock.adoc ---------------------------------------------------------------------- diff --git a/src/main/jbake/content/examples/groovy-spock.adoc b/src/main/jbake/content/examples/groovy-spock.adoc new file mode 100755 index 0000000..203cddc --- /dev/null +++ b/src/main/jbake/content/examples/groovy-spock.adoc @@ -0,0 +1,9 @@ += groovy-spock +:jbake-date: 2016-09-06 +:jbake-type: page +:jbake-tomeepdf: +:jbake-status: published + +Example groovy-spock can be browsed at https://github.com/apache/tomee/tree/master/examples/groovy-spock + +No README.md yet, be the first to contribute one!