├── .gitignore ├── LICENSE ├── README.md ├── application.png ├── pom.xml └── src └── main ├── java └── cool │ └── javaee │ └── cdi │ └── events │ ├── EventViewBean.java │ ├── database │ └── MessageSaver.java │ └── observers │ ├── ImportantEventObserver.java │ ├── SimpleEventObserver.java │ ├── TransactionBoundMessageObserver.java │ ├── entities │ └── Message.java │ └── qualifiers │ ├── Important.java │ └── Transaction.java ├── resources └── META-INF │ └── persistence.xml └── webapp ├── WEB-INF ├── bootstrap.xhtml └── web.xml └── index.xhtml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | lib/ 3 | nb-configuration.xml 4 | nbactions.xml -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Pavel Pscheidl 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CDI Events Playground 2 | Sample project for [CDI Events overview](http://www.pavel.cool/javaee/cdi-events/) article. 3 | 4 | ## Running it 5 | 6 | 1. Git clone the repository 7 | 1. Run *Maven goal* `wildfly-swarm:run` 8 | 1. Visit http://localhost:8080/ in your browser 9 | 10 | **Done !** WildFly Swarm will scan the project and automatically download all the parts necessary to run the application. No interaction required. The download phase only occurs during the first run. During the process, an in-memory H2 database is started. 11 | 12 | ![test](application.png "test") 13 | 14 | ### Logging note 15 | The result of the events fired is visible in console. Standard output is used directly instead of a logger. 16 | -------------------------------------------------------------------------------- /application.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pscheidl/cdi-events-playground/b91458c0e7a2cb2da380757514097f8223024be8/application.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | cz.pscheidl.mythbusting.interceptor 6 | cdi-events-sample 7 | 1.0 8 | war 9 | 10 | cdi-events-sample 11 | 12 | 13 | 2017.5.0 14 | 1.8 15 | 1.8 16 | false 17 | UTF-8 18 | 19 | 20 | 21 | 22 | 23 | org.wildfly.swarm 24 | bom-all 25 | ${version.wildfly.swarm} 26 | import 27 | pom 28 | 29 | 30 | 31 | 32 | 33 | wildfly-swarm-rest-showcase 34 | 35 | 36 | org.wildfly.swarm 37 | wildfly-swarm-plugin 38 | ${version.wildfly.swarm} 39 | 40 | 41 | 42 | package 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | javax 53 | javaee-api 54 | 7.0 55 | provided 56 | 57 | 58 | com.h2database 59 | h2 60 | LATEST 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/EventViewBean.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events; 2 | 3 | import cool.javaee.cdi.events.database.MessageSaver; 4 | import cool.javaee.cdi.events.observers.qualifiers.Important; 5 | import java.io.Serializable; 6 | import javax.enterprise.context.RequestScoped; 7 | import javax.enterprise.event.Event; 8 | import javax.enterprise.util.AnnotationLiteral; 9 | import javax.inject.Inject; 10 | import javax.inject.Named; 11 | 12 | /** 13 | * 14 | * @author Pavel Pscheidl 15 | */ 16 | @Named 17 | @RequestScoped 18 | public class EventViewBean implements Serializable { 19 | 20 | @Inject 21 | private Event simpleMessageEvent; 22 | 23 | @Inject 24 | @Important 25 | private Event importantMessageEvent; 26 | 27 | @Inject 28 | private MessageSaver messageSaver; 29 | 30 | /** 31 | * Fires simple event with the message received from the website frontend. 32 | * Event listeners without any additional qualifiers will receive this 33 | * event. 34 | * 35 | * @param message Message to send 36 | */ 37 | public void sendSimpleMessage(String message) { 38 | simpleMessageEvent.fire(message); 39 | } 40 | 41 | /** 42 | * Fires simple event with the message received from the website frontend. 43 | * Event listeners without any additional qualifiers will receive this 44 | * event. 45 | * 46 | * @param messageMessage to send 47 | */ 48 | public void sendImportantMessage(String message) { 49 | importantMessageEvent.fire(message); 50 | 51 | } 52 | 53 | /** 54 | * Fires simple event with the message received from the website frontend. 55 | * Event listeners without any additional qualifiers will receive this 56 | * event. 57 | * 58 | * @param message Message to send 59 | */ 60 | public void sendImportantMessageAlternatively(String message) { 61 | simpleMessageEvent.select(new AnnotationLiteral() { 62 | }) 63 | .fire(message); 64 | 65 | } 66 | 67 | /** 68 | * Persists a message into database. Inside the saveMessageToDatabase 69 | * method, an event is fired. 70 | * 71 | * @param message Message to send 72 | */ 73 | public void sendMessageToTransactionEvent(String message) { 74 | messageSaver.saveMessageToDatabase(message); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/database/MessageSaver.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events.database; 2 | 3 | import cool.javaee.cdi.events.observers.entities.Message; 4 | import cool.javaee.cdi.events.observers.qualifiers.Transaction; 5 | import javax.ejb.Stateless; 6 | import javax.enterprise.event.Event; 7 | import javax.inject.Inject; 8 | import javax.persistence.EntityManager; 9 | import javax.persistence.PersistenceContext; 10 | 11 | /** 12 | * 13 | * @author Pavel Pscheidl 14 | */ 15 | @Stateless 16 | public class MessageSaver { 17 | 18 | @PersistenceContext 19 | private EntityManager em; 20 | 21 | @Inject 22 | @Transaction 23 | private Event transactionMessageEvent; 24 | 25 | /** 26 | * Persists message to database and fires an event with the message. The 27 | * receiver may decide whether to receive the event before or after the 28 | * transaction was ended and the message was persisted. 29 | * 30 | * @param message Message to persist 31 | */ 32 | public void saveMessageToDatabase(String message) { 33 | transactionMessageEvent.fire(message); 34 | System.out.println("Beginning persistence of message: " + message); 35 | em.persist(new Message(message)); 36 | System.out.println("Message persisted."); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/observers/ImportantEventObserver.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events.observers; 2 | 3 | import cool.javaee.cdi.events.observers.qualifiers.Important; 4 | import javax.enterprise.context.ApplicationScoped; 5 | import javax.enterprise.event.Observes; 6 | import javax.inject.Named; 7 | 8 | /** 9 | * A bean with a method listening only to important messages. 10 | * 11 | * @author Pavel Pscheidl 12 | */ 13 | @Named 14 | @ApplicationScoped 15 | public class ImportantEventObserver { 16 | 17 | /** 18 | * A method observing only events with important messages 19 | * 20 | * @param importantMessage Important message 21 | */ 22 | public void observeSecretMessage(@Observes @Important String importantMessage) { 23 | System.out.println("Important message received: " + importantMessage); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/observers/SimpleEventObserver.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events.observers; 2 | 3 | import javax.enterprise.context.ApplicationScoped; 4 | import javax.enterprise.event.Observes; 5 | import javax.inject.Named; 6 | 7 | /** 8 | * A class containing a method listening to all events of String type 9 | * 10 | * @author Pavel Pscheidl 11 | */ 12 | @Named 13 | @ApplicationScoped 14 | public class SimpleEventObserver { 15 | 16 | /** 17 | * Observes all events with String generic type. 18 | * 19 | * @param message Message from the event 20 | */ 21 | private void simplyObserve(@Observes String message) { 22 | System.out.println("Simply observed: " + message); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/observers/TransactionBoundMessageObserver.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events.observers; 2 | 3 | import cool.javaee.cdi.events.observers.qualifiers.Transaction; 4 | import javax.enterprise.context.ApplicationScoped; 5 | import javax.enterprise.event.Observes; 6 | import javax.enterprise.event.TransactionPhase; 7 | import javax.inject.Named; 8 | 9 | /** 10 | * Contains method that only listens to 11 | * 12 | * @author Pavel Pscheidl 13 | */ 14 | @Named 15 | @ApplicationScoped 16 | public class TransactionBoundMessageObserver { 17 | 18 | public void observeBeforeTransactionCompletion(@Observes(during = TransactionPhase.BEFORE_COMPLETION) @Transaction String message) { 19 | System.out.println("Message from within transaction received before completion: " + message); 20 | } 21 | 22 | public void observeAfterTransactionCompletion(@Observes(during = TransactionPhase.AFTER_SUCCESS) @Transaction String message) { 23 | System.out.println("Message from within transaction received after success: " + message); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/observers/entities/Message.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events.observers.entities; 2 | 3 | import java.io.Serializable; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.Id; 7 | 8 | /** 9 | * A database entity serves as a wrapper for the message to be persisted into 10 | * database. 11 | * 12 | * @author Pavel Pscheidl 13 | */ 14 | @Entity 15 | public class Message implements Serializable { 16 | 17 | public Message() { 18 | } 19 | 20 | public Message(String message) { 21 | this.message = message; 22 | } 23 | 24 | @Id 25 | @GeneratedValue 26 | private Long id; 27 | 28 | private String message; 29 | 30 | public Long getId() { 31 | return id; 32 | } 33 | 34 | public void setId(Long id) { 35 | this.id = id; 36 | } 37 | 38 | public String getEntity() { 39 | return message; 40 | } 41 | 42 | public void setEntity(String entity) { 43 | this.message = entity; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/observers/qualifiers/Important.java: -------------------------------------------------------------------------------- 1 | package cool.javaee.cdi.events.observers.qualifiers; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.ElementType.METHOD; 5 | import static java.lang.annotation.ElementType.PARAMETER; 6 | import static java.lang.annotation.ElementType.TYPE; 7 | import java.lang.annotation.Retention; 8 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 9 | import java.lang.annotation.Target; 10 | import javax.inject.Qualifier; 11 | 12 | /** 13 | * A qualifier for important messages. 14 | * 15 | * @author Pavel Pscheidl 16 | */ 17 | @Qualifier 18 | @Retention(RUNTIME) 19 | @Target({METHOD, FIELD, PARAMETER, TYPE}) 20 | public @interface Important { 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/cool/javaee/cdi/events/observers/qualifiers/Transaction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this license header, choose License Headers in Project Properties. 3 | * To change this template file, choose Tools | Templates 4 | * and open the template in the editor. 5 | */ 6 | package cool.javaee.cdi.events.observers.qualifiers; 7 | 8 | import static java.lang.annotation.ElementType.FIELD; 9 | import static java.lang.annotation.ElementType.METHOD; 10 | import static java.lang.annotation.ElementType.PARAMETER; 11 | import static java.lang.annotation.ElementType.TYPE; 12 | import java.lang.annotation.Retention; 13 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 14 | import java.lang.annotation.Target; 15 | import javax.inject.Qualifier; 16 | 17 | /** 18 | * A qualifier for messages fired during a transaction. 19 | * 20 | * @author Pavel Pscheidl 21 | */ 22 | @Qualifier 23 | @Retention(RUNTIME) 24 | @Target({METHOD, FIELD, PARAMETER, TYPE}) 25 | public @interface Transaction { 26 | } 27 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | java:/jboss/datasources/ExampleDS 5 | false 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/bootstrap.xhtml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | javax.faces.PROJECT_STAGE 5 | Development 6 | 7 | 8 | Faces Servlet 9 | javax.faces.webapp.FacesServlet 10 | 1 11 | 12 | 13 | Faces Servlet 14 | *.xhtml 15 | 16 | 17 | 18 | 30 19 | 20 | 21 | 22 | index.xhtml 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/webapp/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | Events playground 8 | 9 | 10 | 11 |
12 | 15 | 16 |
17 | 18 |
19 |
20 |
Simple message event
21 |
22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 | 30 | 31 |
32 |
33 |
Secret message event
34 |
35 | 36 | 37 | 38 | 39 |
40 |
41 |
42 | 43 |
44 | 45 |
46 |
47 |
Alternative qualifier selection
48 |
49 | 50 | 51 | 52 | 53 |
54 |
55 |
56 |
57 |
58 |
Transaction-bound event
59 |
60 | 61 | 62 | 63 | 64 |
65 |
66 |
67 | 68 | Event messages will appear in the console ... 69 |
70 |
71 | 72 | 73 | --------------------------------------------------------------------------------