TOMEE-2423 - migrating from markdown to adoc
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/180f5c5f Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/180f5c5f Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/180f5c5f Branch: refs/heads/master Commit: 180f5c5f57df593efc893281972ffb4d19802c37 Parents: 0866dbe Author: ivanjunckes <[email protected]> Authored: Thu Dec 27 16:36:21 2018 -0200 Committer: ivanjunckes <[email protected]> Committed: Thu Dec 27 16:36:21 2018 -0200 ---------------------------------------------------------------------- .../cdi-alternative-and-stereotypes/README.adoc | 132 ++++++++ .../cdi-alternative-and-stereotypes/README.md | 131 -------- examples/cdi-application-scope/README.adoc | 143 +++++++++ examples/cdi-application-scope/README.md | 137 --------- examples/cdi-basic/README.adoc | 174 +++++++++++ examples/cdi-basic/README.md | 169 ----------- examples/cdi-events/README.adoc | 35 +++ examples/cdi-events/README.md | 37 --- examples/cdi-interceptors/README.adoc | 220 ++++++++++++++ examples/cdi-interceptors/README.md | 216 ------------- examples/cdi-produces-disposes/README.adoc | 292 ++++++++++++++++++ examples/cdi-produces-disposes/README.md | 276 ----------------- examples/cdi-produces-field/README.adoc | 302 +++++++++++++++++++ examples/cdi-produces-field/README.md | 285 ----------------- examples/cdi-request-scope/README.adoc | 162 ++++++++++ examples/cdi-request-scope/README.md | 153 ---------- examples/cdi-session-scope/README.adoc | 124 ++++++++ examples/cdi-session-scope/README.md | 122 -------- 18 files changed, 1584 insertions(+), 1526 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-alternative-and-stereotypes/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cdi-alternative-and-stereotypes/README.adoc b/examples/cdi-alternative-and-stereotypes/README.adoc new file mode 100644 index 0000000..456ff4a --- /dev/null +++ b/examples/cdi-alternative-and-stereotypes/README.adoc @@ -0,0 +1,132 @@ += CDI Alternative and Stereotypes + +:index-group: CDI +:jbake-type: page +:jbake-status: published + +== Introduction +CDI is a revolution for the Java EE world. This specification is the best one to avoid coupling between classes. + +This example simply aims to override bindings at runtime to simplify mocking work. + +It uses two kind of mocks: +1) a mock with no implementation in the classloader +2) a mock with an implementation in the classloader + +The mock answer from CDI is called _alternative_. + +Annotating `@Alternative` a class will mean it will used as the implementation if there is no other implementation +or if it is forced (through `META-INF/beans.xml`). + +== Code explanation + +=== Main Code + +We use an EJB `Jouney` to modelize a journey where the vehicle and the society can change. Here an EJB is used +because it simplifies the test. A jouney wraps the vehicle and society information. + +We define two interfaces to inject into the `Journey` EJB: `Vehicle` and `Society`. + +Finally we add an implementation for `Scociety` interface: `LowCostCompanie`. + +If we stop here, the `Journey` object will not be able to be created because there is no `Vehicle` implementation is available. + +NOTE: if we do have a `Vehicle` implementation, the injected Society should be `LowCostCompanie`. + +=== test code + +The goal here is to test our `Journey` EJB. So we have to provide a `Vehicle` implementation: `SuperCar`. + +We want to force the `Society` interface to be the `AirOpenEJB` implementation for our test. + +One solution could simply be to add `@Alternative` annotation on `AirOpenEJB` and activate it through +the `META-INF/beans.xml` file. + +Here we want to write more explicit code. So we want to replace the `@Alternative` annotation by `@Mock` one. + +So we define an `@Mock` annotation for classes, resolvable at runtime as a stereotype (`@Stereotype`) +that replaces `@Alternative`. + +Here is the annotation: + + @Stereotype // we define a stereotype + @Retention(RUNTIME) // resolvable at runtime + @Target(TYPE) // this annotation is a class level one + @Alternative // it replace @Alternative + public @interface Mock {} + +NOTE: you can add more CDI annotations after `@Alternative` and it will get the behavior expected (the scope for instance). + +So now we have our `@Mock` annotation which is a stereotype able to replace the `@Alternative` annotation when it +added to our mocks. + +If you run it now you'll have this exception: + + javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.superbiz.cdi.stereotype.Vehicle] is not found with the qualifiers + Qualifiers: [@javax.enterprise.inject.Default()] + for injection into Field Injection Point, field name : vehicle, Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, API Types:[java.lang.Object,org.superbiz.cdi.stereotype.Journey], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]] + +It means the stereotype is not activated. To do it simply add it to your `META-INF/beans.xml`: + + <alternatives> + <stereotype>org.superbiz.cdi.stereotype.Mock</stereotype> + </alternatives> + +NOTE: if you don't specify `AirOpenEJB` as `@Alternative` (done through our mock annotation) you'll get this exception: + + Caused by: javax.enterprise.inject.AmbiguousResolutionException: There is more than one api type with : org.superbiz.cdi.stereotype.Society with qualifiers : Qualifiers: [@javax.enterprise.inject.Default()] + for injection into Field Injection Point, field name : society, Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, API Types:[org.superbiz.cdi.stereotype.Journey,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]] + found beans: + AirOpenEJB, Name:null, WebBeans Type:MANAGED, API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.AirOpenEJB,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default] + LowCostCompanie, Name:null, WebBeans Type:MANAGED, API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.LowCostCompanie,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default] + +which simply means two implementations are available for the same injection point (`Journey.society`). + +== Conclusion + +With CDI it is really easy to define annotations with a strong meaning. You can define business annotations +or simply technical annotations to simplify your code (as we did with the mock annotation). + +NOTE: if you used qualifiers to inject `Scociety` objects you could have put all these qualifiers on +the mock class or defined a `@SocietyMock` annotation to be able to inject the same implementation for +all qualifiers in your tests. + +== Output + + Running org.superbiz.cdi.stereotype.StereotypeTest + Apache OpenEJB 7.0.0-SNAPSHOT build: 20111030-07:54 + http://tomee.apache.org/ + INFO - openejb.home = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes + INFO - openejb.base = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes + 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: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes + INFO - Found EjbModule in classpath: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes + INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes + INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes + INFO - Configuring enterprise application: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes + INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) + INFO - Auto-creating a container for bean cdi-alternative-and-stereotypes_test.Comp: Container(type=MANAGED, id=Default Managed Container) + INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container) + INFO - Auto-creating a container for bean Journey: Container(type=SINGLETON, id=Default Singleton Container) + INFO - Enterprise application "/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes" loaded. + INFO - Assembling app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes + INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp!org.apache.openejb.BeanContext$Comp") + INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp") + INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp!org.apache.openejb.BeanContext$Comp") + INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp") + INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey!org.superbiz.cdi.stereotype.Journey") + INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey") + INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest!org.superbiz.cdi.stereotype.StereotypeTest") + INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest") + INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container) + INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container) + INFO - Created Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container) + INFO - Created Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container) + INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container) + INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container) + INFO - Started Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container) + INFO - Started Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container) + INFO - Deployed Application(path=/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes) + INFO - Undeploying app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-alternative-and-stereotypes/README.md ---------------------------------------------------------------------- diff --git a/examples/cdi-alternative-and-stereotypes/README.md b/examples/cdi-alternative-and-stereotypes/README.md deleted file mode 100644 index b527711..0000000 --- a/examples/cdi-alternative-and-stereotypes/README.md +++ /dev/null @@ -1,131 +0,0 @@ -index-group=CDI -type=page -status=published -title=CDI Alternative and Stereotypes -~~~~~~ -# Introduction - -CDI is a revolution for the Java EE world. This specification is the best one to avoid coupling between classes. - -This example simply aims to override bindings at runtime to simplify mocking work. - -It uses two kind of mocks: -1) a mock with no implementation in the classloader -2) a mock with an implementation in the classloader - -The mock answer from CDI is called *alternative*. - -Annotating `@Alternative` a class will mean it will used as the implementation if there is no other implementation -or if it is forced (through `META-INF/beans.xml`). - -# Code explanation -## main code - -We use an EJB `Jouney` to modelize a journey where the vehicle and the society can change. Here an EJB is used -because it simplifies the test. A jouney wraps the vehicle and society information. - -We define two interfaces to inject into the `Journey` EJB: `Vehicle` and `Society`. - -Finally we add an implementation for `Scociety` interface: `LowCostCompanie`. - -If we stop here, the `Journey` object will not be able to be created because there is no `Vehicle` implementation is available. - -Note: if we do have a `Vehicle` implementation, the injected Society should be `LowCostCompanie`. - -## test code - -The goal here is to test our `Journey` EJB. So we have to provide a `Vehicle` implementation: `SuperCar`. - -We want to force the `Society` interface to be the `AirOpenEJB` implementation for our test. - -One solution could simply be to add `@Alternative` annotation on `AirOpenEJB` and activate it through -the `META-INF/beans.xml` file. - -Here we want to write more explicit code. So we want to replace the `@Alternative` annotation by `@Mock` one. - -So we define an `@Mock` annotation for classes, resolvable at runtime as a stereotype (`@Stereotype`) -that replaces `@Alternative`. - -Here is the annotation: - - @Stereotype // we define a stereotype - @Retention(RUNTIME) // resolvable at runtime - @Target(TYPE) // this annotation is a class level one - @Alternative // it replace @Alternative - public @interface Mock {} - -Note: you can add more CDI annotations after `@Alternative` and it will get the behavior expected (the scope for instance). - -So now we have our `@Mock` annotation which is a stereotype able to replace the `@Alternative` annotation when it -added to our mocks. - -If you run it now you'll have this exception: - - javax.enterprise.inject.UnsatisfiedResolutionException: Api type [org.superbiz.cdi.stereotype.Vehicle] is not found with the qualifiers - Qualifiers: [@javax.enterprise.inject.Default()] - for injection into Field Injection Point, field name : vehicle, Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, API Types:[java.lang.Object,org.superbiz.cdi.stereotype.Journey], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]] - -It means the stereotype is not activated. To do it simply add it to your `META-INF/beans.xml`: - - <alternatives> - <stereotype>org.superbiz.cdi.stereotype.Mock</stereotype> - </alternatives> - -Note: if you don't specify `AirOpenEJB` as `@Alternative` (done through our mock annotation) you'll get this exception: - - Caused by: javax.enterprise.inject.AmbiguousResolutionException: There is more than one api type with : org.superbiz.cdi.stereotype.Society with qualifiers : Qualifiers: [@javax.enterprise.inject.Default()] - for injection into Field Injection Point, field name : society, Bean Owner : [Journey, Name:null, WebBeans Type:ENTERPRISE, API Types:[org.superbiz.cdi.stereotype.Journey,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]] - found beans: - AirOpenEJB, Name:null, WebBeans Type:MANAGED, API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.AirOpenEJB,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default] - LowCostCompanie, Name:null, WebBeans Type:MANAGED, API Types:[org.superbiz.cdi.stereotype.Society,org.superbiz.cdi.stereotype.LowCostCompanie,java.lang.Object], Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default] - -which simply means two implementations are available for the same injection point (`Journey.society`). - -# Conclusion - -With CDI it is really easy to define annotations with a strong meaning. You can define business annotations -or simply technical annotations to simplify your code (as we did with the mock annotation). - -Note: if you used qualifiers to inject `Scociety` objects you could have put all these qualifiers on -the mock class or defined a `@SocietyMock` annotation to be able to inject the same implementation for -all qualifiers in your tests. - -# Output - - Running org.superbiz.cdi.stereotype.StereotypeTest - Apache OpenEJB 7.0.0-SNAPSHOT build: 20111030-07:54 - http://tomee.apache.org/ - INFO - openejb.home = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes - INFO - openejb.base = /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes - 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: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes - INFO - Found EjbModule in classpath: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes - INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/test-classes - INFO - Beginning load: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes/target/classes - INFO - Configuring enterprise application: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean cdi-alternative-and-stereotypes_test.Comp: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring Service(id=Default Singleton Container, type=Container, provider-id=Default Singleton Container) - INFO - Auto-creating a container for bean Journey: Container(type=SINGLETON, id=Default Singleton Container) - INFO - Enterprise application "/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes" loaded. - INFO - Assembling app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes - INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp!org.apache.openejb.BeanContext$Comp") - INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes_test.Comp") - INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp!org.apache.openejb.BeanContext$Comp") - INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/cdi-alternative-and-stereotypes.Comp") - INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey!org.superbiz.cdi.stereotype.Journey") - INFO - Jndi(name="java:global/cdi-alternative-and-stereotypes/Journey") - INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest!org.superbiz.cdi.stereotype.StereotypeTest") - INFO - Jndi(name="java:global/EjbModule162291475/org.superbiz.cdi.stereotype.StereotypeTest") - INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container) - INFO - Created Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container) - INFO - Created Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container) - INFO - Created Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container) - INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes_test.Comp, ejb-name=cdi-alternative-and-stereotypes_test.Comp, container=Default Managed Container) - INFO - Started Ejb(deployment-id=cdi-alternative-and-stereotypes.Comp, ejb-name=cdi-alternative-and-stereotypes.Comp, container=Default Managed Container) - INFO - Started Ejb(deployment-id=org.superbiz.cdi.stereotype.StereotypeTest, ejb-name=org.superbiz.cdi.stereotype.StereotypeTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=Journey, ejb-name=Journey, container=Default Singleton Container) - INFO - Deployed Application(path=/opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes) - INFO - Undeploying app: /opt/dev/openejb/openejb-trunk/examples/cdi-alternative-and-stereotypes http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-application-scope/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cdi-application-scope/README.adoc b/examples/cdi-application-scope/README.adoc new file mode 100644 index 0000000..2c60e77 --- /dev/null +++ b/examples/cdi-application-scope/README.adoc @@ -0,0 +1,143 @@ += CDI @ApplicationScoped +:index-group: CDI +:jbake-type: page +:jbake-status: published + +This example show the use of `@ApplicationScoped` annotation for injected objects. An object +which is defined as `@ApplicationScoped` is created once for the duration of the application. + +== Example + +This example depicts a similar scenario to cdi-request-scope. A restaurant guest orders +a soup from the waiter. The waiter then delivers the soup back to the guest. Another +guest can order the same soup that was ordered by the previous client - this is where +the application scope is used. + +=== Waiter + +The `Waiter` session bean receives a request from the test class via the `orderSoup()` method +and sets the name for the `soup` field. The `orderWhatTheOtherGuyHad()` method returns +the name of the `soup` field. + +.... +@Stateless +public class Waiter { + + @Inject + public Soup soup; + + public String orderSoup(String name){ + soup.setName(name); + return soup.getName(); + } + + public String orderWhatTheOtherGuyHad() { + String name = soup.getName(); + return name; + } +} +.... + +=== Soup + +The `Soup` class is an injectable POJO, defined as `@ApplicationScoped`. This means that an instance +will be created only once for the duration of the whole application. Try changing the `@ApplicationScoped` +annotation to `@RequestScoped` and see what happens. + +.... +@ApplicationScoped +public class Soup { + + private String name = "Soup of the day"; + + @PostConstruct + public void afterCreate() { + System.out.println("Soup created"); + } + + public String getName() { + return name; + } + + public void setName(String name){ + this.name = name; + } +} +.... + +== Test Case + +This is the entry class for this example. First a soup is ordered via `orderSoup()` method. +This initiates the `soup` field. Next, `orderWhatTheOtherGuyHad()` method returns the soup +from the application context. + +.... +public class RestaurantTest { + + private static String TOMATO_SOUP = "Tomato Soup"; + private EJBContainer container; + + @EJB + private Waiter joe; + + @Before + public void startContainer() throws Exception { + container = EJBContainer.createEJBContainer(); + container.getContext().bind("inject", this); + } + + @Test + public void orderSoup(){ + String someSoup = joe.orderSoup(TOMATO_SOUP); + assertEquals(TOMATO_SOUP, someSoup); + + String sameSoup = joe.orderWhatTheOtherGuyHad(); + assertEquals(TOMATO_SOUP, sameSoup); + } + + @After + public void closeContainer() throws Exception { + container.close(); + } +} +.... + +== Running + +In the output you can see that there is just one `Soup` instance created - one for +the whole application. + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.cdi.applicationscope.RestaurantTest +Apache OpenEJB 7.0.0-SNAPSHOT build: 20111224-11:09 +http://tomee.apache.org/ +INFO - openejb.home = C:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope +INFO - openejb.base = C:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope +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: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope\target\classes +INFO - Beginning load: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope\target\classes +INFO - Configuring enterprise application: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean cdi-application-scope.Comp: Container(type=MANAGED, id=Default Managed Container) +INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container) +INFO - Auto-creating a container for bean Waiter: Container(type=STATELESS, id=Default Stateless Container) +INFO - Enterprise application "c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope" loaded. +INFO - Assembling app: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope +INFO - Jndi(name="java:global/cdi-application-scope/Waiter!org.superbiz.cdi.applicationscope.Waiter") +INFO - Jndi(name="java:global/cdi-application-scope/Waiter") +INFO - Created Ejb(deployment-id=Waiter, ejb-name=Waiter, container=Default Stateless Container) +INFO - Started Ejb(deployment-id=Waiter, ejb-name=Waiter, container=Default Stateless Container) +INFO - Deployed Application(path=c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope) +Soup created +INFO - Undeploying app: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.42 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-application-scope/README.md ---------------------------------------------------------------------- diff --git a/examples/cdi-application-scope/README.md b/examples/cdi-application-scope/README.md deleted file mode 100644 index e7938e3..0000000 --- a/examples/cdi-application-scope/README.md +++ /dev/null @@ -1,137 +0,0 @@ -index-group=CDI -type=page -status=published -title=CDI @ApplicationScoped -~~~~~~ - -This example show the use of `@ApplicationScoped` annotation for injected objects. An object -which is defined as `@ApplicationScoped` is created once for the duration of the application. - -# Example - -This example depicts a similar scenario to cdi-request-scope. A restaurant guest orders -a soup from the waiter. The waiter then delivers the soup back to the guest. Another -guest can order the same soup that was ordered by the previous client - this is where -the application scope is used. - -## Waiter - -The `Waiter` session bean receives a request from the test class via the `orderSoup()` method -and sets the name for the `soup` field. The `orderWhatTheOtherGuyHad()` method returns -the name of the `soup` field. - - @Stateless - public class Waiter { - - @Inject - public Soup soup; - - public String orderSoup(String name){ - soup.setName(name); - return soup.getName(); - } - - public String orderWhatTheOtherGuyHad() { - String name = soup.getName(); - return name; - } - } - -## Soup - -The `Soup` class is an injectable POJO, defined as `@ApplicationScoped`. This means that an instance -will be created only once for the duration of the whole application. Try changing the `@ApplicationScoped` -annotation to `@RequestScoped` and see what happens. - - @ApplicationScoped - public class Soup { - - private String name = "Soup of the day"; - - @PostConstruct - public void afterCreate() { - System.out.println("Soup created"); - } - - public String getName() { - return name; - } - - public void setName(String name){ - this.name = name; - } - } - - -# Test Case - -This is the entry class for this example. First a soup is ordered via `orderSoup()` method. -This initiates the `soup` field. Next, `orderWhatTheOtherGuyHad()` method returns the soup -from the application context. - - public class RestaurantTest { - - private static String TOMATO_SOUP = "Tomato Soup"; - private EJBContainer container; - - @EJB - private Waiter joe; - - @Before - public void startContainer() throws Exception { - container = EJBContainer.createEJBContainer(); - container.getContext().bind("inject", this); - } - - @Test - public void orderSoup(){ - String someSoup = joe.orderSoup(TOMATO_SOUP); - assertEquals(TOMATO_SOUP, someSoup); - - String sameSoup = joe.orderWhatTheOtherGuyHad(); - assertEquals(TOMATO_SOUP, sameSoup); - } - - @After - public void closeContainer() throws Exception { - container.close(); - } - } - -# Running - -In the output you can see that there is just one `Soup` instance created - one for -the whole application. - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.cdi.applicationscope.RestaurantTest - Apache OpenEJB 7.0.0-SNAPSHOT build: 20111224-11:09 - http://tomee.apache.org/ - INFO - openejb.home = C:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope - INFO - openejb.base = C:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope - 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: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope\target\classes - INFO - Beginning load: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope\target\classes - INFO - Configuring enterprise application: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean cdi-application-scope.Comp: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container) - INFO - Auto-creating a container for bean Waiter: Container(type=STATELESS, id=Default Stateless Container) - INFO - Enterprise application "c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope" loaded. - INFO - Assembling app: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope - INFO - Jndi(name="java:global/cdi-application-scope/Waiter!org.superbiz.cdi.applicationscope.Waiter") - INFO - Jndi(name="java:global/cdi-application-scope/Waiter") - INFO - Created Ejb(deployment-id=Waiter, ejb-name=Waiter, container=Default Stateless Container) - INFO - Started Ejb(deployment-id=Waiter, ejb-name=Waiter, container=Default Stateless Container) - INFO - Deployed Application(path=c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope) - Soup created - INFO - Undeploying app: c:\Users\Daniel\workspaces\openejb\openejb\examples\cdi-application-scope - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.42 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-basic/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cdi-basic/README.adoc b/examples/cdi-basic/README.adoc new file mode 100644 index 0000000..0df7a93 --- /dev/null +++ b/examples/cdi-basic/README.adoc @@ -0,0 +1,174 @@ += CDI @Inject +:index-group: CDI +:jbake-type: page +:jbake-status: published + +To use `@Inject`, the first thing you need is a `META-INF/beans.xml` file in the module +or jar. This effectively turns on CDI and allows the `@Inject` references to work. +No `META-INF/beans.xml` no injection, period. This may seem overly strict, +but it is not without reason. The CDI API is a bit greedy and does consume a fair +amount of resources by design. + +When the container constructs a bean with an `@Inject` reference, +it will first find or create the object that will be injected. For the sake of +simplicity, the is example has a basic `Faculty` pojo with a no-arg constructor. Anyone +referencing `@Inject Faculty` will get their own instance of `Faculty`. If the desire +is to share the same instance of `Faculty`, see the concept of `scopes` -- this is +exactly what scopes are for. + +== Example + +In this example, we have an `@Stateless` bean `Course` with an `@Inject` reference to an +object of type `Faculty`. When `Course` is created, the container will also create an +instance of `Faculty`. The `@PostConstruct` will be called on the `Faculty`, +then the `Faculty` instance will be injected into the `Course` bean. Finally, the +`@PostConstruct` will be invoked on `Course` and then we're done. All instances will +have been created. + +The `CourseTest` test case drives this creation process by having `Course` injected +in its `@Setup` method. By the time our `@Test` method is invoked, +all the real work should be done and we should be ready to go. In the test case we do +some basic asserts to ensure everything was constructed, all `@PostConstruct` methods +called and everything injected. + +=== Faculty +++<small>+++a basic injectable pojo+++</small>+++ + +.... +public class Faculty { + + private List<String> facultyMembers; + + private String facultyName; + + @PostConstruct + public void initialize() { + this.facultyMembers = new ArrayList<String>(); + facultyMembers.add("Ian Schultz"); + facultyMembers.add("Diane Reyes"); + facultyName = "Computer Science"; + } + + public List<String> getFacultyMembers() { + return facultyMembers; + } + + public String getFacultyName() { + return facultyName; + } + +} +.... + +=== Course +++<small>+++a simple session bean+++</small>+++ + +.... +@Stateless +public class Course { + + @Inject + private Faculty faculty; + + private String courseName; + + private int capacity; + + @PostConstruct + private void init() { + assert faculty != null; + + // These strings can be externalized + // We'll see how to do that later + this.courseName = "CDI 101 - Introduction to CDI"; + this.capacity = 100; + } + + public String getCourseName() { + return courseName; + } + + public int getCapacity() { + return capacity; + } + + public Faculty getFaculty() { + return faculty; + } +} +.... + +== Test Case + +.... +public class CourseTest extends TestCase { + + @EJB + private Course course; + + @Before + public void setUp() throws Exception { + EJBContainer.createEJBContainer().getContext().bind("inject", this); + } + + @Test + public void test() { + + // Was the EJB injected? + assertTrue(course != null); + + // Was the Course @PostConstruct called? + assertNotNull(course.getCourseName()); + assertTrue(course.getCapacity() > 0); + + // Was a Faculty instance injected into Course? + final Faculty faculty = course.getFaculty(); + assertTrue(faculty != null); + + // Was the @PostConstruct called on Faculty? + assertEquals(faculty.getFacultyName(), "Computer Science"); + assertEquals(faculty.getFacultyMembers().size(), 2); + } +} +.... + +== Running + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.cdi.basic.CourseTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/cdi-basic +INFO - openejb.base = /Users/dblevins/examples/cdi-basic +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/cdi-basic/target/classes +INFO - Beginning load: /Users/dblevins/examples/cdi-basic/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/cdi-basic +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean cdi-basic.Comp: Container(type=MANAGED, id=Default Managed Container) +INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container) +INFO - Auto-creating a container for bean Course: Container(type=STATELESS, id=Default Stateless Container) +INFO - Enterprise application "/Users/dblevins/examples/cdi-basic" loaded. +INFO - Assembling app: /Users/dblevins/examples/cdi-basic +INFO - Jndi(name="java:global/cdi-basic/cdi-basic.Comp!org.apache.openejb.BeanContext$Comp") +INFO - Jndi(name="java:global/cdi-basic/cdi-basic.Comp") +INFO - Jndi(name="java:global/cdi-basic/Course!org.superbiz.cdi.basic.Course") +INFO - Jndi(name="java:global/cdi-basic/Course") +INFO - Jndi(name="java:global/EjbModule1833350875/org.superbiz.cdi.basic.CourseTest!org.superbiz.cdi.basic.CourseTest") +INFO - Jndi(name="java:global/EjbModule1833350875/org.superbiz.cdi.basic.CourseTest") +INFO - Created Ejb(deployment-id=Course, ejb-name=Course, container=Default Stateless Container) +INFO - Created Ejb(deployment-id=cdi-basic.Comp, ejb-name=cdi-basic.Comp, container=Default Managed Container) +INFO - Created Ejb(deployment-id=org.superbiz.cdi.basic.CourseTest, ejb-name=org.superbiz.cdi.basic.CourseTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=Course, ejb-name=Course, container=Default Stateless Container) +INFO - Started Ejb(deployment-id=cdi-basic.Comp, ejb-name=cdi-basic.Comp, container=Default Managed Container) +INFO - Started Ejb(deployment-id=org.superbiz.cdi.basic.CourseTest, ejb-name=org.superbiz.cdi.basic.CourseTest, container=Default Managed Container) +INFO - Deployed Application(path=/Users/dblevins/examples/cdi-basic) +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.126 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-basic/README.md ---------------------------------------------------------------------- diff --git a/examples/cdi-basic/README.md b/examples/cdi-basic/README.md deleted file mode 100644 index 961acaa..0000000 --- a/examples/cdi-basic/README.md +++ /dev/null @@ -1,169 +0,0 @@ -index-group=CDI -type=page -status=published -title=CDI @Inject -~~~~~~ - -To use `@Inject`, the first thing you need is a `META-INF/beans.xml` file in the module -or jar. This effectively turns on CDI and allows the `@Inject` references to work. -No `META-INF/beans.xml` no injection, period. This may seem overly strict, -but it is not without reason. The CDI API is a bit greedy and does consume a fair -amount of resources by design. - -When the container constructs a bean with an `@Inject` reference, -it will first find or create the object that will be injected. For the sake of -simplicity, the is example has a basic `Faculty` pojo with a no-arg constructor. Anyone -referencing `@Inject Faculty` will get their own instance of `Faculty`. If the desire -is to share the same instance of `Faculty`, see the concept of `scopes` -- this is -exactly what scopes are for. - -# Example - -In this example, we have an `@Stateless` bean `Course` with an `@Inject` reference to an -object of type `Faculty`. When `Course` is created, the container will also create an -instance of `Faculty`. The `@PostConstruct` will be called on the `Faculty`, -then the `Faculty` instance will be injected into the `Course` bean. Finally, the -`@PostConstruct` will be invoked on `Course` and then we're done. All instances will -have been created. - -The `CourseTest` test case drives this creation process by having `Course` injected -in its `@Setup` method. By the time our `@Test` method is invoked, -all the real work should be done and we should be ready to go. In the test case we do -some basic asserts to ensure everything was constructed, all `@PostConstruct` methods -called and everything injected. - - -## Faculty <small>a basic injectable pojo</small> - - public class Faculty { - - private List<String> facultyMembers; - - private String facultyName; - - @PostConstruct - public void initialize() { - this.facultyMembers = new ArrayList<String>(); - facultyMembers.add("Ian Schultz"); - facultyMembers.add("Diane Reyes"); - facultyName = "Computer Science"; - } - - public List<String> getFacultyMembers() { - return facultyMembers; - } - - public String getFacultyName() { - return facultyName; - } - - } - -## Course <small>a simple session bean</small> - - @Stateless - public class Course { - - @Inject - private Faculty faculty; - - private String courseName; - - private int capacity; - - @PostConstruct - private void init() { - assert faculty != null; - - // These strings can be externalized - // We'll see how to do that later - this.courseName = "CDI 101 - Introduction to CDI"; - this.capacity = 100; - } - - public String getCourseName() { - return courseName; - } - - public int getCapacity() { - return capacity; - } - - public Faculty getFaculty() { - return faculty; - } - } - -# Test Case - - public class CourseTest extends TestCase { - - @EJB - private Course course; - - @Before - public void setUp() throws Exception { - EJBContainer.createEJBContainer().getContext().bind("inject", this); - } - - @Test - public void test() { - - // Was the EJB injected? - assertTrue(course != null); - - // Was the Course @PostConstruct called? - assertNotNull(course.getCourseName()); - assertTrue(course.getCapacity() > 0); - - // Was a Faculty instance injected into Course? - final Faculty faculty = course.getFaculty(); - assertTrue(faculty != null); - - // Was the @PostConstruct called on Faculty? - assertEquals(faculty.getFacultyName(), "Computer Science"); - assertEquals(faculty.getFacultyMembers().size(), 2); - } - } - -# Running - - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.cdi.basic.CourseTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/cdi-basic - INFO - openejb.base = /Users/dblevins/examples/cdi-basic - 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/cdi-basic/target/classes - INFO - Beginning load: /Users/dblevins/examples/cdi-basic/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/cdi-basic - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean cdi-basic.Comp: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container) - INFO - Auto-creating a container for bean Course: Container(type=STATELESS, id=Default Stateless Container) - INFO - Enterprise application "/Users/dblevins/examples/cdi-basic" loaded. - INFO - Assembling app: /Users/dblevins/examples/cdi-basic - INFO - Jndi(name="java:global/cdi-basic/cdi-basic.Comp!org.apache.openejb.BeanContext$Comp") - INFO - Jndi(name="java:global/cdi-basic/cdi-basic.Comp") - INFO - Jndi(name="java:global/cdi-basic/Course!org.superbiz.cdi.basic.Course") - INFO - Jndi(name="java:global/cdi-basic/Course") - INFO - Jndi(name="java:global/EjbModule1833350875/org.superbiz.cdi.basic.CourseTest!org.superbiz.cdi.basic.CourseTest") - INFO - Jndi(name="java:global/EjbModule1833350875/org.superbiz.cdi.basic.CourseTest") - INFO - Created Ejb(deployment-id=Course, ejb-name=Course, container=Default Stateless Container) - INFO - Created Ejb(deployment-id=cdi-basic.Comp, ejb-name=cdi-basic.Comp, container=Default Managed Container) - INFO - Created Ejb(deployment-id=org.superbiz.cdi.basic.CourseTest, ejb-name=org.superbiz.cdi.basic.CourseTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=Course, ejb-name=Course, container=Default Stateless Container) - INFO - Started Ejb(deployment-id=cdi-basic.Comp, ejb-name=cdi-basic.Comp, container=Default Managed Container) - INFO - Started Ejb(deployment-id=org.superbiz.cdi.basic.CourseTest, ejb-name=org.superbiz.cdi.basic.CourseTest, container=Default Managed Container) - INFO - Deployed Application(path=/Users/dblevins/examples/cdi-basic) - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.126 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-events/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cdi-events/README.adoc b/examples/cdi-events/README.adoc new file mode 100644 index 0000000..5f3d047 --- /dev/null +++ b/examples/cdi-events/README.adoc @@ -0,0 +1,35 @@ += CDI events - Loose coupling and extensibility +:index-group: CDI +:jbake-type: page +:jbake-status: published + +CDI allows you to extend business code by the Notifier/Observer pattern. + +To do it you simply inject a field `Event` in the notifier class. This class is a template +and the parameter type is the object type to fire. Then when you want to notify observers +you simply call the method fire of the event object passing as a parameter the event itself +(your own class!). + +On the other side you annotated a method parameter `@Observes` and the parameter type is the sent type +by the notifier. + +NOTE: of course you can add qualifiers to be more precise on your events. + +== Example + +The example is pretty simple: an ejb uses the `@Schedule` annotation to get a notification each second. +The each second this EJB will send the current date through CDI events. + +This is our "business" code. It is a simple behavior (nothing). + +In our test (which is considered as an extension) we created an observer (`Observer` class) +which simply store and log each received date. + +The test itself (`EventTest`) simply verifies the dates were received. + +== Conclusion + +CDI let's you implement very easily plugins through this event mecanism. + +If you go further and look at CDI plugin API you'll realize it is simply the same kind +of events. CDI events is really the basis of CDI. http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-events/README.md ---------------------------------------------------------------------- diff --git a/examples/cdi-events/README.md b/examples/cdi-events/README.md deleted file mode 100644 index 388b9d4..0000000 --- a/examples/cdi-events/README.md +++ /dev/null @@ -1,37 +0,0 @@ -index-group=Unrevised -type=page -status=published -title=CDI Events -~~~~~~ -# CDI events: loose coupling and extensibility - -CDI allows you to extend business code by the Notifier/Observer pattern. - -To do it you simply inject a field `Event` in the notifier class. This class is a template -and the parameter type is the object type to fire. Then when you want to notify observers -you simply call the method fire of the event object passing as a parameter the event itself -(your own class!). - -On the other side you annotated a method parameter `@Observes` and the parameter type is the sent type -by the notifier. - -Note: of course you can add qualifiers to be more precise on your events. - -# The example - -The example is pretty simple: an ejb uses the `@Schedule` annotation to get a notification each second. -The each second this EJB will send the current date through CDI events. - -This is our "business" code. It is a simple behavior (nothing). - -In our test (which is considered as an extension) we created an observer (`Observer` class) -which simply store and log each received date. - -The test itself (`EventTest`) simply verifies the dates were received. - -# Conclusion - -CDI let's you implement very easily plugins through this event mecanism. - -If you go further and look at CDI plugin API you'll realize it is simply the same kind -of events. CDI events is really the basis of CDI. http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-interceptors/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cdi-interceptors/README.adoc b/examples/cdi-interceptors/README.adoc new file mode 100644 index 0000000..d9349f3 --- /dev/null +++ b/examples/cdi-interceptors/README.adoc @@ -0,0 +1,220 @@ += CDI Interceptors +:index-group: CDI +:jbake-type: page +:jbake-status: published + +Let's write a simple application that would allow us to book tickets for a movie show. As with all applications, logging is one cross-cutting concern that we have. Apart from that, there are some methods in our application, that can be accessed only in the working hours. If accessed at non-working-hours we'll throw out an AccessDeniedException. + +How do we mark which methods are to be intercepted? Wouldn't it be handy to annotate a method like + + @Log + public void aMethod(){...} + +or + + @TimeRestricted + public void bMethod(){...} + +Let's create these annotations that would "mark" a method for interception. + + @InterceptorBinding + @Target({ TYPE, METHOD }) + @Retention(RUNTIME) + public @interface Log { + } + +And + + @InterceptorBinding + @Target({ TYPE, METHOD }) + @Retention(RUNTIME) + public @interface TimeRestricted { + } + +Sure, you haven't missed the `@InterceptorBinding` annotation above! Now that our custom annotations are created, lets attach them (or to use a better term for it, "bind them") to interceptors. + +So here's our logging interceptor. An `@AroundInvoke` method and we are almost done. + + @Interceptor + @Log //binding the interceptor here. now any method annotated with @Log would be intercepted by logMethodEntry + public class BookForAShowLoggingInterceptor implements Serializable { + private static final long serialVersionUID = 8139854519874743530L; + private Logger logger = Logger.getLogger("BookForAShowApplicationLogger"); + @AroundInvoke + public Object logMethodEntry(InvocationContext ctx) throws Exception { + logger.info("Before entering method:" + ctx.getMethod().getName()); + InterceptionOrderTracker.getMethodsInterceptedList().add(ctx.getMethod().getName()); + InterceptionOrderTracker.getInterceptedByList().add(this.getClass().getSimpleName()); + return ctx.proceed(); + } + } + +Now the `@Log` annotation we created is bound to this interceptor. (Likewise we bind `@TimeRestrict` for `TimeBasedRestrictingInterceptor`. See links below for source) + +That done, let's annotate at class-level or method-level and have fun intercepting! + + @Log + @Stateful + public class BookForAShowOneInterceptorApplied implements Serializable { + private static final long serialVersionUID = 6350400892234496909L; + public List<String> getMoviesList() { + List<String> moviesAvailable = new ArrayList<String>(); + moviesAvailable.add("12 Angry Men"); + moviesAvailable.add("Kings speech"); + return moviesAvailable; + } + public Integer getDiscountedPrice(int ticketPrice) { + return ticketPrice - 50; + } + // assume more methods are present + } + +The `@Log` annotation applied at class level denotes that all the methods should be intercepted with `BookForAShowLoggingInterceptor`. + +Before we say "all done" there's one last thing we are left with! To enable the interceptors! + +Lets quickly put up a `beans.xml` file like the following in `src/main/resources/META-INF/beans.xml`: + + <beans> + <interceptors> + <class>org.superbiz.cdi.bookshow.interceptors.BookForAShowLoggingInterceptor + </class> + <class>org.superbiz.cdi.bookshow.interceptors.TimeBasedRestrictingInterceptor + </class> + </interceptors> + </beans> + +By default, a bean archive has no enabled interceptors; an interceptor must be explicitly enabled by listing its class +in the `beans.xml`. + +The order of the interceptor annotations has no real significance. +Eg: + + @TimeRestrict + @Log + void cMethod(){} + +It is the `interceptor` elements in `beans.xml` that not only "enable" the interceptors, but also define the "order of execution" of the interceptors. In this case the `BookForAShowLoggingInterceptor` would be applied first and then `TimeBasedRestrictingInterceptor` + +So now you know that the order is only determined by the order within the `interceptors` element within the `beans.xml`. The rule is simple, interceptors which occur earlier in the list are called first. + +Also note that a method can be marked for interception using multiple interceptors by applying multiple annotations as above. + +This brings us to another question. In the above case there were two interceptors applied together. What if I would require about 4 such interceptors that would go along.... Having to annotate so much makes the code a little clumsy? + +No worries! Just create a custom annotation which inherits from others + + @Inherited + @InterceptorBinding + @Target({ TYPE, METHOD }) + @Retention(RUNTIME) + @Log + @TimeRestricted + public @interface TimeRestrictAndLog { + } + +This is interceptor binding inheritance. + +The code below demonstrates the many cases that we have discussed. + +Not to forget, the old style binding with `@Interceptors(WhicheverInterceptor.class)` is also supported. Have a look at `BookForAShowOldStyleInterceptorBinding` where the comments explain how the newer way discussed above is better. + +== The Code + +=== BookForAShowOneInterceptorApplied + +`BookForAShowOneInterceptorApplied` shows a simple `@Log` interceptor applied. + +.... +package org.superbiz.cdi.bookshow.beans; + +import org.superbiz.cdi.bookshow.interceptorbinding.Log; + +import javax.ejb.Stateful; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Log +@Stateful +public class BookForAShowOneInterceptorApplied implements Serializable { + private static final long serialVersionUID = 6350400892234496909L; + + public List<String> getMoviesList() { + List<String> moviesAvailable = new ArrayList<String>(); + moviesAvailable.add("12 Angry Men"); + moviesAvailable.add("Kings speech"); + return moviesAvailable; + } + + public Integer getDiscountedPrice(int ticketPrice) { + return ticketPrice - 50; + } +} +.... + +=== BookForAShowTwoInterceptorsApplied + +`BookForAShowTwoInterceptorsApplied` shows both `@Log` and `@TimeRestricted` being applied. + +.... +package org.superbiz.cdi.bookshow.beans; + +import org.superbiz.cdi.bookshow.interceptorbinding.Log; +import org.superbiz.cdi.bookshow.interceptorbinding.TimeRestricted; + +import javax.ejb.Stateful; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Log +@Stateful +public class BookForAShowTwoInterceptorsApplied implements Serializable { + private static final long serialVersionUID = 6350400892234496909L; + + public List<String> getMoviesList() { + List<String> moviesAvailable = new ArrayList<String>(); + moviesAvailable.add("12 Angry Men"); + moviesAvailable.add("Kings speech"); + return moviesAvailable; + } + + @TimeRestricted + public Integer getDiscountedPrice(int ticketPrice) { + return ticketPrice - 50; + } +} +.... + +=== BookShowInterceptorBindingInheritanceExplored + +`BookShowInterceptorBindingInheritanceExplored` shows how `@TimeRestrictAndLog` (interceptor-binding-inheritance) can be used as an alternative for annotating a method with multiple annotations explicitly. + +.... +package org.superbiz.cdi.bookshow.beans; + +import org.superbiz.cdi.bookshow.interceptorbinding.TimeRestrictAndLog; + +import javax.ejb.Stateful; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@Stateful +public class BookShowInterceptorBindingInheritanceExplored implements Serializable { + private static final long serialVersionUID = 6350400892234496909L; + + public List<String> getMoviesList() { + List<String> moviesAvailable = new ArrayList<String>(); + moviesAvailable.add("12 Angry Men"); + moviesAvailable.add("Kings speech"); + return moviesAvailable; + } + + @TimeRestrictAndLog + public Integer getDiscountedPrice(int ticketPrice) { + return ticketPrice - 50; + } +} +.... http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-interceptors/README.md ---------------------------------------------------------------------- diff --git a/examples/cdi-interceptors/README.md b/examples/cdi-interceptors/README.md deleted file mode 100644 index 3744554..0000000 --- a/examples/cdi-interceptors/README.md +++ /dev/null @@ -1,216 +0,0 @@ -index-group=Unrevised -type=page -status=published -title=CDI Interceptors -~~~~~~ - -Let's write a simple application that would allow us to book tickets for a movie show. As with all applications, logging is one cross-cutting concern that we have. Apart from that, there are some methods in our application, that can be accessed only in the working hours. If accessed at non-working-hours we'll throw out an AccessDeniedException. - -How do we mark which methods are to be intercepted? Wouldn't it be handy to annotate a method like - - @Log - public void aMethod(){...} - -or - - @TimeRestricted - public void bMethod(){...} - -Let's create these annotations that would "mark" a method for interception. - - @InterceptorBinding - @Target({ TYPE, METHOD }) - @Retention(RUNTIME) - public @interface Log { - } - -And - - @InterceptorBinding - @Target({ TYPE, METHOD }) - @Retention(RUNTIME) - public @interface TimeRestricted { - } - -Sure, you haven't missed the `@InterceptorBinding` annotation above! Now that our custom annotations are created, lets attach them (or to use a better term for it, "bind them") to interceptors. - -So here's our logging interceptor. An `@AroundInvoke` method and we are almost done. - - @Interceptor - @Log //binding the interceptor here. now any method annotated with @Log would be intercepted by logMethodEntry - public class BookForAShowLoggingInterceptor implements Serializable { - private static final long serialVersionUID = 8139854519874743530L; - private Logger logger = Logger.getLogger("BookForAShowApplicationLogger"); - @AroundInvoke - public Object logMethodEntry(InvocationContext ctx) throws Exception { - logger.info("Before entering method:" + ctx.getMethod().getName()); - InterceptionOrderTracker.getMethodsInterceptedList().add(ctx.getMethod().getName()); - InterceptionOrderTracker.getInterceptedByList().add(this.getClass().getSimpleName()); - return ctx.proceed(); - } - } - -Now the `@Log` annotation we created is bound to this interceptor. (Likewise we bind `@TimeRestrict` for `TimeBasedRestrictingInterceptor`. See links below for source) - -That done, let's annotate at class-level or method-level and have fun intercepting! - - @Log - @Stateful - public class BookForAShowOneInterceptorApplied implements Serializable { - private static final long serialVersionUID = 6350400892234496909L; - public List<String> getMoviesList() { - List<String> moviesAvailable = new ArrayList<String>(); - moviesAvailable.add("12 Angry Men"); - moviesAvailable.add("Kings speech"); - return moviesAvailable; - } - public Integer getDiscountedPrice(int ticketPrice) { - return ticketPrice - 50; - } - // assume more methods are present - } - -The `@Log` annotation applied at class level denotes that all the methods should be intercepted with `BookForAShowLoggingInterceptor`. - -Before we say "all done" there's one last thing we are left with! To enable the interceptors! - -Lets quickly put up a `beans.xml` file like the following in `src/main/resources/META-INF/beans.xml`: - - <beans> - <interceptors> - <class>org.superbiz.cdi.bookshow.interceptors.BookForAShowLoggingInterceptor - </class> - <class>org.superbiz.cdi.bookshow.interceptors.TimeBasedRestrictingInterceptor - </class> - </interceptors> - </beans> - - -By default, a bean archive has no enabled interceptors; an interceptor must be explicitly enabled by listing its class -in the `beans.xml`. - -The order of the interceptor annotations has no real significance. -Eg: - - @TimeRestrict - @Log - void cMethod(){} - -It is the `interceptor` elements in `beans.xml` that not only "enable" the interceptors, but also define the "order of execution" of the interceptors. In this case the `BookForAShowLoggingInterceptor` would be applied first and then `TimeBasedRestrictingInterceptor` - -So now you know that the order is only determined by the order within the `interceptors` element within the `beans.xml`. The rule is simple, interceptors which occur earlier in the list are called first. - -Also note that a method can be marked for interception using multiple interceptors by applying multiple annotations as above. - -This brings us to another question. In the above case there were two interceptors applied together. What if I would require about 4 such interceptors that would go along.... Having to annotate so much makes the code a little clumsy? - -No worries! Just create a custom annotation which inherits from others - - @Inherited - @InterceptorBinding - @Target({ TYPE, METHOD }) - @Retention(RUNTIME) - @Log - @TimeRestricted - public @interface TimeRestrictAndLog { - } - -This is interceptor binding inheritance. - -The code below demonstrates the many cases that we have discussed. - -Not to forget, the old style binding with `@Interceptors(WhicheverInterceptor.class)` is also supported. Have a look at `BookForAShowOldStyleInterceptorBinding` where the comments explain how the newer way discussed above is better. - -# The Code - -## BookForAShowOneInterceptorApplied - -`BookForAShowOneInterceptorApplied` shows a simple `@Log` interceptor applied. - - package org.superbiz.cdi.bookshow.beans; - - import org.superbiz.cdi.bookshow.interceptorbinding.Log; - - import javax.ejb.Stateful; - import java.io.Serializable; - import java.util.ArrayList; - import java.util.List; - - @Log - @Stateful - public class BookForAShowOneInterceptorApplied implements Serializable { - private static final long serialVersionUID = 6350400892234496909L; - - public List<String> getMoviesList() { - List<String> moviesAvailable = new ArrayList<String>(); - moviesAvailable.add("12 Angry Men"); - moviesAvailable.add("Kings speech"); - return moviesAvailable; - } - - public Integer getDiscountedPrice(int ticketPrice) { - return ticketPrice - 50; - } - } - -## BookForAShowTwoInterceptorsApplied - -`BookForAShowTwoInterceptorsApplied` shows both `@Log` and `@TimeRestricted` being applied. - - package org.superbiz.cdi.bookshow.beans; - - import org.superbiz.cdi.bookshow.interceptorbinding.Log; - import org.superbiz.cdi.bookshow.interceptorbinding.TimeRestricted; - - import javax.ejb.Stateful; - import java.io.Serializable; - import java.util.ArrayList; - import java.util.List; - - @Log - @Stateful - public class BookForAShowTwoInterceptorsApplied implements Serializable { - private static final long serialVersionUID = 6350400892234496909L; - - public List<String> getMoviesList() { - List<String> moviesAvailable = new ArrayList<String>(); - moviesAvailable.add("12 Angry Men"); - moviesAvailable.add("Kings speech"); - return moviesAvailable; - } - - @TimeRestricted - public Integer getDiscountedPrice(int ticketPrice) { - return ticketPrice - 50; - } - } - -## BookShowInterceptorBindingInheritanceExplored - -`BookShowInterceptorBindingInheritanceExplored` shows how `@TimeRestrictAndLog` (interceptor-binding-inheritance) can be used as an alternative for annotating a method with multiple annotations explicitly. - - package org.superbiz.cdi.bookshow.beans; - - import org.superbiz.cdi.bookshow.interceptorbinding.TimeRestrictAndLog; - - import javax.ejb.Stateful; - import java.io.Serializable; - import java.util.ArrayList; - import java.util.List; - - @Stateful - public class BookShowInterceptorBindingInheritanceExplored implements Serializable { - private static final long serialVersionUID = 6350400892234496909L; - - public List<String> getMoviesList() { - List<String> moviesAvailable = new ArrayList<String>(); - moviesAvailable.add("12 Angry Men"); - moviesAvailable.add("Kings speech"); - return moviesAvailable; - } - - @TimeRestrictAndLog - public Integer getDiscountedPrice(int ticketPrice) { - return ticketPrice - 50; - } - } http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-produces-disposes/README.adoc ---------------------------------------------------------------------- diff --git a/examples/cdi-produces-disposes/README.adoc b/examples/cdi-produces-disposes/README.adoc new file mode 100644 index 0000000..c144f93 --- /dev/null +++ b/examples/cdi-produces-disposes/README.adoc @@ -0,0 +1,292 @@ += CDI Produces Disposes +:index-group: CDI +:jbake-type: page +:jbake-status: published + +This example shows how the @Produces and @Disposes annotations work. A LogFactory creates an instance of the LogHandler +depending on a "type" attribute. For the purposes of this example, the type is hard-coded to a specific value. +A Logger implementation shall contain a list of LogHandlers. We shall have three implementations of the LogHandler interface. + +* A DatabaseHandler +* A FileHandler +* A ConsoleHandler + +The DatabaseHandler would seemingly write the logs to a database. The FileHandler would write the same logs to a file. +The ConsoleHandler would just print the logs to a console (Standard out). This example is just an illustration of how +the concepts within CDI work and is not intended to provide a logging framework design/implementation. + +_Help us finish documenting this example! Click the blue pencil icon in the upper right to edit this page._ + +== ConsoleHandler + +.... +package org.superbiz.cdi.produces.disposes; + +public class ConsoleHandler implements LogHandler { + + private String name; + + public ConsoleHandler(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public void writeLog(String s) { + System.out.printf("##### Handler: %s, Writing to the console!\n", getName()); + } +} +.... + +== DatabaseHandler + +.... +package org.superbiz.cdi.produces.disposes; + +public class DatabaseHandler implements LogHandler { + + private String name; + + public DatabaseHandler(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public void writeLog(String s) { + System.out.printf("##### Handler: %s, Writing to the database!\n", getName()); + // Use connection to write log to database + } +} +.... + +== FileHandler + +.... +package org.superbiz.cdi.produces.disposes; + +public class FileHandler implements LogHandler { + + private String name; + + public FileHandler(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public void writeLog(String s) { + System.out.printf("##### Handler: %s, Writing to the file!\n", getName()); + // Write to log file + } +} +.... + +== LogFactory + +.... +package org.superbiz.cdi.produces.disposes; + +import javax.enterprise.inject.Disposes; +import javax.enterprise.inject.Produces; + +public class LogFactory { + + private int type = 2; + + @Produces + public LogHandler getLogHandler() { + switch (type) { + case 1: + return new FileHandler("@Produces created FileHandler!"); + case 2: + return new DatabaseHandler("@Produces created DatabaseHandler!"); + case 3: + default: + return new ConsoleHandler("@Produces created ConsoleHandler!"); + } + } + + public void closeLogHandler(@Disposes LogHandler handler) { + switch (type) { + case 1: + System.out.println("Closing File handler!"); + break; + case 2: + System.out.println("Closing DB handler!"); + break; + case 3: + default: + System.out.println("Closing Console handler!"); + } + } +} +.... + +== Logger + +.... +package org.superbiz.cdi.produces.disposes; + +public interface Logger { + + public void log(String s); + + public LogHandler getHandler(); +} +.... + +== LoggerImpl + +.... +package org.superbiz.cdi.produces.disposes; + +import javax.inject.Inject; +import javax.inject.Named; + +@Named("logger") +public class LoggerImpl implements Logger { + + @Inject + private LogHandler handler; + + @Override + public void log(String s) { + getHandler().writeLog(s); + } + + public LogHandler getHandler() { + return handler; + } +} +.... + +== LogHandler + +.... +package org.superbiz.cdi.produces.disposes; + +public interface LogHandler { + + public String getName(); + + public void writeLog(String s); +} +.... + +== beans.xml + +.... +<beans 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/beans_1_0.xsd"> + +</beans> +.... + +== LoggerTest + +.... +package org.superbiz.cdi.produces.disposes; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import javax.ejb.embeddable.EJBContainer; +import javax.inject.Inject; +import javax.naming.Context; + +import static junit.framework.Assert.assertNotNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class LoggerTest { + + @Inject + Logger logger; + + private Context ctxt; + + @Before + public void setUp() { + try { + ctxt = EJBContainer.createEJBContainer().getContext(); + ctxt.bind("inject", this); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @After + public void cleanUp() { + try { + ctxt.unbind("inject"); + ctxt.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Test + public void testLogHandler() { + assertNotNull(logger); + assertFalse("Handler should not be a ConsoleHandler", logger.getHandler() instanceof ConsoleHandler); + assertFalse("Handler should not be a FileHandler", logger.getHandler() instanceof FileHandler); + assertTrue("Handler should be a DatabaseHandler", logger.getHandler() instanceof DatabaseHandler); + logger.log("##### Testing write\n"); + logger = null; + } + +} +.... + += Running + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.cdi.produces.disposes.LoggerTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/cdi-produces-disposes +INFO - openejb.base = /Users/dblevins/examples/cdi-produces-disposes +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/cdi-produces-disposes/target/classes +INFO - Beginning load: /Users/dblevins/examples/cdi-produces-disposes/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/cdi-produces-disposes +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean cdi-produces-disposes.Comp: Container(type=MANAGED, id=Default Managed Container) +INFO - Enterprise application "/Users/dblevins/examples/cdi-produces-disposes" loaded. +INFO - Assembling app: /Users/dblevins/examples/cdi-produces-disposes +INFO - Jndi(name="java:global/cdi-produces-disposes/cdi-produces-disposes.Comp!org.apache.openejb.BeanContext$Comp") +INFO - Jndi(name="java:global/cdi-produces-disposes/cdi-produces-disposes.Comp") +INFO - Jndi(name="java:global/EjbModule10202458/org.superbiz.cdi.produces.disposes.LoggerTest!org.superbiz.cdi.produces.disposes.LoggerTest") +INFO - Jndi(name="java:global/EjbModule10202458/org.superbiz.cdi.produces.disposes.LoggerTest") +INFO - Created Ejb(deployment-id=cdi-produces-disposes.Comp, ejb-name=cdi-produces-disposes.Comp, container=Default Managed Container) +INFO - Created Ejb(deployment-id=org.superbiz.cdi.produces.disposes.LoggerTest, ejb-name=org.superbiz.cdi.produces.disposes.LoggerTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=cdi-produces-disposes.Comp, ejb-name=cdi-produces-disposes.Comp, container=Default Managed Container) +INFO - Started Ejb(deployment-id=org.superbiz.cdi.produces.disposes.LoggerTest, ejb-name=org.superbiz.cdi.produces.disposes.LoggerTest, container=Default Managed Container) +INFO - Deployed Application(path=/Users/dblevins/examples/cdi-produces-disposes) +##### Handler: @Produces created DatabaseHandler!, Writing to the database! +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.02 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... http://git-wip-us.apache.org/repos/asf/tomee/blob/180f5c5f/examples/cdi-produces-disposes/README.md ---------------------------------------------------------------------- diff --git a/examples/cdi-produces-disposes/README.md b/examples/cdi-produces-disposes/README.md deleted file mode 100644 index 840bd7c..0000000 --- a/examples/cdi-produces-disposes/README.md +++ /dev/null @@ -1,276 +0,0 @@ -index-group=CDI -type=page -status=published -title=CDI Produces Disposes -~~~~~~ - - -This example shows how the @Produces and @Disposes annotations work. A LogFactory creates an instance of the LogHandler -depending on a "type" attribute. For the purposes of this example, the type is hard-coded to a specific value. -A Logger implementation shall contain a list of LogHandlers. We shall have three implementations of the LogHandler interface. - - * A DatabaseHandler - * A FileHandler - * A ConsoleHandler - -The DatabaseHandler would seemingly write the logs to a database. The FileHandler would write the same logs to a file. -The ConsoleHandler would just print the logs to a console (Standard out). This example is just an illustration of how -the concepts within CDI work and is not intended to provide a logging framework design/implementation. - -*Help us finish documenting this example! Click the blue pencil icon in the upper right to edit this page.* - -## ConsoleHandler - - package org.superbiz.cdi.produces.disposes; - - public class ConsoleHandler implements LogHandler { - - private String name; - - public ConsoleHandler(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public void writeLog(String s) { - System.out.printf("##### Handler: %s, Writing to the console!\n", getName()); - } - } - -## DatabaseHandler - - package org.superbiz.cdi.produces.disposes; - - public class DatabaseHandler implements LogHandler { - - private String name; - - public DatabaseHandler(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public void writeLog(String s) { - System.out.printf("##### Handler: %s, Writing to the database!\n", getName()); - // Use connection to write log to database - } - } - -## FileHandler - - package org.superbiz.cdi.produces.disposes; - - public class FileHandler implements LogHandler { - - private String name; - - public FileHandler(String name) { - this.name = name; - } - - @Override - public String getName() { - return name; - } - - @Override - public void writeLog(String s) { - System.out.printf("##### Handler: %s, Writing to the file!\n", getName()); - // Write to log file - } - } - -## LogFactory - - package org.superbiz.cdi.produces.disposes; - - import javax.enterprise.inject.Disposes; - import javax.enterprise.inject.Produces; - - public class LogFactory { - - private int type = 2; - - @Produces - public LogHandler getLogHandler() { - switch (type) { - case 1: - return new FileHandler("@Produces created FileHandler!"); - case 2: - return new DatabaseHandler("@Produces created DatabaseHandler!"); - case 3: - default: - return new ConsoleHandler("@Produces created ConsoleHandler!"); - } - } - - public void closeLogHandler(@Disposes LogHandler handler) { - switch (type) { - case 1: - System.out.println("Closing File handler!"); - break; - case 2: - System.out.println("Closing DB handler!"); - break; - case 3: - default: - System.out.println("Closing Console handler!"); - } - } - } - -## Logger - - package org.superbiz.cdi.produces.disposes; - - public interface Logger { - - public void log(String s); - - public LogHandler getHandler(); - } - -## LoggerImpl - - package org.superbiz.cdi.produces.disposes; - - import javax.inject.Inject; - import javax.inject.Named; - - @Named("logger") - public class LoggerImpl implements Logger { - - @Inject - private LogHandler handler; - - @Override - public void log(String s) { - getHandler().writeLog(s); - } - - public LogHandler getHandler() { - return handler; - } - } - -## LogHandler - - package org.superbiz.cdi.produces.disposes; - - public interface LogHandler { - - public String getName(); - - public void writeLog(String s); - } - -## beans.xml - - <beans 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/beans_1_0.xsd"> - - </beans> - -## LoggerTest - - package org.superbiz.cdi.produces.disposes; - - import org.junit.After; - import org.junit.Before; - import org.junit.Test; - - import javax.ejb.embeddable.EJBContainer; - import javax.inject.Inject; - import javax.naming.Context; - - import static junit.framework.Assert.assertNotNull; - import static org.junit.Assert.assertFalse; - import static org.junit.Assert.assertTrue; - - public class LoggerTest { - - @Inject - Logger logger; - - private Context ctxt; - - @Before - public void setUp() { - try { - ctxt = EJBContainer.createEJBContainer().getContext(); - ctxt.bind("inject", this); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @After - public void cleanUp() { - try { - ctxt.unbind("inject"); - ctxt.close(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - @Test - public void testLogHandler() { - assertNotNull(logger); - assertFalse("Handler should not be a ConsoleHandler", logger.getHandler() instanceof ConsoleHandler); - assertFalse("Handler should not be a FileHandler", logger.getHandler() instanceof FileHandler); - assertTrue("Handler should be a DatabaseHandler", logger.getHandler() instanceof DatabaseHandler); - logger.log("##### Testing write\n"); - logger = null; - } - - } - -# Running - - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.cdi.produces.disposes.LoggerTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/cdi-produces-disposes - INFO - openejb.base = /Users/dblevins/examples/cdi-produces-disposes - 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/cdi-produces-disposes/target/classes - INFO - Beginning load: /Users/dblevins/examples/cdi-produces-disposes/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/cdi-produces-disposes - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean cdi-produces-disposes.Comp: Container(type=MANAGED, id=Default Managed Container) - INFO - Enterprise application "/Users/dblevins/examples/cdi-produces-disposes" loaded. - INFO - Assembling app: /Users/dblevins/examples/cdi-produces-disposes - INFO - Jndi(name="java:global/cdi-produces-disposes/cdi-produces-disposes.Comp!org.apache.openejb.BeanContext$Comp") - INFO - Jndi(name="java:global/cdi-produces-disposes/cdi-produces-disposes.Comp") - INFO - Jndi(name="java:global/EjbModule10202458/org.superbiz.cdi.produces.disposes.LoggerTest!org.superbiz.cdi.produces.disposes.LoggerTest") - INFO - Jndi(name="java:global/EjbModule10202458/org.superbiz.cdi.produces.disposes.LoggerTest") - INFO - Created Ejb(deployment-id=cdi-produces-disposes.Comp, ejb-name=cdi-produces-disposes.Comp, container=Default Managed Container) - INFO - Created Ejb(deployment-id=org.superbiz.cdi.produces.disposes.LoggerTest, ejb-name=org.superbiz.cdi.produces.disposes.LoggerTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=cdi-produces-disposes.Comp, ejb-name=cdi-produces-disposes.Comp, container=Default Managed Container) - INFO - Started Ejb(deployment-id=org.superbiz.cdi.produces.disposes.LoggerTest, ejb-name=org.superbiz.cdi.produces.disposes.LoggerTest, container=Default Managed Container) - INFO - Deployed Application(path=/Users/dblevins/examples/cdi-produces-disposes) - ##### Handler: @Produces created DatabaseHandler!, Writing to the database! - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.02 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 -
