From 56c51babac0fc0c2d363a3b2dbf82073e0b5ea7d Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:14:48 -0200 Subject: [PATCH 01/10] Transform cdi session scope readme to adoc. --- examples/cdi-session-scope/README.adoc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/cdi-session-scope/README.adoc b/examples/cdi-session-scope/README.adoc index e529424fc59..0994cc1d5f8 100644 --- a/examples/cdi-session-scope/README.adoc +++ b/examples/cdi-session-scope/README.adoc @@ -1,8 +1,7 @@ -index-group=Unrevised -type=page -status=unpublished - = CDI @SessionScoped +:index-group: CDI +:jbake-type: page +:jbake-status: published This example show the use of `@SessionScoped` annotation for injected objects. An object which is defined as `@SessionScoped` is created once for every HTTPSession and is shared by all the From 14f8e156b24dc5d4de1a860fd1123fcf919f5aef Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:18:33 -0200 Subject: [PATCH 02/10] dding adoc --- examples/schedule-events/README.adoc | 170 +++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 examples/schedule-events/README.adoc diff --git a/examples/schedule-events/README.adoc b/examples/schedule-events/README.adoc new file mode 100644 index 00000000000..08a5206e1e4 --- /dev/null +++ b/examples/schedule-events/README.adoc @@ -0,0 +1,170 @@ += Schedule CDI Events +:index-group: CDI +:jbake-type: page +:jbake-status: published + +This example uses a nice CDI/EJB combination to schedule CDI Events. This is useful if you want CDI Events that fire regularly or at a specific time or calendar date. + +Effectively this is a simple wrapper around the `+BeanManager.fireEvent(Object,Annotations...)+` method that adds `ScheduleExpression` into the mix. + +== ScheduleExpression and @Timeout + +The logic here is simple, we effecitvely expose a method identical to `+BeanManager.fireEvent(Object, Annotations...)+` and wrap it as `+scheduleEvent(ScheduleExpression, Object, Annotation...)+` + +To do that we use the EJB `TimerService` (under the covers this is Quartz) and create an `@Timeout` method which will be run when the `ScheduleExpression` activates. + +The `@Timeout` method, simply called `timeout`, takes the event and fires it. + +.... +@Singleton +@Lock(LockType.READ) +public class Scheduler { + + @Resource + private TimerService timerService; + + @Resource + private BeanManager beanManager; + + public void scheduleEvent(ScheduleExpression schedule, Object event, Annotation... qualifiers) { + + timerService.createCalendarTimer(schedule, new TimerConfig(new EventConfig(event, qualifiers), false)); + } + + @Timeout + private void timeout(Timer timer) { + final EventConfig config = (EventConfig) timer.getInfo(); + + beanManager.fireEvent(config.getEvent(), config.getQualifiers()); + } + + // Doesn't actually need to be serializable, just has to implement it + private final class EventConfig implements Serializable { + + private final Object event; + private final Annotation[] qualifiers; + + private EventConfig(Object event, Annotation[] qualifiers) { + this.event = event; + this.qualifiers = qualifiers; + } + + public Object getEvent() { + return event; + } + + public Annotation[] getQualifiers() { + return qualifiers; + } + } +} +.... + +Then to use it, have `Scheduler` injected as an EJB and enjoy. + +.... +public class SomeBean { + + @EJB + private Scheduler scheduler; + + public void doit() throws Exception { + + // every five minutes + final ScheduleExpression schedule = new ScheduleExpression() + .hour("*") + .minute("*") + .second("*/5"); + + scheduler.scheduleEvent(schedule, new TestEvent("five")); + } + + /** + * Event will fire every five minutes + */ + public void observe(@Observes TestEvent event) { + // process the event + } + +} +.... + +== Test Case + +A working test case for the above would be as follows: + +.... +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.ejb.AccessTimeout; +import javax.ejb.EJB; +import javax.ejb.ScheduleExpression; +import javax.ejb.embeddable.EJBContainer; +import javax.enterprise.event.Observes; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +/** + * @version $Revision$ $Date$ + */ +public class SchedulerTest { + + public static final CountDownLatch events = new CountDownLatch(3); + + @EJB + private Scheduler scheduler; + + @Test + public void test() throws Exception { + + final ScheduleExpression schedule = new ScheduleExpression() + .hour("*") + .minute("*") + .second("*/5"); + + scheduler.scheduleEvent(schedule, new TestEvent("five")); + + Assert.assertTrue(events.await(1, TimeUnit.MINUTES)); + } + + + @AccessTimeout(value = 1, unit = TimeUnit.MINUTES) + public void observe(@Observes TestEvent event) { + if ("five".equals(event.getMessage())) { + events.countDown(); + } + } + + public static class TestEvent { + private final String message; + + public TestEvent(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + } + + @Before + public void setup() throws Exception { + EJBContainer.createEJBContainer().getContext().bind("inject", this); + } +} +.... + +== You must know + +* CDI Events are not multi-treaded + +If there are 10 observers and each of them take 7 minutes to execute, then the total execution time for the one event is 70 minutes. It would do you absolutely no good to schedule that event to fire more frequently than 70 minutes. + +What would happen if you did? Depends on the `@Singleton` `@Lock` policy + +* `@Lock(WRITE)` is the default. In this mode the `timeout` method would essentially be locked until the previous invocation completes. Having it fire every 5 minutes even though you can only process one every 70 minutes would eventually cause all the pooled timer threads to be waiting on your Singleton. +* `@Lock(READ)` allows for parallel execution of the `timeout` method. Events will fire in parallel for a while. However since they actually are taking 70 minutes each, within an hour or so we'll run out of threads in the timer pool just like above. + +The elegant solution is to use `@Lock(WRITE)` then specify some short timeout like `@AccessTimeout(value = 1, unit = TimeUnit.MINUTES)` on the `timeout` method. When the next 5 minute invocation is triggered, it will wait up until 1 minute to get access to the Singleton before giving up. This will keep your timer pool from filling up with backed up jobs -- the "overflow" is simply discarded. From e9958ac2417fe6148c848838cd1374ba76e4c24f Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:19:06 -0200 Subject: [PATCH 03/10] Adding simple mdb adoc --- examples/simple-mdb/README.adoc | 219 ++++++++++++++++++++++++++++++++ examples/simple-mdb/README.md | 215 ------------------------------- 2 files changed, 219 insertions(+), 215 deletions(-) create mode 100644 examples/simple-mdb/README.adoc delete mode 100644 examples/simple-mdb/README.md diff --git a/examples/simple-mdb/README.adoc b/examples/simple-mdb/README.adoc new file mode 100644 index 00000000000..f0e5d353337 --- /dev/null +++ b/examples/simple-mdb/README.adoc @@ -0,0 +1,219 @@ += Simple MDB + +:index-group: JMS and MDBs +:jbake-type: page +:jbake-status: published + +Below is a fun app, a chat application that uses JMS. We create a message driven bean, by marking our class with `@MessageDriven`. A message driven bean has some similarities with a stateless session bean, in the part that it is pooled too. + +Well, lets tell our chat-app to listen for incoming messages. That we do by implementing `MessageListener` and overriding the `onMessage(Message message)`. + +Then this app "listens" for incoming messages, and the messages picked up are processed by `onMessage(Message message)` method. + +That finishes our message driven bean implementation. The "processing" part could be anything that fits your business-requirement. + +In this case, it is to respond to the user. The `respond` method shows how a Message can be sent. + +This sequence diagram shows how a message is sent. + +image::../../resources/mdb-flow.png[] + +== ChatBean + +.... +package org.superbiz.mdb; + +import javax.annotation.Resource; +import javax.ejb.MessageDriven; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +@MessageDriven +public class ChatBean implements MessageListener { + + @Resource + private ConnectionFactory connectionFactory; + + @Resource(name = "AnswerQueue") + private Queue answerQueue; + + public void onMessage(Message message) { + try { + + final TextMessage textMessage = (TextMessage) message; + final String question = textMessage.getText(); + + if ("Hello World!".equals(question)) { + + respond("Hello, Test Case!"); + } else if ("How are you?".equals(question)) { + + respond("I'm doing well."); + } else if ("Still spinning?".equals(question)) { + + respond("Once every day, as usual."); + } + } catch (JMSException e) { + throw new IllegalStateException(e); + } + } + + private void respond(String text) throws JMSException { + + Connection connection = null; + Session session = null; + + try { + connection = connectionFactory.createConnection(); + connection.start(); + + // Create a Session + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Create a MessageProducer from the Session to the Topic or Queue + MessageProducer producer = session.createProducer(answerQueue); + producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + + // Create a message + TextMessage message = session.createTextMessage(text); + + // Tell the producer to send the message + producer.send(message); + } finally { + // Clean up + if (session != null) session.close(); + if (connection != null) connection.close(); + } + } +} +.... + +== ChatBeanTest + +.... +package org.superbiz.mdb; + +import junit.framework.TestCase; + +import javax.annotation.Resource; +import javax.ejb.embeddable.EJBContainer; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +public class ChatBeanTest extends TestCase { + + @Resource + private ConnectionFactory connectionFactory; + + @Resource(name = "ChatBean") + private Queue questionQueue; + + @Resource(name = "AnswerQueue") + private Queue answerQueue; + + public void test() throws Exception { + EJBContainer.createEJBContainer().getContext().bind("inject", this); + + + final Connection connection = connectionFactory.createConnection(); + + connection.start(); + + final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + final MessageProducer questions = session.createProducer(questionQueue); + + final MessageConsumer answers = session.createConsumer(answerQueue); + + + sendText("Hello World!", questions, session); + + assertEquals("Hello, Test Case!", receiveText(answers)); + + + sendText("How are you?", questions, session); + + assertEquals("I'm doing well.", receiveText(answers)); + + + sendText("Still spinning?", questions, session); + + assertEquals("Once every day, as usual.", receiveText(answers)); + } + + private void sendText(String text, MessageProducer questions, Session session) throws JMSException { + + questions.send(session.createTextMessage(text)); + } + + private String receiveText(MessageConsumer answers) throws JMSException { + + return ((TextMessage) answers.receive(1000)).getText(); + } +} +.... + += Running + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.mdb.ChatBeanTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/simple-mdb +INFO - openejb.base = /Users/dblevins/examples/simple-mdb +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/simple-mdb/target/classes +INFO - Beginning load: /Users/dblevins/examples/simple-mdb/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/simple-mdb +WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime. +INFO - Auto-configuring a message driven bean ChatBean destination ChatBean to be destinationType javax.jms.Queue +INFO - Configuring Service(id=Default MDB Container, type=Container, provider-id=Default MDB Container) +INFO - Auto-creating a container for bean ChatBean: Container(type=MESSAGE, id=Default MDB Container) +INFO - Configuring Service(id=Default JMS Resource Adapter, type=Resource, provider-id=Default JMS Resource Adapter) +INFO - Configuring Service(id=Default JMS Connection Factory, type=Resource, provider-id=Default JMS Connection Factory) +INFO - Auto-creating a Resource with id 'Default JMS Connection Factory' of type 'javax.jms.ConnectionFactory for 'ChatBean'. +INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdb.ChatBean/connectionFactory' in bean ChatBean to Resource(id=Default JMS Connection Factory) +INFO - Configuring Service(id=AnswerQueue, type=Resource, provider-id=Default Queue) +INFO - Auto-creating a Resource with id 'AnswerQueue' of type 'javax.jms.Queue for 'ChatBean'. +INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean ChatBean to Resource(id=AnswerQueue) +INFO - Configuring Service(id=ChatBean, type=Resource, provider-id=Default Queue) +INFO - Auto-creating a Resource with id 'ChatBean' of type 'javax.jms.Queue for 'ChatBean'. +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean org.superbiz.mdb.ChatBeanTest: Container(type=MANAGED, id=Default Managed Container) +INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdb.ChatBeanTest/connectionFactory' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=Default JMS Connection Factory) +INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=AnswerQueue) +INFO - Auto-linking resource-env-ref 'java:comp/env/ChatBean' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=ChatBean) +INFO - Enterprise application "/Users/dblevins/examples/simple-mdb" loaded. +INFO - Assembling app: /Users/dblevins/examples/simple-mdb +INFO - Jndi(name="java:global/EjbModule1515710343/org.superbiz.mdb.ChatBeanTest!org.superbiz.mdb.ChatBeanTest") +INFO - Jndi(name="java:global/EjbModule1515710343/org.superbiz.mdb.ChatBeanTest") +INFO - Created Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) +INFO - Created Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) +INFO - Started Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) +INFO - Deployed Application(path=/Users/dblevins/examples/simple-mdb) +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.547 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... diff --git a/examples/simple-mdb/README.md b/examples/simple-mdb/README.md deleted file mode 100644 index 7c478d43187..00000000000 --- a/examples/simple-mdb/README.md +++ /dev/null @@ -1,215 +0,0 @@ -index-group=JMS and MDBs -type=page -status=published -title=Simple MDB -~~~~~~ - -Below is a fun app, a chat application that uses JMS. We create a message driven bean, by marking our class with `@MessageDriven`. A message driven bean has some similarities with a stateless session bean, in the part that it is pooled too. - -Well, lets tell our chat-app to listen for incoming messages. That we do by implementing `MessageListener` and overriding the `onMessage(Message message)`. - -Then this app "listens" for incoming messages, and the messages picked up are processed by `onMessage(Message message)` method. - -That finishes our message driven bean implementation. The "processing" part could be anything that fits your business-requirement. - -In this case, it is to respond to the user. The `respond` method shows how a Message can be sent. - -This sequence diagram shows how a message is sent. - - - -## ChatBean - - package org.superbiz.mdb; - - import javax.annotation.Resource; - import javax.ejb.MessageDriven; - import javax.jms.Connection; - import javax.jms.ConnectionFactory; - import javax.jms.DeliveryMode; - import javax.jms.JMSException; - import javax.jms.Message; - import javax.jms.MessageListener; - import javax.jms.MessageProducer; - import javax.jms.Queue; - import javax.jms.Session; - import javax.jms.TextMessage; - - @MessageDriven - public class ChatBean implements MessageListener { - - @Resource - private ConnectionFactory connectionFactory; - - @Resource(name = "AnswerQueue") - private Queue answerQueue; - - public void onMessage(Message message) { - try { - - final TextMessage textMessage = (TextMessage) message; - final String question = textMessage.getText(); - - if ("Hello World!".equals(question)) { - - respond("Hello, Test Case!"); - } else if ("How are you?".equals(question)) { - - respond("I'm doing well."); - } else if ("Still spinning?".equals(question)) { - - respond("Once every day, as usual."); - } - } catch (JMSException e) { - throw new IllegalStateException(e); - } - } - - private void respond(String text) throws JMSException { - - Connection connection = null; - Session session = null; - - try { - connection = connectionFactory.createConnection(); - connection.start(); - - // Create a Session - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - // Create a MessageProducer from the Session to the Topic or Queue - MessageProducer producer = session.createProducer(answerQueue); - producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - - // Create a message - TextMessage message = session.createTextMessage(text); - - // Tell the producer to send the message - producer.send(message); - } finally { - // Clean up - if (session != null) session.close(); - if (connection != null) connection.close(); - } - } - } - -## ChatBeanTest - - package org.superbiz.mdb; - - import junit.framework.TestCase; - - import javax.annotation.Resource; - import javax.ejb.embeddable.EJBContainer; - import javax.jms.Connection; - import javax.jms.ConnectionFactory; - import javax.jms.JMSException; - import javax.jms.MessageConsumer; - import javax.jms.MessageProducer; - import javax.jms.Queue; - import javax.jms.Session; - import javax.jms.TextMessage; - - public class ChatBeanTest extends TestCase { - - @Resource - private ConnectionFactory connectionFactory; - - @Resource(name = "ChatBean") - private Queue questionQueue; - - @Resource(name = "AnswerQueue") - private Queue answerQueue; - - public void test() throws Exception { - EJBContainer.createEJBContainer().getContext().bind("inject", this); - - - final Connection connection = connectionFactory.createConnection(); - - connection.start(); - - final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - final MessageProducer questions = session.createProducer(questionQueue); - - final MessageConsumer answers = session.createConsumer(answerQueue); - - - sendText("Hello World!", questions, session); - - assertEquals("Hello, Test Case!", receiveText(answers)); - - - sendText("How are you?", questions, session); - - assertEquals("I'm doing well.", receiveText(answers)); - - - sendText("Still spinning?", questions, session); - - assertEquals("Once every day, as usual.", receiveText(answers)); - } - - private void sendText(String text, MessageProducer questions, Session session) throws JMSException { - - questions.send(session.createTextMessage(text)); - } - - private String receiveText(MessageConsumer answers) throws JMSException { - - return ((TextMessage) answers.receive(1000)).getText(); - } - } - -# Running - - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.mdb.ChatBeanTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/simple-mdb - INFO - openejb.base = /Users/dblevins/examples/simple-mdb - 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/simple-mdb/target/classes - INFO - Beginning load: /Users/dblevins/examples/simple-mdb/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/simple-mdb - WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime. - INFO - Auto-configuring a message driven bean ChatBean destination ChatBean to be destinationType javax.jms.Queue - INFO - Configuring Service(id=Default MDB Container, type=Container, provider-id=Default MDB Container) - INFO - Auto-creating a container for bean ChatBean: Container(type=MESSAGE, id=Default MDB Container) - INFO - Configuring Service(id=Default JMS Resource Adapter, type=Resource, provider-id=Default JMS Resource Adapter) - INFO - Configuring Service(id=Default JMS Connection Factory, type=Resource, provider-id=Default JMS Connection Factory) - INFO - Auto-creating a Resource with id 'Default JMS Connection Factory' of type 'javax.jms.ConnectionFactory for 'ChatBean'. - INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdb.ChatBean/connectionFactory' in bean ChatBean to Resource(id=Default JMS Connection Factory) - INFO - Configuring Service(id=AnswerQueue, type=Resource, provider-id=Default Queue) - INFO - Auto-creating a Resource with id 'AnswerQueue' of type 'javax.jms.Queue for 'ChatBean'. - INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean ChatBean to Resource(id=AnswerQueue) - INFO - Configuring Service(id=ChatBean, type=Resource, provider-id=Default Queue) - INFO - Auto-creating a Resource with id 'ChatBean' of type 'javax.jms.Queue for 'ChatBean'. - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean org.superbiz.mdb.ChatBeanTest: Container(type=MANAGED, id=Default Managed Container) - INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdb.ChatBeanTest/connectionFactory' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=Default JMS Connection Factory) - INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=AnswerQueue) - INFO - Auto-linking resource-env-ref 'java:comp/env/ChatBean' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=ChatBean) - INFO - Enterprise application "/Users/dblevins/examples/simple-mdb" loaded. - INFO - Assembling app: /Users/dblevins/examples/simple-mdb - INFO - Jndi(name="java:global/EjbModule1515710343/org.superbiz.mdb.ChatBeanTest!org.superbiz.mdb.ChatBeanTest") - INFO - Jndi(name="java:global/EjbModule1515710343/org.superbiz.mdb.ChatBeanTest") - INFO - Created Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) - INFO - Created Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) - INFO - Started Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) - INFO - Deployed Application(path=/Users/dblevins/examples/simple-mdb) - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.547 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - From 2dbfc566aacfeab9d0b687b26e840978467c817e Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:19:24 -0200 Subject: [PATCH 04/10] removing old md doc --- examples/schedule-events/README.md | 166 ----------------------------- 1 file changed, 166 deletions(-) delete mode 100644 examples/schedule-events/README.md diff --git a/examples/schedule-events/README.md b/examples/schedule-events/README.md deleted file mode 100644 index 0b0e519d571..00000000000 --- a/examples/schedule-events/README.md +++ /dev/null @@ -1,166 +0,0 @@ -index-group=Unrevised -type=page -status=published -title=Schedule CDI Events -~~~~~~ - -This example uses a nice CDI/EJB combination to schedule CDI Events. This is useful if you want CDI Events that fire regularly or at a specific time or calendar date. - -Effectively this is a simple wrapper around the `BeanManager.fireEvent(Object,Annotations...)` method that adds `ScheduleExpression` into the mix. - -## ScheduleExpression and @Timeout - -The logic here is simple, we effecitvely expose a method identical to `BeanManager.fireEvent(Object, Annotations...)` and wrap it as `scheduleEvent(ScheduleExpression, Object, Annotation...)` - -To do that we use the EJB `TimerService` (under the covers this is Quartz) and create an `@Timeout` method which will be run when the `ScheduleExpression` activates. - -The `@Timeout` method, simply called `timeout`, takes the event and fires it. - - @Singleton - @Lock(LockType.READ) - public class Scheduler { - - @Resource - private TimerService timerService; - - @Resource - private BeanManager beanManager; - - public void scheduleEvent(ScheduleExpression schedule, Object event, Annotation... qualifiers) { - - timerService.createCalendarTimer(schedule, new TimerConfig(new EventConfig(event, qualifiers), false)); - } - - @Timeout - private void timeout(Timer timer) { - final EventConfig config = (EventConfig) timer.getInfo(); - - beanManager.fireEvent(config.getEvent(), config.getQualifiers()); - } - - // Doesn't actually need to be serializable, just has to implement it - private final class EventConfig implements Serializable { - - private final Object event; - private final Annotation[] qualifiers; - - private EventConfig(Object event, Annotation[] qualifiers) { - this.event = event; - this.qualifiers = qualifiers; - } - - public Object getEvent() { - return event; - } - - public Annotation[] getQualifiers() { - return qualifiers; - } - } - } - -Then to use it, have `Scheduler` injected as an EJB and enjoy. - - public class SomeBean { - - @EJB - private Scheduler scheduler; - - public void doit() throws Exception { - - // every five minutes - final ScheduleExpression schedule = new ScheduleExpression() - .hour("*") - .minute("*") - .second("*/5"); - - scheduler.scheduleEvent(schedule, new TestEvent("five")); - } - - /** - * Event will fire every five minutes - */ - public void observe(@Observes TestEvent event) { - // process the event - } - - } - -## Test Case - -A working test case for the above would be as follows: - - import org.junit.Assert; - import org.junit.Before; - import org.junit.Test; - - import javax.ejb.AccessTimeout; - import javax.ejb.EJB; - import javax.ejb.ScheduleExpression; - import javax.ejb.embeddable.EJBContainer; - import javax.enterprise.event.Observes; - import java.util.concurrent.CountDownLatch; - import java.util.concurrent.TimeUnit; - - /** - * @version $Revision$ $Date$ - */ - public class SchedulerTest { - - public static final CountDownLatch events = new CountDownLatch(3); - - @EJB - private Scheduler scheduler; - - @Test - public void test() throws Exception { - - final ScheduleExpression schedule = new ScheduleExpression() - .hour("*") - .minute("*") - .second("*/5"); - - scheduler.scheduleEvent(schedule, new TestEvent("five")); - - Assert.assertTrue(events.await(1, TimeUnit.MINUTES)); - } - - - @AccessTimeout(value = 1, unit = TimeUnit.MINUTES) - public void observe(@Observes TestEvent event) { - if ("five".equals(event.getMessage())) { - events.countDown(); - } - } - - public static class TestEvent { - private final String message; - - public TestEvent(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - } - - @Before - public void setup() throws Exception { - EJBContainer.createEJBContainer().getContext().bind("inject", this); - } - } - - -## You must know - - - CDI Events are not multi-treaded - -If there are 10 observers and each of them take 7 minutes to execute, then the total execution time for the one event is 70 minutes. It would do you absolutely no good to schedule that event to fire more frequently than 70 minutes. - -What would happen if you did? Depends on the `@Singleton` `@Lock` policy - - - `@Lock(WRITE)` is the default. In this mode the `timeout` method would essentially be locked until the previous invocation completes. Having it fire every 5 minutes even though you can only process one every 70 minutes would eventually cause all the pooled timer threads to be waiting on your Singleton. - - `@Lock(READ)` allows for parallel execution of the `timeout` method. Events will fire in parallel for a while. However since they actually are taking 70 minutes each, within an hour or so we'll run out of threads in the timer pool just like above. - -The elegant solution is to use `@Lock(WRITE)` then specify some short timeout like `@AccessTimeout(value = 1, unit = TimeUnit.MINUTES)` on the `timeout` method. When the next 5 minute invocation is triggered, it will wait up until 1 minute to get access to the Singleton before giving up. This will keep your timer pool from filling up with backed up jobs -- the "overflow" is simply discarded. From f8be746996a360fd1237626fec3bc597838d17f3 Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:25:05 -0200 Subject: [PATCH 05/10] converting simple mdb and cdi from md to adoc --- examples/simple-mdb-and-cdi/README.adoc | 195 ++++++++++++++++++++++++ examples/simple-mdb-and-cdi/README.md | 189 ----------------------- 2 files changed, 195 insertions(+), 189 deletions(-) create mode 100644 examples/simple-mdb-and-cdi/README.adoc delete mode 100644 examples/simple-mdb-and-cdi/README.md diff --git a/examples/simple-mdb-and-cdi/README.adoc b/examples/simple-mdb-and-cdi/README.adoc new file mode 100644 index 00000000000..c0e2c4590eb --- /dev/null +++ b/examples/simple-mdb-and-cdi/README.adoc @@ -0,0 +1,195 @@ += Simple MDB and CDI +:index-group: JMS and MDBs +:jbake-type: page +:jbake-status: published + +_Help us document this example! Click the blue pencil icon in the upper right to edit this page._ + +== ChatBean + +.... +package org.superbiz.mdb; + +import javax.annotation.Resource; +import javax.ejb.MessageDriven; +import javax.inject.Inject; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +@MessageDriven +public class ChatBean implements MessageListener { + + @Resource + private ConnectionFactory connectionFactory; + + @Resource(name = "AnswerQueue") + private Queue answerQueue; + + @Inject + private ChatRespondCreator responder; + + public void onMessage(Message message) { + try { + + final TextMessage textMessage = (TextMessage) message; + final String question = textMessage.getText(); + final String response = responder.respond(question); + + if (response != null) { + respond(response); + } + } catch (JMSException e) { + throw new IllegalStateException(e); + } + } + + private void respond(String text) throws JMSException { + + Connection connection = null; + Session session = null; + + try { + connection = connectionFactory.createConnection(); + connection.start(); + + // Create a Session + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Create a MessageProducer from the Session to the Topic or Queue + MessageProducer producer = session.createProducer(answerQueue); + producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + + // Create a message + TextMessage message = session.createTextMessage(text); + + // Tell the producer to send the message + producer.send(message); + } finally { + // Clean up + if (session != null) session.close(); + if (connection != null) connection.close(); + } + } +} +.... + +== ChatRespondCreator + +.... +package org.superbiz.mdb; + +public class ChatRespondCreator { + public String respond(String question) { + if ("Hello World!".equals(question)) { + return "Hello, Test Case!"; + } else if ("How are you?".equals(question)) { + return "I'm doing well."; + } else if ("Still spinning?".equals(question)) { + return "Once every day, as usual."; + } + return null; + } +} +.... + +== beans.xml + +.... + + + +.... + +== ChatBeanTest + +.... +package org.superbiz.mdb; + +import junit.framework.TestCase; + +import javax.annotation.Resource; +import javax.ejb.embeddable.EJBContainer; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +public class ChatBeanTest extends TestCase { + + @Resource + private ConnectionFactory connectionFactory; + + @Resource(name = "ChatBean") + private Queue questionQueue; + + @Resource(name = "AnswerQueue") + private Queue answerQueue; + + public void test() throws Exception { + EJBContainer.createEJBContainer().getContext().bind("inject", this); + + + final Connection connection = connectionFactory.createConnection(); + + connection.start(); + + final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + final MessageProducer questions = session.createProducer(questionQueue); + + final MessageConsumer answers = session.createConsumer(answerQueue); + + + sendText("Hello World!", questions, session); + + assertEquals("Hello, Test Case!", receiveText(answers)); + + + sendText("How are you?", questions, session); + + assertEquals("I'm doing well.", receiveText(answers)); + + + sendText("Still spinning?", questions, session); + + assertEquals("Once every day, as usual.", receiveText(answers)); + } + + private void sendText(String text, MessageProducer questions, Session session) throws JMSException { + + questions.send(session.createTextMessage(text)); + } + + private String receiveText(MessageConsumer answers) throws JMSException { + + return ((TextMessage) answers.receive(1000)).getText(); + } +} +.... diff --git a/examples/simple-mdb-and-cdi/README.md b/examples/simple-mdb-and-cdi/README.md deleted file mode 100644 index 68b9b25a64b..00000000000 --- a/examples/simple-mdb-and-cdi/README.md +++ /dev/null @@ -1,189 +0,0 @@ -index-group=Unrevised -type=page -status=published -title=Simple MDB and CDI -~~~~~~ - -*Help us document this example! Click the blue pencil icon in the upper right to edit this page.* - -## ChatBean - - package org.superbiz.mdb; - - import javax.annotation.Resource; - import javax.ejb.MessageDriven; - import javax.inject.Inject; - import javax.jms.Connection; - import javax.jms.ConnectionFactory; - import javax.jms.DeliveryMode; - import javax.jms.JMSException; - import javax.jms.Message; - import javax.jms.MessageListener; - import javax.jms.MessageProducer; - import javax.jms.Queue; - import javax.jms.Session; - import javax.jms.TextMessage; - - @MessageDriven - public class ChatBean implements MessageListener { - - @Resource - private ConnectionFactory connectionFactory; - - @Resource(name = "AnswerQueue") - private Queue answerQueue; - - @Inject - private ChatRespondCreator responder; - - public void onMessage(Message message) { - try { - - final TextMessage textMessage = (TextMessage) message; - final String question = textMessage.getText(); - final String response = responder.respond(question); - - if (response != null) { - respond(response); - } - } catch (JMSException e) { - throw new IllegalStateException(e); - } - } - - private void respond(String text) throws JMSException { - - Connection connection = null; - Session session = null; - - try { - connection = connectionFactory.createConnection(); - connection.start(); - - // Create a Session - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - // Create a MessageProducer from the Session to the Topic or Queue - MessageProducer producer = session.createProducer(answerQueue); - producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - - // Create a message - TextMessage message = session.createTextMessage(text); - - // Tell the producer to send the message - producer.send(message); - } finally { - // Clean up - if (session != null) session.close(); - if (connection != null) connection.close(); - } - } - } - -## ChatRespondCreator - - package org.superbiz.mdb; - - public class ChatRespondCreator { - public String respond(String question) { - if ("Hello World!".equals(question)) { - return "Hello, Test Case!"; - } else if ("How are you?".equals(question)) { - return "I'm doing well."; - } else if ("Still spinning?".equals(question)) { - return "Once every day, as usual."; - } - return null; - } - } - -## beans.xml - - - - - - -## ChatBeanTest - - package org.superbiz.mdb; - - import junit.framework.TestCase; - - import javax.annotation.Resource; - import javax.ejb.embeddable.EJBContainer; - import javax.jms.Connection; - import javax.jms.ConnectionFactory; - import javax.jms.JMSException; - import javax.jms.MessageConsumer; - import javax.jms.MessageProducer; - import javax.jms.Queue; - import javax.jms.Session; - import javax.jms.TextMessage; - - public class ChatBeanTest extends TestCase { - - @Resource - private ConnectionFactory connectionFactory; - - @Resource(name = "ChatBean") - private Queue questionQueue; - - @Resource(name = "AnswerQueue") - private Queue answerQueue; - - public void test() throws Exception { - EJBContainer.createEJBContainer().getContext().bind("inject", this); - - - final Connection connection = connectionFactory.createConnection(); - - connection.start(); - - final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - final MessageProducer questions = session.createProducer(questionQueue); - - final MessageConsumer answers = session.createConsumer(answerQueue); - - - sendText("Hello World!", questions, session); - - assertEquals("Hello, Test Case!", receiveText(answers)); - - - sendText("How are you?", questions, session); - - assertEquals("I'm doing well.", receiveText(answers)); - - - sendText("Still spinning?", questions, session); - - assertEquals("Once every day, as usual.", receiveText(answers)); - } - - private void sendText(String text, MessageProducer questions, Session session) throws JMSException { - - questions.send(session.createTextMessage(text)); - } - - private String receiveText(MessageConsumer answers) throws JMSException { - - return ((TextMessage) answers.receive(1000)).getText(); - } - } From 36b7a1ef5d0f9e77514e6b2de818c5ed6c276d96 Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:32:02 -0200 Subject: [PATCH 06/10] converting simple mdb with descriptor from md to adoc --- .../simple-mdb-with-descriptor/README.adoc | 249 ++++++++++++++++++ examples/simple-mdb-with-descriptor/README.md | 245 ----------------- 2 files changed, 249 insertions(+), 245 deletions(-) create mode 100644 examples/simple-mdb-with-descriptor/README.adoc delete mode 100644 examples/simple-mdb-with-descriptor/README.md diff --git a/examples/simple-mdb-with-descriptor/README.adoc b/examples/simple-mdb-with-descriptor/README.adoc new file mode 100644 index 00000000000..0c5ccc52ebe --- /dev/null +++ b/examples/simple-mdb-with-descriptor/README.adoc @@ -0,0 +1,249 @@ += Simple MDB with Descriptor +:index-group: JMS and MDBs +:jbake-type: page +:jbake-status: published + +_Help us document this example! Click the blue pencil icon in the upper right to edit this page._ + +== ChatBean + +.... +package org.superbiz.mdbdesc; + +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +public class ChatBean implements MessageListener { + + private ConnectionFactory connectionFactory; + + private Queue answerQueue; + + public void onMessage(Message message) { + try { + + final TextMessage textMessage = (TextMessage) message; + final String question = textMessage.getText(); + + if ("Hello World!".equals(question)) { + + respond("Hello, Test Case!"); + } else if ("How are you?".equals(question)) { + + respond("I'm doing well."); + } else if ("Still spinning?".equals(question)) { + + respond("Once every day, as usual."); + } + } catch (JMSException e) { + throw new IllegalStateException(e); + } + } + + private void respond(String text) throws JMSException { + + Connection connection = null; + Session session = null; + + try { + connection = connectionFactory.createConnection(); + connection.start(); + + // Create a Session + session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + // Create a MessageProducer from the Session to the Topic or Queue + MessageProducer producer = session.createProducer(answerQueue); + producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); + + // Create a message + TextMessage message = session.createTextMessage(text); + + // Tell the producer to send the message + producer.send(message); + } finally { + // Clean up + if (session != null) session.close(); + if (connection != null) connection.close(); + } + } +} +.... + +== ejb-jar.xml + +.... + + + + + + ChatBean + org.superbiz.mdbdesc.ChatBean + + javax.jms.MessageListener + + + + destination + ChatBean + + + destinationType + javax.jms.Queue + + + + + java:comp/env/org.superbiz.mdbdesc.ChatBean/connectionFactory + javax.jms.ConnectionFactory + + org.superbiz.mdbdesc.ChatBean + connectionFactory + + + + + java:comp/env/AnswerQueue + javax.jms.Queue + AnswerQueue + + org.superbiz.mdbdesc.ChatBean + answerQueue + + + + + + + +.... + +== ChatBeanTest + +.... +package org.superbiz.mdb; + +import junit.framework.TestCase; + +import javax.annotation.Resource; +import javax.ejb.embeddable.EJBContainer; +import javax.jms.Connection; +import javax.jms.ConnectionFactory; +import javax.jms.JMSException; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +public class ChatBeanTest extends TestCase { + + @Resource + private ConnectionFactory connectionFactory; + + @Resource(name = "ChatBean") + private Queue questionQueue; + + @Resource(name = "AnswerQueue") + private Queue answerQueue; + + public void test() throws Exception { + + EJBContainer.createEJBContainer().getContext().bind("inject", this); + + final Connection connection = connectionFactory.createConnection(); + + connection.start(); + + final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + final MessageProducer questions = session.createProducer(questionQueue); + + final MessageConsumer answers = session.createConsumer(answerQueue); + + + sendText("Hello World!", questions, session); + + assertEquals("Hello, Test Case!", receiveText(answers)); + + + sendText("How are you?", questions, session); + + assertEquals("I'm doing well.", receiveText(answers)); + + + sendText("Still spinning?", questions, session); + + assertEquals("Once every day, as usual.", receiveText(answers)); + } + + private void sendText(String text, MessageProducer questions, Session session) throws JMSException { + + questions.send(session.createTextMessage(text)); + } + + private String receiveText(MessageConsumer answers) throws JMSException { + + return ((TextMessage) answers.receive(1000)).getText(); + } +} +.... + += Running + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.mdb.ChatBeanTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/simple-mdb-with-descriptor +INFO - openejb.base = /Users/dblevins/examples/simple-mdb-with-descriptor +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/simple-mdb-with-descriptor/target/classes +INFO - Beginning load: /Users/dblevins/examples/simple-mdb-with-descriptor/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/simple-mdb-with-descriptor +WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime. +INFO - Configuring Service(id=Default MDB Container, type=Container, provider-id=Default MDB Container) +INFO - Auto-creating a container for bean ChatBean: Container(type=MESSAGE, id=Default MDB Container) +INFO - Configuring Service(id=Default JMS Resource Adapter, type=Resource, provider-id=Default JMS Resource Adapter) +INFO - Configuring Service(id=Default JMS Connection Factory, type=Resource, provider-id=Default JMS Connection Factory) +INFO - Auto-creating a Resource with id 'Default JMS Connection Factory' of type 'javax.jms.ConnectionFactory for 'ChatBean'. +INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdbdesc.ChatBean/connectionFactory' in bean ChatBean to Resource(id=Default JMS Connection Factory) +INFO - Configuring Service(id=AnswerQueue, type=Resource, provider-id=Default Queue) +INFO - Auto-creating a Resource with id 'AnswerQueue' of type 'javax.jms.Queue for 'ChatBean'. +INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean ChatBean to Resource(id=AnswerQueue) +INFO - Configuring Service(id=ChatBean, type=Resource, provider-id=Default Queue) +INFO - Auto-creating a Resource with id 'ChatBean' of type 'javax.jms.Queue for 'ChatBean'. +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean org.superbiz.mdb.ChatBeanTest: Container(type=MANAGED, id=Default Managed Container) +INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdb.ChatBeanTest/connectionFactory' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=Default JMS Connection Factory) +INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=AnswerQueue) +INFO - Auto-linking resource-env-ref 'java:comp/env/ChatBean' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=ChatBean) +INFO - Enterprise application "/Users/dblevins/examples/simple-mdb-with-descriptor" loaded. +INFO - Assembling app: /Users/dblevins/examples/simple-mdb-with-descriptor +INFO - Jndi(name="java:global/EjbModule1842275169/org.superbiz.mdb.ChatBeanTest!org.superbiz.mdb.ChatBeanTest") +INFO - Jndi(name="java:global/EjbModule1842275169/org.superbiz.mdb.ChatBeanTest") +INFO - Created Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) +INFO - Created Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) +INFO - Started Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) +INFO - Deployed Application(path=/Users/dblevins/examples/simple-mdb-with-descriptor) +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.914 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... diff --git a/examples/simple-mdb-with-descriptor/README.md b/examples/simple-mdb-with-descriptor/README.md deleted file mode 100644 index 3b248ed09df..00000000000 --- a/examples/simple-mdb-with-descriptor/README.md +++ /dev/null @@ -1,245 +0,0 @@ -index-group=JMS and MDBs -type=page -status=published -title=Simple MDB with Descriptor -~~~~~~ - -*Help us document this example! Click the blue pencil icon in the upper right to edit this page.* - -## ChatBean - - package org.superbiz.mdbdesc; - - import javax.jms.Connection; - import javax.jms.ConnectionFactory; - import javax.jms.DeliveryMode; - import javax.jms.JMSException; - import javax.jms.Message; - import javax.jms.MessageListener; - import javax.jms.MessageProducer; - import javax.jms.Queue; - import javax.jms.Session; - import javax.jms.TextMessage; - - public class ChatBean implements MessageListener { - - private ConnectionFactory connectionFactory; - - private Queue answerQueue; - - public void onMessage(Message message) { - try { - - final TextMessage textMessage = (TextMessage) message; - final String question = textMessage.getText(); - - if ("Hello World!".equals(question)) { - - respond("Hello, Test Case!"); - } else if ("How are you?".equals(question)) { - - respond("I'm doing well."); - } else if ("Still spinning?".equals(question)) { - - respond("Once every day, as usual."); - } - } catch (JMSException e) { - throw new IllegalStateException(e); - } - } - - private void respond(String text) throws JMSException { - - Connection connection = null; - Session session = null; - - try { - connection = connectionFactory.createConnection(); - connection.start(); - - // Create a Session - session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - // Create a MessageProducer from the Session to the Topic or Queue - MessageProducer producer = session.createProducer(answerQueue); - producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT); - - // Create a message - TextMessage message = session.createTextMessage(text); - - // Tell the producer to send the message - producer.send(message); - } finally { - // Clean up - if (session != null) session.close(); - if (connection != null) connection.close(); - } - } - } - -## ejb-jar.xml - - - - - - - ChatBean - org.superbiz.mdbdesc.ChatBean - - javax.jms.MessageListener - - - - destination - ChatBean - - - destinationType - javax.jms.Queue - - - - - java:comp/env/org.superbiz.mdbdesc.ChatBean/connectionFactory - javax.jms.ConnectionFactory - - org.superbiz.mdbdesc.ChatBean - connectionFactory - - - - - java:comp/env/AnswerQueue - javax.jms.Queue - AnswerQueue - - org.superbiz.mdbdesc.ChatBean - answerQueue - - - - - - - - - -## ChatBeanTest - - package org.superbiz.mdb; - - import junit.framework.TestCase; - - import javax.annotation.Resource; - import javax.ejb.embeddable.EJBContainer; - import javax.jms.Connection; - import javax.jms.ConnectionFactory; - import javax.jms.JMSException; - import javax.jms.MessageConsumer; - import javax.jms.MessageProducer; - import javax.jms.Queue; - import javax.jms.Session; - import javax.jms.TextMessage; - - public class ChatBeanTest extends TestCase { - - @Resource - private ConnectionFactory connectionFactory; - - @Resource(name = "ChatBean") - private Queue questionQueue; - - @Resource(name = "AnswerQueue") - private Queue answerQueue; - - public void test() throws Exception { - - EJBContainer.createEJBContainer().getContext().bind("inject", this); - - final Connection connection = connectionFactory.createConnection(); - - connection.start(); - - final Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - - final MessageProducer questions = session.createProducer(questionQueue); - - final MessageConsumer answers = session.createConsumer(answerQueue); - - - sendText("Hello World!", questions, session); - - assertEquals("Hello, Test Case!", receiveText(answers)); - - - sendText("How are you?", questions, session); - - assertEquals("I'm doing well.", receiveText(answers)); - - - sendText("Still spinning?", questions, session); - - assertEquals("Once every day, as usual.", receiveText(answers)); - } - - private void sendText(String text, MessageProducer questions, Session session) throws JMSException { - - questions.send(session.createTextMessage(text)); - } - - private String receiveText(MessageConsumer answers) throws JMSException { - - return ((TextMessage) answers.receive(1000)).getText(); - } - } - -# Running - - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.mdb.ChatBeanTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/simple-mdb-with-descriptor - INFO - openejb.base = /Users/dblevins/examples/simple-mdb-with-descriptor - 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/simple-mdb-with-descriptor/target/classes - INFO - Beginning load: /Users/dblevins/examples/simple-mdb-with-descriptor/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/simple-mdb-with-descriptor - WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime. - INFO - Configuring Service(id=Default MDB Container, type=Container, provider-id=Default MDB Container) - INFO - Auto-creating a container for bean ChatBean: Container(type=MESSAGE, id=Default MDB Container) - INFO - Configuring Service(id=Default JMS Resource Adapter, type=Resource, provider-id=Default JMS Resource Adapter) - INFO - Configuring Service(id=Default JMS Connection Factory, type=Resource, provider-id=Default JMS Connection Factory) - INFO - Auto-creating a Resource with id 'Default JMS Connection Factory' of type 'javax.jms.ConnectionFactory for 'ChatBean'. - INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdbdesc.ChatBean/connectionFactory' in bean ChatBean to Resource(id=Default JMS Connection Factory) - INFO - Configuring Service(id=AnswerQueue, type=Resource, provider-id=Default Queue) - INFO - Auto-creating a Resource with id 'AnswerQueue' of type 'javax.jms.Queue for 'ChatBean'. - INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean ChatBean to Resource(id=AnswerQueue) - INFO - Configuring Service(id=ChatBean, type=Resource, provider-id=Default Queue) - INFO - Auto-creating a Resource with id 'ChatBean' of type 'javax.jms.Queue for 'ChatBean'. - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean org.superbiz.mdb.ChatBeanTest: Container(type=MANAGED, id=Default Managed Container) - INFO - Auto-linking resource-ref 'java:comp/env/org.superbiz.mdb.ChatBeanTest/connectionFactory' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=Default JMS Connection Factory) - INFO - Auto-linking resource-env-ref 'java:comp/env/AnswerQueue' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=AnswerQueue) - INFO - Auto-linking resource-env-ref 'java:comp/env/ChatBean' in bean org.superbiz.mdb.ChatBeanTest to Resource(id=ChatBean) - INFO - Enterprise application "/Users/dblevins/examples/simple-mdb-with-descriptor" loaded. - INFO - Assembling app: /Users/dblevins/examples/simple-mdb-with-descriptor - INFO - Jndi(name="java:global/EjbModule1842275169/org.superbiz.mdb.ChatBeanTest!org.superbiz.mdb.ChatBeanTest") - INFO - Jndi(name="java:global/EjbModule1842275169/org.superbiz.mdb.ChatBeanTest") - INFO - Created Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) - INFO - Created Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) - INFO - Started Ejb(deployment-id=org.superbiz.mdb.ChatBeanTest, ejb-name=org.superbiz.mdb.ChatBeanTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=ChatBean, ejb-name=ChatBean, container=Default MDB Container) - INFO - Deployed Application(path=/Users/dblevins/examples/simple-mdb-with-descriptor) - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.914 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - From a68903e7af00d9615d0d0b828cc95064bafabe72 Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 12:49:41 -0200 Subject: [PATCH 07/10] converting and fixing group of jpa examples --- .../injection-of-entitymanager/README.adoc | 229 ++++++++++++++ examples/injection-of-entitymanager/README.md | 221 -------------- examples/jpa-eclipselink/README.adoc | 215 +++++++++++++ examples/jpa-eclipselink/README.md | 211 ------------- examples/jpa-enumerated/README.adoc | 259 ++++++++++++++++ examples/jpa-enumerated/README.md | 252 --------------- examples/jpa-hibernate/README.adoc | 213 +++++++++++++ examples/jpa-hibernate/README.md | 209 ------------- .../multi-jpa-provider-testing/README.adoc | 287 ++++++++++++++++++ .../simple-remote-tomcatusers/README.adoc | 210 ++++++------- 10 files changed, 1308 insertions(+), 998 deletions(-) create mode 100644 examples/injection-of-entitymanager/README.adoc delete mode 100644 examples/injection-of-entitymanager/README.md create mode 100644 examples/jpa-eclipselink/README.adoc delete mode 100644 examples/jpa-eclipselink/README.md create mode 100644 examples/jpa-enumerated/README.adoc delete mode 100644 examples/jpa-enumerated/README.md create mode 100644 examples/jpa-hibernate/README.adoc delete mode 100644 examples/jpa-hibernate/README.md create mode 100644 examples/multi-jpa-provider-testing/README.adoc diff --git a/examples/injection-of-entitymanager/README.adoc b/examples/injection-of-entitymanager/README.adoc new file mode 100644 index 00000000000..821b1f5bb33 --- /dev/null +++ b/examples/injection-of-entitymanager/README.adoc @@ -0,0 +1,229 @@ += Injection Of Entitymanager +:index-group: JPA +:jbake-type: page +:jbake-status: published + +This example shows use of `@PersistenceContext` to have an `EntityManager` with an +`EXTENDED` persistence context injected into a `@Stateful bean`. A JPA +`@Entity` bean is used with the `EntityManager` to create, persist and merge +data to a database. + +== Creating the JPA Entity + +The entity itself is simply a pojo annotated with `@Entity`. We create one called `Movie` which we can use to hold movie records. + +.... +package org.superbiz.injection.jpa; + +import javax.persistence.Entity; + +@Entity +public class Movie { + + @Id @GeneratedValue + private long id; + + private String director; + private String title; + private int year; + + public Movie() { + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Movie(String director, String title, int year) { + this.director = director; + this.title = title; + this.year = year; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } +} +.... + +== Configure the EntityManager via a persistence.xml file + +The above `Movie` entity can be created, removed, updated or deleted via an `EntityManager` object. The `EntityManager` itself is +configured via a `META-INF/persistence.xml` file that is placed in the same jar as the `Movie` entity. + +.... + + + + movieDatabase + movieDatabaseUnmanaged + org.superbiz.injection.jpa.Movie + + + + + + +.... + +Notice that the `Movie` entity is listed via a `` element. This is not required, but can help when testing or when the +`Movie` class is located in a different jar than the jar containing the `persistence.xml` file. + +== Injection via @PersistenceContext + +The `EntityManager` itself is created by the container using the information in the `persistence.xml`, so to use it at +runtime, we simply need to request it be injected into one of our components. We do this via `@PersistenceContext` + +The `@PersistenceContext` annotation can be used on any CDI bean, EJB, Servlet, Servlet Listener, Servlet Filter, or JSF ManagedBean. If you don't use an EJB you will need to use a `UserTransaction` begin and commit transactions manually. A transaction is required for any of the create, update or delete methods of the EntityManager to work. + +.... +package org.superbiz.injection.jpa; + +import javax.ejb.Stateful; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceContextType; +import javax.persistence.Query; +import java.util.List; + +@Stateful +public class Movies { + + @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) + private EntityManager entityManager; + + public void addMovie(Movie movie) throws Exception { + entityManager.persist(movie); + } + + public void deleteMovie(Movie movie) throws Exception { + entityManager.remove(movie); + } + + public List getMovies() throws Exception { + Query query = entityManager.createQuery("SELECT m from Movie as m"); + return query.getResultList(); + } +} +.... + +This particular `EntityManager` is injected as an `EXTENDED` persistence context, which simply means that the `EntityManager` +is created when the `@Stateful` bean is created and destroyed when the `@Stateful` bean is destroyed. Simply put, the +data in the `EntityManager` is cached for the lifetime of the `@Stateful` bean. + +The use of `EXTENDED` persistence contexts is *only* available to `@Stateful` beans. See the link:../../jpa-concepts.html[JPA Concepts] page for an high level explanation of what a "persistence context" really is and how it is significant to JPA. + +== MoviesTest + +Testing JPA is quite easy, we can simply use the `EJBContainer` API to create a container in our test case. + +.... +package org.superbiz.injection.jpa; + +import junit.framework.TestCase; + +import javax.ejb.embeddable.EJBContainer; +import javax.naming.Context; +import java.util.List; +import java.util.Properties; + +//START SNIPPET: code +public class MoviesTest extends TestCase { + + public void test() throws Exception { + + final Properties p = new Properties(); + p.put("movieDatabase", "new://Resource?type=DataSource"); + p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); + p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); + + final Context context = EJBContainer.createEJBContainer(p).getContext(); + + Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies"); + + movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); + movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); + movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); + + List list = movies.getMovies(); + assertEquals("List.size()", 3, list.size()); + + for (Movie movie : list) { + movies.deleteMovie(movie); + } + + assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); + } +} +.... + += Running + +When we run our test case we should see output similar to the following. + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.injection.jpa.MoviesTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager +INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager +INFO - Using 'javax.ejb.embeddable.EJBContainer=true' +INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) +INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) +INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) +INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes +INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager +INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) +INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container) +INFO - Configuring PersistenceUnit(name=movie-unit) +INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. +INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) +INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' +INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded. +INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager +INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms +INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies") +INFO - Jndi(name="java:global/injection-of-entitymanager/Movies") +INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest") +INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest") +INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container) +INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager) +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... diff --git a/examples/injection-of-entitymanager/README.md b/examples/injection-of-entitymanager/README.md deleted file mode 100644 index 3200b5d0bb0..00000000000 --- a/examples/injection-of-entitymanager/README.md +++ /dev/null @@ -1,221 +0,0 @@ -index-group=EntityManagers -type=page -status=published -title=Injection Of Entitymanager -~~~~~~ - -This example shows use of `@PersistenceContext` to have an `EntityManager` with an -`EXTENDED` persistence context injected into a `@Stateful bean`. A JPA -`@Entity` bean is used with the `EntityManager` to create, persist and merge -data to a database. - -## Creating the JPA Entity - -The entity itself is simply a pojo annotated with `@Entity`. We create one called `Movie` which we can use to hold movie records. - - package org.superbiz.injection.jpa; - - import javax.persistence.Entity; - - @Entity - public class Movie { - - @Id @GeneratedValue - private long id; - - private String director; - private String title; - private int year; - - public Movie() { - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public Movie(String director, String title, int year) { - this.director = director; - this.title = title; - this.year = year; - } - - public String getDirector() { - return director; - } - - public void setDirector(String director) { - this.director = director; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } - } - -## Configure the EntityManager via a persistence.xml file - -The above `Movie` entity can be created, removed, updated or deleted via an `EntityManager` object. The `EntityManager` itself is -configured via a `META-INF/persistence.xml` file that is placed in the same jar as the `Movie` entity. - - - - - movieDatabase - movieDatabaseUnmanaged - org.superbiz.injection.jpa.Movie - - - - - - - -Notice that the `Movie` entity is listed via a `` element. This is not required, but can help when testing or when the -`Movie` class is located in a different jar than the jar containing the `persistence.xml` file. - -## Injection via @PersistenceContext - -The `EntityManager` itself is created by the container using the information in the `persistence.xml`, so to use it at -runtime, we simply need to request it be injected into one of our components. We do this via `@PersistenceContext` - -The `@PersistenceContext` annotation can be used on any CDI bean, EJB, Servlet, Servlet Listener, Servlet Filter, or JSF ManagedBean. If you don't use an EJB you will need to use a `UserTransaction` begin and commit transactions manually. A transaction is required for any of the create, update or delete methods of the EntityManager to work. - - package org.superbiz.injection.jpa; - - import javax.ejb.Stateful; - import javax.persistence.EntityManager; - import javax.persistence.PersistenceContext; - import javax.persistence.PersistenceContextType; - import javax.persistence.Query; - import java.util.List; - - @Stateful - public class Movies { - - @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) - private EntityManager entityManager; - - public void addMovie(Movie movie) throws Exception { - entityManager.persist(movie); - } - - public void deleteMovie(Movie movie) throws Exception { - entityManager.remove(movie); - } - - public List getMovies() throws Exception { - Query query = entityManager.createQuery("SELECT m from Movie as m"); - return query.getResultList(); - } - } - -This particular `EntityManager` is injected as an `EXTENDED` persistence context, which simply means that the `EntityManager` -is created when the `@Stateful` bean is created and destroyed when the `@Stateful` bean is destroyed. Simply put, the -data in the `EntityManager` is cached for the lifetime of the `@Stateful` bean. - -The use of `EXTENDED` persistence contexts is **only** available to `@Stateful` beans. See the [JPA Concepts](../../jpa-concepts.html) page for an high level explanation of what a "persistence context" really is and how it is significant to JPA. - -## MoviesTest - -Testing JPA is quite easy, we can simply use the `EJBContainer` API to create a container in our test case. - - package org.superbiz.injection.jpa; - - import junit.framework.TestCase; - - import javax.ejb.embeddable.EJBContainer; - import javax.naming.Context; - import java.util.List; - import java.util.Properties; - - //START SNIPPET: code - public class MoviesTest extends TestCase { - - public void test() throws Exception { - - final Properties p = new Properties(); - p.put("movieDatabase", "new://Resource?type=DataSource"); - p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); - p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); - - final Context context = EJBContainer.createEJBContainer(p).getContext(); - - Movies movies = (Movies) context.lookup("java:global/injection-of-entitymanager/Movies"); - - movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); - movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); - movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); - - List list = movies.getMovies(); - assertEquals("List.size()", 3, list.size()); - - for (Movie movie : list) { - movies.deleteMovie(movie); - } - - assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); - } - } - -# Running - -When we run our test case we should see output similar to the following. - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.injection.jpa.MoviesTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/injection-of-entitymanager - INFO - openejb.base = /Users/dblevins/examples/injection-of-entitymanager - INFO - Using 'javax.ejb.embeddable.EJBContainer=true' - INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) - INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) - INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) - INFO - Found EjbModule in classpath: /Users/dblevins/examples/injection-of-entitymanager/target/classes - INFO - Beginning load: /Users/dblevins/examples/injection-of-entitymanager/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/injection-of-entitymanager - INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) - INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean org.superbiz.injection.jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring PersistenceUnit(name=movie-unit) - INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. - INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) - INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' - INFO - Enterprise application "/Users/dblevins/examples/injection-of-entitymanager" loaded. - INFO - Assembling app: /Users/dblevins/examples/injection-of-entitymanager - INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 462ms - INFO - Jndi(name="java:global/injection-of-entitymanager/Movies!org.superbiz.injection.jpa.Movies") - INFO - Jndi(name="java:global/injection-of-entitymanager/Movies") - INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest!org.superbiz.injection.jpa.MoviesTest") - INFO - Jndi(name="java:global/EjbModule1461341140/org.superbiz.injection.jpa.MoviesTest") - INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Created Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Started Ejb(deployment-id=org.superbiz.injection.jpa.MoviesTest, ejb-name=org.superbiz.injection.jpa.MoviesTest, container=Default Managed Container) - INFO - Deployed Application(path=/Users/dblevins/examples/injection-of-entitymanager) - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.301 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - diff --git a/examples/jpa-eclipselink/README.adoc b/examples/jpa-eclipselink/README.adoc new file mode 100644 index 00000000000..0c628fc4aee --- /dev/null +++ b/examples/jpa-eclipselink/README.adoc @@ -0,0 +1,215 @@ += JPA Eclipselink +:index-group: JPA +:jbake-type: page +:jbake-status: published + +This example shows how to configure `persistence.xml` to work with Eclipselink. It uses an `@Entity` class and a `@Stateful` bean to add and delete entities from a database. + +== Creating the JPA Entity + +The entity itself is simply a pojo annotated with `@Entity`. We create one pojo called `Movie` which we can use to hold movie records. + +.... +package org.superbiz.eclipselink; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Movie { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String director; + private String title; + private int year; + + public Movie() { + } + + public Movie(String director, String title, int year) { + this.director = director; + this.title = title; + this.year = year; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + +} +.... + +== Database Operations + +This is the bean responsible for database operations; it allows us to persist or delete entities. +For more information we recommend you to see http://tomee.apache.org/examples-trunk/injection-of-entitymanager/README.html[injection-of-entitymanager] + +.... +package org.superbiz.eclipselink; + +import javax.ejb.Stateful; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceContextType; +import javax.persistence.Query; +import java.util.List; + +@Stateful +public class Movies { + + @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) + private EntityManager entityManager; + + public void addMovie(Movie movie) throws Exception { + entityManager.persist(movie); + } + + public void deleteMovie(Movie movie) throws Exception { + entityManager.remove(movie); + } + + public List getMovies() throws Exception { + Query query = entityManager.createQuery("SELECT m from Movie as m"); + return query.getResultList(); + } +} +.... + +== Persistence.xml with EclipseLink configuration + +This operation is too easy, just set the `provider` to `org.eclipse.persistence.jpa.PersistenceProvider` and add additional properties to the persistence unit. +The example has followed a strategy that allows the creation of tables in a HSQL database. +For a complete list of persistence unit properties see http://www.eclipse.org/eclipselink/api/2.4/org/eclipse/persistence/config/PersistenceUnitProperties.html[here] + + + + org.eclipse.persistence.jpa.PersistenceProvider + movieDatabase + movieDatabaseUnmanaged + + + + + + + + +== MoviesTest + +Testing JPA is quite easy, we can simply use the `EJBContainer` API to create a container in our test case. + +.... +package org.superbiz.eclipselink; + +import junit.framework.TestCase; + +import javax.ejb.embeddable.EJBContainer; +import javax.naming.Context; +import java.util.List; +import java.util.Properties; + +/** + * @version $Revision: 607077 $ $Date: 2007-12-27 06:55:23 -0800 (Thu, 27 Dec 2007) $ + */ +public class MoviesTest extends TestCase { + + public void test() throws Exception { + Properties p = new Properties(); + p.put("movieDatabase", "new://Resource?type=DataSource"); + p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); + p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); + + final Context context = EJBContainer.createEJBContainer(p).getContext(); + + Movies movies = (Movies) context.lookup("java:global/jpa-eclipselink/Movies"); + + movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); + movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); + movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); + + List list = movies.getMovies(); + assertEquals("List.size()", 3, list.size()); + + for (Movie movie : list) { + movies.deleteMovie(movie); + } + + assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); + } +} +.... + += Running + +When we run our test case we should see output similar to the following. + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.eclipselink.MoviesTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/jpa-eclipselink +INFO - openejb.base = /Users/dblevins/examples/jpa-eclipselink +INFO - Using 'javax.ejb.embeddable.EJBContainer=true' +INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) +INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) +INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) +INFO - Found EjbModule in classpath: /Users/dblevins/examples/jpa-eclipselink/target/classes +INFO - Beginning load: /Users/dblevins/examples/jpa-eclipselink/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/jpa-eclipselink +INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) +INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean org.superbiz.eclipselink.MoviesTest: Container(type=MANAGED, id=Default Managed Container) +INFO - Configuring PersistenceUnit(name=movie-unit, provider=org.eclipse.persistence.jpa.PersistenceProvider) +INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. +INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) +INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' +INFO - Enterprise application "/Users/dblevins/examples/jpa-eclipselink" loaded. +INFO - Assembling app: /Users/dblevins/examples/jpa-eclipselink +INFO - PersistenceUnit(name=movie-unit, provider=org.eclipse.persistence.jpa.PersistenceProvider) - provider time 511ms +INFO - Jndi(name="java:global/jpa-eclipselink/Movies!org.superbiz.eclipselink.Movies") +INFO - Jndi(name="java:global/jpa-eclipselink/Movies") +INFO - Jndi(name="java:global/EjbModule225280863/org.superbiz.eclipselink.MoviesTest!org.superbiz.eclipselink.MoviesTest") +INFO - Jndi(name="java:global/EjbModule225280863/org.superbiz.eclipselink.MoviesTest") +INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Created Ejb(deployment-id=org.superbiz.eclipselink.MoviesTest, ejb-name=org.superbiz.eclipselink.MoviesTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Started Ejb(deployment-id=org.superbiz.eclipselink.MoviesTest, ejb-name=org.superbiz.eclipselink.MoviesTest, container=Default Managed Container) +INFO - Deployed Application(path=/Users/dblevins/examples/jpa-eclipselink) +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.188 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... diff --git a/examples/jpa-eclipselink/README.md b/examples/jpa-eclipselink/README.md deleted file mode 100644 index 1023c9bb64c..00000000000 --- a/examples/jpa-eclipselink/README.md +++ /dev/null @@ -1,211 +0,0 @@ -index-group=EntityManagers -type=page -status=published -title=JPA Eclipselink -~~~~~~ - -This example shows how to configure `persistence.xml` to work with Eclipselink. It uses an `@Entity` class and a `@Stateful` bean to add and delete entities from a database. - -## Creating the JPA Entity - -The entity itself is simply a pojo annotated with `@Entity`. We create one pojo called `Movie` which we can use to hold movie records. - - package org.superbiz.eclipselink; - - import javax.persistence.Entity; - import javax.persistence.GeneratedValue; - import javax.persistence.GenerationType; - import javax.persistence.Id; - - @Entity - public class Movie { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private long id; - - private String director; - private String title; - private int year; - - public Movie() { - } - - public Movie(String director, String title, int year) { - this.director = director; - this.title = title; - this.year = year; - } - - public String getDirector() { - return director; - } - - public void setDirector(String director) { - this.director = director; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } - - } - -## Database Operations - -This is the bean responsible for database operations; it allows us to persist or delete entities. -For more information we recommend you to see [injection-of-entitymanager](http://tomee.apache.org/examples-trunk/injection-of-entitymanager/README.html) - - - package org.superbiz.eclipselink; - - import javax.ejb.Stateful; - import javax.persistence.EntityManager; - import javax.persistence.PersistenceContext; - import javax.persistence.PersistenceContextType; - import javax.persistence.Query; - import java.util.List; - - @Stateful - public class Movies { - - @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) - private EntityManager entityManager; - - public void addMovie(Movie movie) throws Exception { - entityManager.persist(movie); - } - - public void deleteMovie(Movie movie) throws Exception { - entityManager.remove(movie); - } - - public List getMovies() throws Exception { - Query query = entityManager.createQuery("SELECT m from Movie as m"); - return query.getResultList(); - } - } - -## Persistence.xml with EclipseLink configuration - -This operation is too easy, just set the `provider` to `org.eclipse.persistence.jpa.PersistenceProvider` and add additional properties to the persistence unit. -The example has followed a strategy that allows the creation of tables in a HSQL database. -For a complete list of persistence unit properties see [here](http://www.eclipse.org/eclipselink/api/2.4/org/eclipse/persistence/config/PersistenceUnitProperties.html) - - - - org.eclipse.persistence.jpa.PersistenceProvider - movieDatabase - movieDatabaseUnmanaged - - - - - - - - - -## MoviesTest - -Testing JPA is quite easy, we can simply use the `EJBContainer` API to create a container in our test case. - - package org.superbiz.eclipselink; - - import junit.framework.TestCase; - - import javax.ejb.embeddable.EJBContainer; - import javax.naming.Context; - import java.util.List; - import java.util.Properties; - - /** - * @version $Revision: 607077 $ $Date: 2007-12-27 06:55:23 -0800 (Thu, 27 Dec 2007) $ - */ - public class MoviesTest extends TestCase { - - public void test() throws Exception { - Properties p = new Properties(); - p.put("movieDatabase", "new://Resource?type=DataSource"); - p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); - p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); - - final Context context = EJBContainer.createEJBContainer(p).getContext(); - - Movies movies = (Movies) context.lookup("java:global/jpa-eclipselink/Movies"); - - movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); - movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); - movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); - - List list = movies.getMovies(); - assertEquals("List.size()", 3, list.size()); - - for (Movie movie : list) { - movies.deleteMovie(movie); - } - - assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); - } - } - -# Running - -When we run our test case we should see output similar to the following. - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.eclipselink.MoviesTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/jpa-eclipselink - INFO - openejb.base = /Users/dblevins/examples/jpa-eclipselink - INFO - Using 'javax.ejb.embeddable.EJBContainer=true' - INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) - INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) - INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) - INFO - Found EjbModule in classpath: /Users/dblevins/examples/jpa-eclipselink/target/classes - INFO - Beginning load: /Users/dblevins/examples/jpa-eclipselink/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/jpa-eclipselink - INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) - INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean org.superbiz.eclipselink.MoviesTest: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring PersistenceUnit(name=movie-unit, provider=org.eclipse.persistence.jpa.PersistenceProvider) - INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. - INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) - INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' - INFO - Enterprise application "/Users/dblevins/examples/jpa-eclipselink" loaded. - INFO - Assembling app: /Users/dblevins/examples/jpa-eclipselink - INFO - PersistenceUnit(name=movie-unit, provider=org.eclipse.persistence.jpa.PersistenceProvider) - provider time 511ms - INFO - Jndi(name="java:global/jpa-eclipselink/Movies!org.superbiz.eclipselink.Movies") - INFO - Jndi(name="java:global/jpa-eclipselink/Movies") - INFO - Jndi(name="java:global/EjbModule225280863/org.superbiz.eclipselink.MoviesTest!org.superbiz.eclipselink.MoviesTest") - INFO - Jndi(name="java:global/EjbModule225280863/org.superbiz.eclipselink.MoviesTest") - INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Created Ejb(deployment-id=org.superbiz.eclipselink.MoviesTest, ejb-name=org.superbiz.eclipselink.MoviesTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Started Ejb(deployment-id=org.superbiz.eclipselink.MoviesTest, ejb-name=org.superbiz.eclipselink.MoviesTest, container=Default Managed Container) - INFO - Deployed Application(path=/Users/dblevins/examples/jpa-eclipselink) - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.188 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - diff --git a/examples/jpa-enumerated/README.adoc b/examples/jpa-enumerated/README.adoc new file mode 100644 index 00000000000..c446204cedd --- /dev/null +++ b/examples/jpa-enumerated/README.adoc @@ -0,0 +1,259 @@ += JPA and Enums via @Enumerated +:index-group: JPA +:jbake-type: page +:jbake-status: published + +It can sometimes be desirable to have a Java `enum` type to represent a particular column in a database. JPA supports converting database data to and from Java `enum` types via the `@javax.persistence.Enumerated` annotation. + +This example will show basic `@Enumerated` usage in a field of an `@Entity` as well as ``enum``s as the parameter of a `Query`. We'll also see that the actual database representation can be effectively `String` or `int`. + +== Enum + +For our example we will leverage the familiar `Movie` entity and add a new field to represent the MPAA.org rating of the movie. This is defined via a simple `enum` that requires no JPA specific annotations. + + public enum Rating { + UNRATED, + G, + PG, + PG13, + R, + NC17 + } + +== @Enumerated + +In our `Movie` entity, we add a `rating` field of the enum type `Rating` and annotate it with `@Enumerated(EnumType.STRING)` to declare that its value should be converted from what is effectively a `String` in the database to the `Rating` type. + +.... +@Entity +public class Movie { + + @Id + @GeneratedValue + private int id; + private String director; + private String title; + private int year; + + @Enumerated(EnumType.STRING) + private Rating rating; + + public Movie() { + } + + public Movie(String director, String title, int year, Rating rating) { + this.director = director; + this.title = title; + this.year = year; + this.rating = rating; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + + public Rating getRating() { + return rating; + } + + public void setRating(Rating rating) { + this.rating = rating; + } +} +.... + +The above is enough and we are effectively done. For the sake of completeness we'll show a sample `Query` + +== Enum in JPQL Query + +Note the `findByRating` method which creates a `Query` with a `rating` named parameter. The key thing to notice is that the `rating` enum instance itself is passed into the + `query.setParameter` method, *not* `rating.name()` or `rating.ordinal()`. + +Regardless if you use `EnumType.STRING` or `EnumType.ORDINAL`, you still always pass the enum itself in calls to `query.setParameter`. + +.... +@Stateful +public class Movies { + + @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) + private EntityManager entityManager; + + public void addMovie(Movie movie) { + entityManager.persist(movie); + } + + public void deleteMovie(Movie movie) { + entityManager.remove(movie); + } + + public List findByRating(Rating rating) { + final Query query = entityManager.createQuery("SELECT m FROM Movie as m WHERE m.rating = :rating"); + query.setParameter("rating", rating); + return query.getResultList(); + } + + public List getMovies() throws Exception { + Query query = entityManager.createQuery("SELECT m from Movie as m"); + return query.getResultList(); + } + +} +.... + +== EnumType.STRING vs EnumType.ORDINAL + +It is a matter of style how you would like your `enum` data represented in the database. Either `name()` or `ordinal()` are supported: + +* `@Enumerated(EnumType.STRING) Rating rating` the value of `rating.name()` is written and read from the corresponding database column; e.g. `G`, `PG`, `PG13` +* `@Enumerated(EnumType.ORDINAL) Rating rating` the value of `rating.ordinal()` is written and read from the corresponding database column; e.g. `0`, `1`, `2` + +The default is `EnumType.ORDINAL` + +There are advantages and disadvantages to each. + +=== Disadvantage of EnumType.ORDINAL + +A disadvantage of `EnumType.ORDINAL` is the effect of time and the desire to keep `enums` in a logical order. With `EnumType.ORDINAL` any new enum elements must be added to the +*end* of the list or you will accidentally change the meaning of all your records. + +Let's use our `Rating` enum and see how it would have had to evolve over time to keep up with changes in the MPAA.org ratings system. + +*1980* + + public enum Rating { + G, + PG, + R, + UNRATED + } + +*1984* PG-13 is added + + public enum Rating { + G, + PG, + R, + UNRATED, + PG13 + } + +*1990* NC-17 is added + + public enum Rating { + G, + PG, + R, + UNRATED, + PG13, + NC17 + } + +If `EnumType.STRING` was used, then the enum could be reordered at anytime and would instead look as we have defined it originally with ratings starting at `G` and increasing in severity to `NC17` and eventually `UNRATED`. With `EnumType.ORDINAL` the logical ordering would not have withstood the test of time as new values were added. + +If the order of the enum values is significant to your code, avoid `EnumType.ORDINAL` + +== Unit Testing the JPA @Enumerated + +.... +public class MoviesTest extends TestCase { + + public void test() throws Exception { + + final Properties p = new Properties(); + p.put("movieDatabase", "new://Resource?type=DataSource"); + p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); + p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); + + EJBContainer container = EJBContainer.createEJBContainer(p); + final Context context = container.getContext(); + + final Movies movies = (Movies) context.lookup("java:global/jpa-scratch/Movies"); + + movies.addMovie(new Movie("James Frawley", "The Muppet Movie", 1979, Rating.G)); + movies.addMovie(new Movie("Jim Henson", "The Great Muppet Caper", 1981, Rating.G)); + movies.addMovie(new Movie("Frank Oz", "The Muppets Take Manhattan", 1984, Rating.G)); + movies.addMovie(new Movie("James Bobin", "The Muppets", 2011, Rating.PG)); + + assertEquals("List.size()", 4, movies.getMovies().size()); + + assertEquals("List.size()", 3, movies.findByRating(Rating.G).size()); + + assertEquals("List.size()", 1, movies.findByRating(Rating.PG).size()); + + assertEquals("List.size()", 0, movies.findByRating(Rating.R).size()); + + container.close(); + } +} +.... + += Running + +To run the example via maven: + + cd jpa-enumerated + mvn clean install + +Which will generate output similar to the following: + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.jpa.enums.MoviesTest +Apache OpenEJB 4.0.0-beta-2 build: 20120115-08:26 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/openejb/examples/jpa-enumerated +INFO - openejb.base = /Users/dblevins/openejb/examples/jpa-enumerated +INFO - Using 'javax.ejb.embeddable.EJBContainer=true' +INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) +INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) +INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) +INFO - Found EjbModule in classpath: /Users/dblevins/openejb/examples/jpa-enumerated/target/classes +INFO - Beginning load: /Users/dblevins/openejb/examples/jpa-enumerated/target/classes +INFO - Configuring enterprise application: /Users/dblevins/openejb/examples/jpa-enumerated +INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) +INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean org.superbiz.jpa.enums.MoviesTest: Container(type=MANAGED, id=Default Managed Container) +INFO - Configuring PersistenceUnit(name=movie-unit) +INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. +INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) +INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' +INFO - Enterprise application "/Users/dblevins/openejb/examples/jpa-enumerated" loaded. +INFO - Assembling app: /Users/dblevins/openejb/examples/jpa-enumerated +INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 406ms +INFO - Jndi(name="java:global/jpa-enumerated/Movies!org.superbiz.jpa.enums.Movies") +INFO - Jndi(name="java:global/jpa-enumerated/Movies") +INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Deployed Application(path=/Users/dblevins/openejb/examples/jpa-enumerated) +INFO - Undeploying app: /Users/dblevins/openejb/examples/jpa-enumerated +INFO - Closing DataSource: movieDatabase +INFO - Closing DataSource: movieDatabaseNonJta +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.831 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... diff --git a/examples/jpa-enumerated/README.md b/examples/jpa-enumerated/README.md deleted file mode 100644 index d85b3b0cfa0..00000000000 --- a/examples/jpa-enumerated/README.md +++ /dev/null @@ -1,252 +0,0 @@ -index-group=EntityManagers -type=page -status=published -title=JPA and Enums via @Enumerated -~~~~~~ - -It can sometimes be desirable to have a Java `enum` type to represent a particular column in a database. JPA supports converting database data to and from Java `enum` types via the `@javax.persistence.Enumerated` annotation. - -This example will show basic `@Enumerated` usage in a field of an `@Entity` as well as `enum`s as the parameter of a `Query`. We'll also see that the actual database representation can be effectively `String` or `int`. - -## Enum - -For our example we will leverage the familiar `Movie` entity and add a new field to represent the MPAA.org rating of the movie. This is defined via a simple `enum` that requires no JPA specific annotations. - - public enum Rating { - UNRATED, - G, - PG, - PG13, - R, - NC17 - } - -## @Enumerated - -In our `Movie` entity, we add a `rating` field of the enum type `Rating` and annotate it with `@Enumerated(EnumType.STRING)` to declare that its value should be converted from what is effectively a `String` in the database to the `Rating` type. - - @Entity - public class Movie { - - @Id - @GeneratedValue - private int id; - private String director; - private String title; - private int year; - - @Enumerated(EnumType.STRING) - private Rating rating; - - public Movie() { - } - - public Movie(String director, String title, int year, Rating rating) { - this.director = director; - this.title = title; - this.year = year; - this.rating = rating; - } - - public String getDirector() { - return director; - } - - public void setDirector(String director) { - this.director = director; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } - - public Rating getRating() { - return rating; - } - - public void setRating(Rating rating) { - this.rating = rating; - } - } - -The above is enough and we are effectively done. For the sake of completeness we'll show a sample `Query` - -## Enum in JPQL Query - -Note the `findByRating` method which creates a `Query` with a `rating` named parameter. The key thing to notice is that the `rating` enum instance itself is passed into the - `query.setParameter` method, **not** `rating.name()` or `rating.ordinal()`. - -Regardless if you use `EnumType.STRING` or `EnumType.ORDINAL`, you still always pass the enum itself in calls to `query.setParameter`. - - @Stateful - public class Movies { - - @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) - private EntityManager entityManager; - - public void addMovie(Movie movie) { - entityManager.persist(movie); - } - - public void deleteMovie(Movie movie) { - entityManager.remove(movie); - } - - public List findByRating(Rating rating) { - final Query query = entityManager.createQuery("SELECT m FROM Movie as m WHERE m.rating = :rating"); - query.setParameter("rating", rating); - return query.getResultList(); - } - - public List getMovies() throws Exception { - Query query = entityManager.createQuery("SELECT m from Movie as m"); - return query.getResultList(); - } - - } - -## EnumType.STRING vs EnumType.ORDINAL - -It is a matter of style how you would like your `enum` data represented in the database. Either `name()` or `ordinal()` are supported: - - - `@Enumerated(EnumType.STRING) Rating rating` the value of `rating.name()` is written and read from the corresponding database column; e.g. `G`, `PG`, `PG13` - - `@Enumerated(EnumType.ORDINAL) Rating rating` the value of `rating.ordinal()` is written and read from the corresponding database column; e.g. `0`, `1`, `2` - -The default is `EnumType.ORDINAL` - -There are advantages and disadvantages to each. - -### Disadvantage of EnumType.ORDINAL - -A disadvantage of `EnumType.ORDINAL` is the effect of time and the desire to keep `enums` in a logical order. With `EnumType.ORDINAL` any new enum elements must be added to the -**end** of the list or you will accidentally change the meaning of all your records. - -Let's use our `Rating` enum and see how it would have had to evolve over time to keep up with changes in the MPAA.org ratings system. - -**1980** - - public enum Rating { - G, - PG, - R, - UNRATED - } - -**1984** PG-13 is added - - public enum Rating { - G, - PG, - R, - UNRATED, - PG13 - } - -**1990** NC-17 is added - - public enum Rating { - G, - PG, - R, - UNRATED, - PG13, - NC17 - } - -If `EnumType.STRING` was used, then the enum could be reordered at anytime and would instead look as we have defined it originally with ratings starting at `G` and increasing in severity to `NC17` and eventually `UNRATED`. With `EnumType.ORDINAL` the logical ordering would not have withstood the test of time as new values were added. - -If the order of the enum values is significant to your code, avoid `EnumType.ORDINAL` - -## Unit Testing the JPA @Enumerated - - public class MoviesTest extends TestCase { - - public void test() throws Exception { - - final Properties p = new Properties(); - p.put("movieDatabase", "new://Resource?type=DataSource"); - p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); - p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); - - EJBContainer container = EJBContainer.createEJBContainer(p); - final Context context = container.getContext(); - - final Movies movies = (Movies) context.lookup("java:global/jpa-scratch/Movies"); - - movies.addMovie(new Movie("James Frawley", "The Muppet Movie", 1979, Rating.G)); - movies.addMovie(new Movie("Jim Henson", "The Great Muppet Caper", 1981, Rating.G)); - movies.addMovie(new Movie("Frank Oz", "The Muppets Take Manhattan", 1984, Rating.G)); - movies.addMovie(new Movie("James Bobin", "The Muppets", 2011, Rating.PG)); - - assertEquals("List.size()", 4, movies.getMovies().size()); - - assertEquals("List.size()", 3, movies.findByRating(Rating.G).size()); - - assertEquals("List.size()", 1, movies.findByRating(Rating.PG).size()); - - assertEquals("List.size()", 0, movies.findByRating(Rating.R).size()); - - container.close(); - } - } - -# Running - -To run the example via maven: - - cd jpa-enumerated - mvn clean install - -Which will generate output similar to the following: - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.jpa.enums.MoviesTest - Apache OpenEJB 4.0.0-beta-2 build: 20120115-08:26 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/openejb/examples/jpa-enumerated - INFO - openejb.base = /Users/dblevins/openejb/examples/jpa-enumerated - INFO - Using 'javax.ejb.embeddable.EJBContainer=true' - INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) - INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) - INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) - INFO - Found EjbModule in classpath: /Users/dblevins/openejb/examples/jpa-enumerated/target/classes - INFO - Beginning load: /Users/dblevins/openejb/examples/jpa-enumerated/target/classes - INFO - Configuring enterprise application: /Users/dblevins/openejb/examples/jpa-enumerated - INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) - INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean org.superbiz.jpa.enums.MoviesTest: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring PersistenceUnit(name=movie-unit) - INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. - INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) - INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' - INFO - Enterprise application "/Users/dblevins/openejb/examples/jpa-enumerated" loaded. - INFO - Assembling app: /Users/dblevins/openejb/examples/jpa-enumerated - INFO - PersistenceUnit(name=movie-unit, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 406ms - INFO - Jndi(name="java:global/jpa-enumerated/Movies!org.superbiz.jpa.enums.Movies") - INFO - Jndi(name="java:global/jpa-enumerated/Movies") - INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Deployed Application(path=/Users/dblevins/openejb/examples/jpa-enumerated) - INFO - Undeploying app: /Users/dblevins/openejb/examples/jpa-enumerated - INFO - Closing DataSource: movieDatabase - INFO - Closing DataSource: movieDatabaseNonJta - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.831 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 diff --git a/examples/jpa-hibernate/README.adoc b/examples/jpa-hibernate/README.adoc new file mode 100644 index 00000000000..0bb85f13a23 --- /dev/null +++ b/examples/jpa-hibernate/README.adoc @@ -0,0 +1,213 @@ += JPA Hibernate +:index-group: JPA +:jbake-type: page +:jbake-status: published + +This example shows the persist, remove and creation a query in JPA Hibernate. +The Java Persistence API (JPA) is a Java specification for accessing, persisting, and managing data between Java objects / classes and a relational database. + +== Movie + +Define the class Movie as an entity with de annotation @Entity + +.... +package org.superbiz.injection.h3jpa; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Movie { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String director; + private String title; + private int year; + + public Movie() { + } + + public Movie(String director, String title, int year) { + this.director = director; + this.title = title; + this.year = year; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + +} +.... + +== Movies + +@PersistenceContext A persistence context is a set of entities such that for any persistent identity there is a unique entity instance. +@EntityManager is associated with a persistence context. Is at the core of JPA, supported by some methods: persist, remove,merge, find, + +.... +package org.superbiz.injection.h3jpa; + +import javax.ejb.Stateful; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.PersistenceContextType; +import javax.persistence.Query; +import java.util.List; + +@Stateful +public class Movies { + + @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) + private EntityManager entityManager; + + public void addMovie(Movie movie) throws Exception { + entityManager.persist(movie); + } + + public void deleteMovie(Movie movie) throws Exception { + entityManager.remove(movie); + } + + public List getMovies() throws Exception { + Query query = entityManager.createQuery("SELECT m from Movie as m"); + return query.getResultList(); + } +} +.... + +== persistence.xml + + + + org.hibernate.ejb.HibernatePersistence + movieDatabase + movieDatabaseUnmanaged + + + + + + + +== MoviesTest + +.... +package org.superbiz.injection.h3jpa; + +import junit.framework.TestCase; + +import javax.ejb.embeddable.EJBContainer; +import javax.naming.Context; +import java.util.List; +import java.util.Properties; + +/** + * @version $Revision: 607077 $ $Date: 2007-12-27 06:55:23 -0800 (Thu, 27 Dec 2007) $ + */ +public class MoviesTest extends TestCase { + + public void test() throws Exception { + final Properties p = new Properties(); + p.put("movieDatabase", "new://Resource?type=DataSource"); + p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); + p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); + + final Context context = EJBContainer.createEJBContainer(p).getContext(); + Movies movies = (Movies) context.lookup("java:global/jpa-hibernate/Movies"); + + movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); + movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); + movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); + + List list = movies.getMovies(); + assertEquals("List.size()", 3, list.size()); + + for (Movie movie : list) { + movies.deleteMovie(movie); + } + + assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); + } +} +.... + += Running + +To run the example via maven: + +cd jpa-hibernate +mvn clean install + +Which will generate output similar to the following: + +.... +------------------------------------------------------- + T E S T S +------------------------------------------------------- +Running org.superbiz.injection.h3jpa.MoviesTest +Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 +http://tomee.apache.org/ +INFO - openejb.home = /Users/dblevins/examples/jpa-hibernate +INFO - openejb.base = /Users/dblevins/examples/jpa-hibernate +INFO - Using 'javax.ejb.embeddable.EJBContainer=true' +INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) +INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) +INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) +INFO - Found EjbModule in classpath: /Users/dblevins/examples/jpa-hibernate/target/classes +INFO - Beginning load: /Users/dblevins/examples/jpa-hibernate/target/classes +INFO - Configuring enterprise application: /Users/dblevins/examples/jpa-hibernate +INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) +INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean org.superbiz.injection.h3jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container) +INFO - Configuring PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence) +INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. +INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) +INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' +INFO - Enterprise application "/Users/dblevins/examples/jpa-hibernate" loaded. +INFO - Assembling app: /Users/dblevins/examples/jpa-hibernate +INFO - PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence) - provider time 631ms +INFO - Jndi(name="java:global/jpa-hibernate/Movies!org.superbiz.injection.h3jpa.Movies") +INFO - Jndi(name="java:global/jpa-hibernate/Movies") +INFO - Jndi(name="java:global/EjbModule1235930463/org.superbiz.injection.h3jpa.MoviesTest!org.superbiz.injection.h3jpa.MoviesTest") +INFO - Jndi(name="java:global/EjbModule1235930463/org.superbiz.injection.h3jpa.MoviesTest") +INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Created Ejb(deployment-id=org.superbiz.injection.h3jpa.MoviesTest, ejb-name=org.superbiz.injection.h3jpa.MoviesTest, container=Default Managed Container) +INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) +INFO - Started Ejb(deployment-id=org.superbiz.injection.h3jpa.MoviesTest, ejb-name=org.superbiz.injection.h3jpa.MoviesTest, container=Default Managed Container) +INFO - Deployed Application(path=/Users/dblevins/examples/jpa-hibernate) +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.22 sec + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... diff --git a/examples/jpa-hibernate/README.md b/examples/jpa-hibernate/README.md deleted file mode 100644 index 081fad4bbc3..00000000000 --- a/examples/jpa-hibernate/README.md +++ /dev/null @@ -1,209 +0,0 @@ -index-group=EntityManagers -type=page -status=published -title=JPA Hibernate -~~~~~~ - -This example shows the persist, remove and creation a query in JPA Hibernate. -The Java Persistence API (JPA) is a Java specification for accessing, persisting, and managing data between Java objects / classes and a relational database. - - -## Movie - -Define the class Movie as an entity with de annotation @Entity - - package org.superbiz.injection.h3jpa; - - import javax.persistence.Entity; - import javax.persistence.GeneratedValue; - import javax.persistence.GenerationType; - import javax.persistence.Id; - - @Entity - public class Movie { - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private long id; - - private String director; - private String title; - private int year; - - public Movie() { - } - - public Movie(String director, String title, int year) { - this.director = director; - this.title = title; - this.year = year; - } - - public String getDirector() { - return director; - } - - public void setDirector(String director) { - this.director = director; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } - - } - -## Movies - -@PersistenceContext A persistence context is a set of entities such that for any persistent identity there is a unique entity instance. -@EntityManager is associated with a persistence context. Is at the core of JPA, supported by some methods: persist, remove,merge, find, - - package org.superbiz.injection.h3jpa; - - import javax.ejb.Stateful; - import javax.persistence.EntityManager; - import javax.persistence.PersistenceContext; - import javax.persistence.PersistenceContextType; - import javax.persistence.Query; - import java.util.List; - - @Stateful - public class Movies { - - @PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED) - private EntityManager entityManager; - - public void addMovie(Movie movie) throws Exception { - entityManager.persist(movie); - } - - public void deleteMovie(Movie movie) throws Exception { - entityManager.remove(movie); - } - - public List getMovies() throws Exception { - Query query = entityManager.createQuery("SELECT m from Movie as m"); - return query.getResultList(); - } - } - -## persistence.xml - - - - org.hibernate.ejb.HibernatePersistence - movieDatabase - movieDatabaseUnmanaged - - - - - - - - -## MoviesTest - - package org.superbiz.injection.h3jpa; - - import junit.framework.TestCase; - - import javax.ejb.embeddable.EJBContainer; - import javax.naming.Context; - import java.util.List; - import java.util.Properties; - - /** - * @version $Revision: 607077 $ $Date: 2007-12-27 06:55:23 -0800 (Thu, 27 Dec 2007) $ - */ - public class MoviesTest extends TestCase { - - public void test() throws Exception { - final Properties p = new Properties(); - p.put("movieDatabase", "new://Resource?type=DataSource"); - p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); - p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); - - final Context context = EJBContainer.createEJBContainer(p).getContext(); - Movies movies = (Movies) context.lookup("java:global/jpa-hibernate/Movies"); - - movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992)); - movies.addMovie(new Movie("Joel Coen", "Fargo", 1996)); - movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998)); - - List list = movies.getMovies(); - assertEquals("List.size()", 3, list.size()); - - for (Movie movie : list) { - movies.deleteMovie(movie); - } - - assertEquals("Movies.getMovies()", 0, movies.getMovies().size()); - } - } - -# Running - -To run the example via maven: - -cd jpa-hibernate -mvn clean install - -Which will generate output similar to the following: - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.injection.h3jpa.MoviesTest - Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 - http://tomee.apache.org/ - INFO - openejb.home = /Users/dblevins/examples/jpa-hibernate - INFO - openejb.base = /Users/dblevins/examples/jpa-hibernate - INFO - Using 'javax.ejb.embeddable.EJBContainer=true' - INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service) - INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager) - INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database) - INFO - Found EjbModule in classpath: /Users/dblevins/examples/jpa-hibernate/target/classes - INFO - Beginning load: /Users/dblevins/examples/jpa-hibernate/target/classes - INFO - Configuring enterprise application: /Users/dblevins/examples/jpa-hibernate - INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container) - INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container) - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean org.superbiz.injection.h3jpa.MoviesTest: Container(type=MANAGED, id=Default Managed Container) - INFO - Configuring PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence) - INFO - Auto-creating a Resource with id 'movieDatabaseNonJta' of type 'DataSource for 'movie-unit'. - INFO - Configuring Service(id=movieDatabaseNonJta, type=Resource, provider-id=movieDatabase) - INFO - Adjusting PersistenceUnit movie-unit to Resource ID 'movieDatabaseNonJta' from 'movieDatabaseUnmanaged' - INFO - Enterprise application "/Users/dblevins/examples/jpa-hibernate" loaded. - INFO - Assembling app: /Users/dblevins/examples/jpa-hibernate - INFO - PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence) - provider time 631ms - INFO - Jndi(name="java:global/jpa-hibernate/Movies!org.superbiz.injection.h3jpa.Movies") - INFO - Jndi(name="java:global/jpa-hibernate/Movies") - INFO - Jndi(name="java:global/EjbModule1235930463/org.superbiz.injection.h3jpa.MoviesTest!org.superbiz.injection.h3jpa.MoviesTest") - INFO - Jndi(name="java:global/EjbModule1235930463/org.superbiz.injection.h3jpa.MoviesTest") - INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Created Ejb(deployment-id=org.superbiz.injection.h3jpa.MoviesTest, ejb-name=org.superbiz.injection.h3jpa.MoviesTest, container=Default Managed Container) - INFO - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) - INFO - Started Ejb(deployment-id=org.superbiz.injection.h3jpa.MoviesTest, ejb-name=org.superbiz.injection.h3jpa.MoviesTest, container=Default Managed Container) - INFO - Deployed Application(path=/Users/dblevins/examples/jpa-hibernate) - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.22 sec - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - diff --git a/examples/multi-jpa-provider-testing/README.adoc b/examples/multi-jpa-provider-testing/README.adoc new file mode 100644 index 00000000000..0472365b88f --- /dev/null +++ b/examples/multi-jpa-provider-testing/README.adoc @@ -0,0 +1,287 @@ += Multiple JPA Providers Test +:index-group: JPA +:jbake-type: page +:jbake-status: published + +This test shows how to use multiple JPA providers, Hibernate and Openjpa. Using JPA annotations the code can be easily used with different implementations. The @Entity class is straight forward, a Person POJO with an id and a name, the persistence.xml creates and drop Person table for both implementations. The examples and implementations dependency are inside test resources, in particularly: arquillian.xml for test purpose, hibernate-pom.xml loads hibernate-core dependencies and openjpa-pom.xml loads openjpa dependencies. The test inside JPATest.java class is executed twice, once for each implementation. + +== @Entity + +Simple POJO class that follows JPA standard + +.... +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue + private long id; + + private String name; + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} +.... + +== persistence.xml + +Create and drop Person table + +.... + + + jdbc/jpa + + + + + + + + + +.... + +== JPA test + +The entity manager is injected through cdi and an Object Person is created and inserted into the inmemory database + +.... +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.transaction.api.annotation.TransactionMode; +import org.jboss.arquillian.transaction.api.annotation.Transactional; +import org.jboss.shrinkwrap.api.ArchivePaths; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.superbiz.model.Person; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import static org.junit.Assert.assertNotNull; + +@RunWith(Arquillian.class) +public class JPATest { + + @Deployment + public static WebArchive war() { + return ShrinkWrap.create(WebArchive.class) + .addClass(Person.class) + .addAsWebInfResource(new ClassLoaderAsset("META-INF/persistence.xml"), ArchivePaths.create("persistence.xml")); + } + + @PersistenceContext + private EntityManager em; + + @Test + @Transactional(TransactionMode.ROLLBACK) + public void persist() { + assertNotNull(em); + + // do something with the em + final Person p = new Person(); + p.setName("Apache OpenEJB"); + em.persist(p); + } +} +.... + +Inside the example there are no reference to the JPA implementations. + +== Test implementations + +The test classes inside org.superbiz.enricher package simply load the implementation libraries and the test runs twice as described inside the pom.xml, a system property variable is used to distinguish between Hibernate and OpenJPA. + += Running + +Running the example can be done from maven with a simple 'mvn clean install' command run from the 'multi-jpa-provider-testing' directory. + +When run you should see output similar to the following. + +.... +------------------------------------------------------- +T E S T S +------------------------------------------------------- +Running org.superbiz.JPATest +INFO - ******************************************************************************** +INFO - OpenEJB http://tomee.apache.org/ +INFO - Startup: Wed Dec 26 17:55:31 CET 2018 +INFO - Copyright 1999-2018 (C) Apache OpenEJB Project, All Rights Reserved. +INFO - Version: 8.0.0-SNAPSHOT +INFO - Build date: 20181226 +INFO - Build time: 02:26 +INFO - ******************************************************************************** +INFO - openejb.home = /tomee/examples/multi-jpa-provider-testing +INFO - openejb.base = /tomee/examples/multi-jpa-provider-testing +INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@5db45159 +INFO - Succeeded in installing singleton service +INFO - Cannot find the configuration file [conf/openejb.xml]. Will attempt to create one for the beans deployed. +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 - Using 'openejb.deployments.classpath=false' +INFO - Creating TransactionManager(id=Default Transaction Manager) +INFO - Creating SecurityService(id=Default Security Service) +INFO - Using 'openejb.classloader.forced-load=org.superbiz.model' +INFO - Configuring enterprise application: /tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean 413724ac-4a44-48a3-ae4a-db190b95cc62_org.superbiz.JPATest: Container(type=MANAGED, id=Default Managed Container) +INFO - Creating Container(id=Default Managed Container) +INFO - Using directory /tmp for stateful session passivation +INFO - Configuring PersistenceUnit(name=jpa) +INFO - Configuring Service(id=Default JDBC Database, type=Resource, provider-id=Default JDBC Database) +INFO - Auto-creating a Resource with id 'Default JDBC Database' of type 'DataSource for 'jpa'. +INFO - Creating Resource(id=Default JDBC Database) +INFO - Configuring Service(id=Default Unmanaged JDBC Database, type=Resource, provider-id=Default Unmanaged JDBC Database) +INFO - Auto-creating a Resource with id 'Default Unmanaged JDBC Database' of type 'DataSource for 'jpa'. +INFO - Creating Resource(id=Default Unmanaged JDBC Database) +INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default JDBC Database' from 'jdbc/jpa' +INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default Unmanaged JDBC Database' from 'null' +INFO - Using 'javax.persistence.provider=org.hibernate.ejb.HibernatePersistence' +INFO - Enterprise application "/tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war" loaded. +INFO - Assembling app: /tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war +INFO - HCANN000001: Hibernate Commons Annotations {4.0.2.Final} +INFO - HHH000412: Hibernate Core {4.2.18.Final} +INFO - HHH000206: hibernate.properties not found +INFO - HHH000021: Bytecode provider name : javassist +INFO - HHH000204: Processing PersistenceUnitInfo [ + name: jpa + ...] +INFO - HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider +INFO - HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect +INFO - HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory +INFO - HHH000397: Using ASTQueryTranslatorFactory +INFO - HHH000227: Running hbm2ddl schema export +INFO - HHH000230: Schema export complete +INFO - PersistenceUnit(name=jpa, provider=org.hibernate.ejb.HibernatePersistence) - provider time 1053ms +INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@5db45159 +INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found +INFO - OpenWebBeans Container is starting... +INFO - Adding OpenWebBeansPlugin : [CdiPlugin] +INFO - HV000001: Hibernate Validator 5.1.3.Final +INFO - All injection points were validated successfully. +INFO - OpenWebBeans Container has started, it took 194 ms. +INFO - Deployed Application(path=/tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war) +INFO - Undeploying app: /tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war +INFO - HHH000227: Running hbm2ddl schema export +INFO - HHH000230: Schema export complete +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.951 sec - in org.superbiz.JPATest +INFO - Destroying container system +INFO - Closing DataSource: Default JDBC Database +INFO - Closing DataSource: Default Unmanaged JDBC Database + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 + +------------------------------------------------------- +T E S T S +------------------------------------------------------- +SUREFIRE-859: 57 classpath-bootstrap INFO [main] openjpa.Enhance - You have enabled runtime enhancement, but have not specified the set of persistent classes. OpenJPA must look for metadata for every loaded class, which might increase class load times significantly. +353 classpath-bootstrap INFO [main] openjpa.Runtime - OpenJPA dynamically loaded a validation provider. +Running org.superbiz.JPATest +INFO - ******************************************************************************** +INFO - OpenEJB http://tomee.apache.org/ +INFO - Startup: Wed Dec 26 17:55:35 CET 2018 +INFO - Copyright 1999-2018 (C) Apache OpenEJB Project, All Rights Reserved. +INFO - Version: 8.0.0-SNAPSHOT +INFO - Build date: 20181226 +INFO - Build time: 02:26 +INFO - ******************************************************************************** +INFO - openejb.home = /tomee/examples/multi-jpa-provider-testing +INFO - openejb.base = /tomee/examples/multi-jpa-provider-testing +INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@4a8a60bc +INFO - Succeeded in installing singleton service +INFO - Cannot find the configuration file [conf/openejb.xml]. Will attempt to create one for the beans deployed. +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 - Using 'openejb.deployments.classpath=false' +INFO - Creating TransactionManager(id=Default Transaction Manager) +INFO - Creating SecurityService(id=Default Security Service) +INFO - Configuring enterprise application: /tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war +INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) +INFO - Auto-creating a container for bean 450e397e-de39-49eb-837f-7b066fc9f248_org.superbiz.JPATest: Container(type=MANAGED, id=Default Managed Container) +INFO - Creating Container(id=Default Managed Container) +INFO - Using directory /tmp for stateful session passivation +INFO - Configuring PersistenceUnit(name=jpa) +INFO - Configuring Service(id=Default JDBC Database, type=Resource, provider-id=Default JDBC Database) +INFO - Auto-creating a Resource with id 'Default JDBC Database' of type 'DataSource for 'jpa'. +INFO - Creating Resource(id=Default JDBC Database) +INFO - Configuring Service(id=Default Unmanaged JDBC Database, type=Resource, provider-id=Default Unmanaged JDBC Database) +INFO - Auto-creating a Resource with id 'Default Unmanaged JDBC Database' of type 'DataSource for 'jpa'. +INFO - Creating Resource(id=Default Unmanaged JDBC Database) +INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default JDBC Database' from 'jdbc/jpa' +INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default Unmanaged JDBC Database' from 'null' +INFO - Using 'javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl' +INFO - Enterprise application "/tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war" loaded. +INFO - Assembling app: /tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war +INFO - OpenJPA dynamically loaded a validation provider. +INFO - PersistenceUnit(name=jpa, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 116ms +INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@4a8a60bc +INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found +INFO - OpenWebBeans Container is starting... +INFO - Adding OpenWebBeansPlugin : [CdiPlugin] +INFO - HV000001: Hibernate Validator 5.1.3.Final +INFO - All injection points were validated successfully. +INFO - OpenWebBeans Container has started, it took 170 ms. +INFO - Deployed Application(path=/tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war) +INFO - Starting OpenJPA 3.0.0 +INFO - Using dictionary class "org.apache.openjpa.jdbc.sql.HSQLDictionary" (HSQL Database Engine 2.3.2 ,HSQL Database Engine Driver 2.3.2). +INFO - Connected to HSQL Database Engine version 2.2 using JDBC driver HSQL Database Engine Driver version 2.3.2. +INFO - Undeploying app: /tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.666 sec - in org.superbiz.JPATest +INFO - Destroying container system +INFO - Closing DataSource: Default JDBC Database +INFO - Closing DataSource: Default Unmanaged JDBC Database + +Results : + +Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 +.... + +From the log you can see that both implementations are used: INFO - Using 'javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl', INFO - Using 'javax.persistence.provider=org.hibernate.ejb.HibernatePersistence'. + +== Inside the jar + +If we look at the jar built by maven, we'll see the application itself is quite small: + + jar tvf multi-jpa-provider-testing-8.0.0-SNAPSHOT.jar + 0 Wed Dec 26 17:55:40 CET 2018 META-INF/ + 134 Wed Dec 26 17:55:38 CET 2018 META-INF/MANIFEST.MF + 0 Wed Dec 26 17:55:30 CET 2018 org/ + 0 Wed Dec 26 17:55:30 CET 2018 org/superbiz/ + 0 Wed Dec 26 17:55:30 CET 2018 org/superbiz/model/ + 780 Wed Dec 26 17:55:30 CET 2018 org/superbiz/model/Person.class + 1554 Wed Dec 26 17:55:30 CET 2018 META-INF/persistence.xml + 0 Wed Dec 26 17:55:40 CET 2018 META-INF/maven/ + 0 Wed Dec 26 17:55:40 CET 2018 META-INF/maven/org.superbiz/ + 0 Wed Dec 26 17:55:40 CET 2018 META-INF/maven/org.superbiz/multi-jpa-provider-testing/ + 5696 Wed Dec 26 17:41:54 CET 2018 META-INF/maven/org.superbiz/multi-jpa-provider-testing/pom.xml + 132 Wed Dec 26 17:55:38 CET 2018 META-INF/maven/org.superbiz/multi-jpa-provider-testing/pom.properties + +Inside the resources package there is only a java class and the persistence.xml and the only dependency is javaee-api:8.0. diff --git a/examples/simple-remote-tomcatusers/README.adoc b/examples/simple-remote-tomcatusers/README.adoc index 2f65df75428..642a2a0254c 100644 --- a/examples/simple-remote-tomcatusers/README.adoc +++ b/examples/simple-remote-tomcatusers/README.adoc @@ -1,106 +1,106 @@ -index-group=Unrevised -type=page -status=published - -= Simple Remote Tomcatusers - -This is an example on how to use JNDI with security restrictions in TomEE. - - -== Contract - -In our example Contract is an interface annotated with @Remote which indicates that all methods of this interface can be accessed by client code. -[source,java] ----- - - @Remote - public interface Contract { - String hi(); - } ----- -== ContractImpl - -ContractImpl is a concrete implementation of the Contract interface restricting access to the hi method for users with role test. - -[source,java] ----- -public class ContractImpl implements Contract { - @Override - @RolesAllowed("test") - public String hi() { - return "hi"; - } -} ----- - -== ContractTest - -In this class we test the correctness of our application with Arquillian by creating a war with Contract and ContractImpl classes and deploying to -an embedded TomEE server with the war name test.war. In arquillian.xml we specify that arquillian pick tomcat-users.xml from src/test/conf folder. -In tomcat-users.xml there is a single user with username "tomcat", password="users" and role "test". - -To test we lookup for the ContractImpl and call the hi method using different usernames and passwords. - - -[source,java] ----- -@RunWith(Arquillian.class) -public class ContractTest { - @Deployment(testable = false) - public static Archive app() { - return ShrinkWrap.create(WebArchive.class, "test.war") - .addClasses(Contract.class, ContractImpl.class); - } - - @ArquillianResource - private URL base; - - @Test - public void valid() throws NamingException { - assertEquals("hi", hi(new Properties() {{ - setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); - setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort())); - setProperty(Context.SECURITY_PRINCIPAL, "tomcat"); - setProperty(Context.SECURITY_CREDENTIALS, "users"); - }})); - } - - @Test - public void invalid() throws NamingException { - try { - hi(new Properties() {{ - setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); - setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort())); - setProperty(Context.SECURITY_PRINCIPAL, "tomcat"); - setProperty(Context.SECURITY_CREDENTIALS, "wrong"); - }}); - fail(); - } catch (final AuthenticationException ae) { - // ok - } - } - - @Test - public void missingCredentials() throws NamingException { - try { - hi(new Properties() {{ - setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); - setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort())); - }}); - fail(); - } catch (final EJBAccessException eae) { - // no-op - } - } - - private String hi(final Properties clientConfig) throws NamingException { - return Contract.class.cast(new InitialContext(clientConfig).lookup("java:global/test/ContractImpl!org.superbiz.Contract")).hi(); - } -} ----- - -== Run the application: - - mvn install - +index-group=Unrevised +type=page +status=published + += Simple Remote Tomcatusers + +This is an example on how to use JNDI with security restrictions in TomEE. + + +== Contract + +In our example Contract is an interface annotated with @Remote which indicates that all methods of this interface can be accessed by client code. +[source,java] +---- + + @Remote + public interface Contract { + String hi(); + } +---- +== ContractImpl + +ContractImpl is a concrete implementation of the Contract interface restricting access to the hi method for users with role test. + +[source,java] +---- +public class ContractImpl implements Contract { + @Override + @RolesAllowed("test") + public String hi() { + return "hi"; + } +} +---- + +== ContractTest + +In this class we test the correctness of our application with Arquillian by creating a war with Contract and ContractImpl classes and deploying to +an embedded TomEE server with the war name test.war. In arquillian.xml we specify that arquillian pick tomcat-users.xml from src/test/conf folder. +In tomcat-users.xml there is a single user with username "tomcat", password="users" and role "test". + +To test we lookup for the ContractImpl and call the hi method using different usernames and passwords. + + +[source,java] +---- +@RunWith(Arquillian.class) +public class ContractTest { + @Deployment(testable = false) + public static Archive app() { + return ShrinkWrap.create(WebArchive.class, "test.war") + .addClasses(Contract.class, ContractImpl.class); + } + + @ArquillianResource + private URL base; + + @Test + public void valid() throws NamingException { + assertEquals("hi", hi(new Properties() {{ + setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); + setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort())); + setProperty(Context.SECURITY_PRINCIPAL, "tomcat"); + setProperty(Context.SECURITY_CREDENTIALS, "users"); + }})); + } + + @Test + public void invalid() throws NamingException { + try { + hi(new Properties() {{ + setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); + setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort())); + setProperty(Context.SECURITY_PRINCIPAL, "tomcat"); + setProperty(Context.SECURITY_CREDENTIALS, "wrong"); + }}); + fail(); + } catch (final AuthenticationException ae) { + // ok + } + } + + @Test + public void missingCredentials() throws NamingException { + try { + hi(new Properties() {{ + setProperty(Context.INITIAL_CONTEXT_FACTORY, RemoteInitialContextFactory.class.getName()); + setProperty(Context.PROVIDER_URL, String.format("http://localhost:%s/tomee/ejb", base.getPort())); + }}); + fail(); + } catch (final EJBAccessException eae) { + // no-op + } + } + + private String hi(final Properties clientConfig) throws NamingException { + return Contract.class.cast(new InitialContext(clientConfig).lookup("java:global/test/ContractImpl!org.superbiz.Contract")).hi(); + } +} +---- + +== Run the application: + + mvn install + All test cases will pass. \ No newline at end of file From 1ddb97442c7ee0b6a424a648c3c84dfba80d4fcf Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 13:35:31 -0200 Subject: [PATCH 08/10] remove md --- examples/multi-jpa-provider-testing/README.md | 281 ------------------ 1 file changed, 281 deletions(-) delete mode 100644 examples/multi-jpa-provider-testing/README.md diff --git a/examples/multi-jpa-provider-testing/README.md b/examples/multi-jpa-provider-testing/README.md deleted file mode 100644 index b24a54dc16c..00000000000 --- a/examples/multi-jpa-provider-testing/README.md +++ /dev/null @@ -1,281 +0,0 @@ -index-group=JPA Providers -type=page -status=published -title=Multiple JPA providers test -~~~~~~ - -This test shows how to use multiple JPA providers, Hibernate and Openjpa. Using JPA annotations the code can be easily used with different implementations. The @Entity class is straight forward, a Person POJO with an id and a name, the persistence.xml creates and drop Person table for both implementations. The examples and implementations dependency are inside test resources, in particularly: arquillian.xml for test purpose, hibernate-pom.xml loads hibernate-core dependencies and openjpa-pom.xml loads openjpa dependencies. The test inside JPATest.java class is executed twice, once for each implementation. - -## @Entity - -Simple POJO class that follows JPA standard - - import javax.persistence.Entity; - import javax.persistence.GeneratedValue; - import javax.persistence.Id; - - @Entity - public class Person { - - @Id - @GeneratedValue - private long id; - - private String name; - - public long getId() { - return id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - } - -## persistence.xml - -Create and drop Person table - - - - jdbc/jpa - - - - - - - - - - -## JPA test - -The entity manager is injected through cdi and an Object Person is created and inserted into the inmemory database - - import org.jboss.arquillian.container.test.api.Deployment; - import org.jboss.arquillian.junit.Arquillian; - import org.jboss.arquillian.transaction.api.annotation.TransactionMode; - import org.jboss.arquillian.transaction.api.annotation.Transactional; - import org.jboss.shrinkwrap.api.ArchivePaths; - import org.jboss.shrinkwrap.api.ShrinkWrap; - import org.jboss.shrinkwrap.api.asset.ClassLoaderAsset; - import org.jboss.shrinkwrap.api.spec.WebArchive; - import org.junit.Test; - import org.junit.runner.RunWith; - import org.superbiz.model.Person; - - import javax.persistence.EntityManager; - import javax.persistence.PersistenceContext; - - import static org.junit.Assert.assertNotNull; - - @RunWith(Arquillian.class) - public class JPATest { - - @Deployment - public static WebArchive war() { - return ShrinkWrap.create(WebArchive.class) - .addClass(Person.class) - .addAsWebInfResource(new ClassLoaderAsset("META-INF/persistence.xml"), ArchivePaths.create("persistence.xml")); - } - - @PersistenceContext - private EntityManager em; - - @Test - @Transactional(TransactionMode.ROLLBACK) - public void persist() { - assertNotNull(em); - - // do something with the em - final Person p = new Person(); - p.setName("Apache OpenEJB"); - em.persist(p); - } - } - -Inside the example there are no reference to the JPA implementations. - -## Test implementations - -The test classes inside org.superbiz.enricher package simply load the implementation libraries and the test runs twice as described inside the pom.xml, a system property variable is used to distinguish between Hibernate and OpenJPA. - -# Running - -Running the example can be done from maven with a simple 'mvn clean install' command run from the 'multi-jpa-provider-testing' directory. - -When run you should see output similar to the following. - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - Running org.superbiz.JPATest - INFO - ******************************************************************************** - INFO - OpenEJB http://tomee.apache.org/ - INFO - Startup: Wed Dec 26 17:55:31 CET 2018 - INFO - Copyright 1999-2018 (C) Apache OpenEJB Project, All Rights Reserved. - INFO - Version: 8.0.0-SNAPSHOT - INFO - Build date: 20181226 - INFO - Build time: 02:26 - INFO - ******************************************************************************** - INFO - openejb.home = /tomee/examples/multi-jpa-provider-testing - INFO - openejb.base = /tomee/examples/multi-jpa-provider-testing - INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@5db45159 - INFO - Succeeded in installing singleton service - INFO - Cannot find the configuration file [conf/openejb.xml]. Will attempt to create one for the beans deployed. - 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 - Using 'openejb.deployments.classpath=false' - INFO - Creating TransactionManager(id=Default Transaction Manager) - INFO - Creating SecurityService(id=Default Security Service) - INFO - Using 'openejb.classloader.forced-load=org.superbiz.model' - INFO - Configuring enterprise application: /tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean 413724ac-4a44-48a3-ae4a-db190b95cc62_org.superbiz.JPATest: Container(type=MANAGED, id=Default Managed Container) - INFO - Creating Container(id=Default Managed Container) - INFO - Using directory /tmp for stateful session passivation - INFO - Configuring PersistenceUnit(name=jpa) - INFO - Configuring Service(id=Default JDBC Database, type=Resource, provider-id=Default JDBC Database) - INFO - Auto-creating a Resource with id 'Default JDBC Database' of type 'DataSource for 'jpa'. - INFO - Creating Resource(id=Default JDBC Database) - INFO - Configuring Service(id=Default Unmanaged JDBC Database, type=Resource, provider-id=Default Unmanaged JDBC Database) - INFO - Auto-creating a Resource with id 'Default Unmanaged JDBC Database' of type 'DataSource for 'jpa'. - INFO - Creating Resource(id=Default Unmanaged JDBC Database) - INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default JDBC Database' from 'jdbc/jpa' - INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default Unmanaged JDBC Database' from 'null' - INFO - Using 'javax.persistence.provider=org.hibernate.ejb.HibernatePersistence' - INFO - Enterprise application "/tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war" loaded. - INFO - Assembling app: /tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war - INFO - HCANN000001: Hibernate Commons Annotations {4.0.2.Final} - INFO - HHH000412: Hibernate Core {4.2.18.Final} - INFO - HHH000206: hibernate.properties not found - INFO - HHH000021: Bytecode provider name : javassist - INFO - HHH000204: Processing PersistenceUnitInfo [ - name: jpa - ...] - INFO - HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider - INFO - HHH000400: Using dialect: org.hibernate.dialect.HSQLDialect - INFO - HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory - INFO - HHH000397: Using ASTQueryTranslatorFactory - INFO - HHH000227: Running hbm2ddl schema export - INFO - HHH000230: Schema export complete - INFO - PersistenceUnit(name=jpa, provider=org.hibernate.ejb.HibernatePersistence) - provider time 1053ms - INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@5db45159 - INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found - INFO - OpenWebBeans Container is starting... - INFO - Adding OpenWebBeansPlugin : [CdiPlugin] - INFO - HV000001: Hibernate Validator 5.1.3.Final - INFO - All injection points were validated successfully. - INFO - OpenWebBeans Container has started, it took 194 ms. - INFO - Deployed Application(path=/tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war) - INFO - Undeploying app: /tomee/examples/multi-jpa-provider-testing/413724ac-4a44-48a3-ae4a-db190b95cc62.war - INFO - HHH000227: Running hbm2ddl schema export - INFO - HHH000230: Schema export complete - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.951 sec - in org.superbiz.JPATest - INFO - Destroying container system - INFO - Closing DataSource: Default JDBC Database - INFO - Closing DataSource: Default Unmanaged JDBC Database - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - - ------------------------------------------------------- - T E S T S - ------------------------------------------------------- - SUREFIRE-859: 57 classpath-bootstrap INFO [main] openjpa.Enhance - You have enabled runtime enhancement, but have not specified the set of persistent classes. OpenJPA must look for metadata for every loaded class, which might increase class load times significantly. - 353 classpath-bootstrap INFO [main] openjpa.Runtime - OpenJPA dynamically loaded a validation provider. - Running org.superbiz.JPATest - INFO - ******************************************************************************** - INFO - OpenEJB http://tomee.apache.org/ - INFO - Startup: Wed Dec 26 17:55:35 CET 2018 - INFO - Copyright 1999-2018 (C) Apache OpenEJB Project, All Rights Reserved. - INFO - Version: 8.0.0-SNAPSHOT - INFO - Build date: 20181226 - INFO - Build time: 02:26 - INFO - ******************************************************************************** - INFO - openejb.home = /tomee/examples/multi-jpa-provider-testing - INFO - openejb.base = /tomee/examples/multi-jpa-provider-testing - INFO - Created new singletonService org.apache.openejb.cdi.ThreadSingletonServiceImpl@4a8a60bc - INFO - Succeeded in installing singleton service - INFO - Cannot find the configuration file [conf/openejb.xml]. Will attempt to create one for the beans deployed. - 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 - Using 'openejb.deployments.classpath=false' - INFO - Creating TransactionManager(id=Default Transaction Manager) - INFO - Creating SecurityService(id=Default Security Service) - INFO - Configuring enterprise application: /tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war - INFO - Configuring Service(id=Default Managed Container, type=Container, provider-id=Default Managed Container) - INFO - Auto-creating a container for bean 450e397e-de39-49eb-837f-7b066fc9f248_org.superbiz.JPATest: Container(type=MANAGED, id=Default Managed Container) - INFO - Creating Container(id=Default Managed Container) - INFO - Using directory /tmp for stateful session passivation - INFO - Configuring PersistenceUnit(name=jpa) - INFO - Configuring Service(id=Default JDBC Database, type=Resource, provider-id=Default JDBC Database) - INFO - Auto-creating a Resource with id 'Default JDBC Database' of type 'DataSource for 'jpa'. - INFO - Creating Resource(id=Default JDBC Database) - INFO - Configuring Service(id=Default Unmanaged JDBC Database, type=Resource, provider-id=Default Unmanaged JDBC Database) - INFO - Auto-creating a Resource with id 'Default Unmanaged JDBC Database' of type 'DataSource for 'jpa'. - INFO - Creating Resource(id=Default Unmanaged JDBC Database) - INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default JDBC Database' from 'jdbc/jpa' - INFO - Adjusting PersistenceUnit jpa to Resource ID 'Default Unmanaged JDBC Database' from 'null' - INFO - Using 'javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl' - INFO - Enterprise application "/tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war" loaded. - INFO - Assembling app: /tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war - INFO - OpenJPA dynamically loaded a validation provider. - INFO - PersistenceUnit(name=jpa, provider=org.apache.openjpa.persistence.PersistenceProviderImpl) - provider time 116ms - INFO - Existing thread singleton service in SystemInstance(): org.apache.openejb.cdi.ThreadSingletonServiceImpl@4a8a60bc - INFO - Some Principal APIs could not be loaded: org.eclipse.microprofile.jwt.JsonWebToken out of org.eclipse.microprofile.jwt.JsonWebToken not found - INFO - OpenWebBeans Container is starting... - INFO - Adding OpenWebBeansPlugin : [CdiPlugin] - INFO - HV000001: Hibernate Validator 5.1.3.Final - INFO - All injection points were validated successfully. - INFO - OpenWebBeans Container has started, it took 170 ms. - INFO - Deployed Application(path=/tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war) - INFO - Starting OpenJPA 3.0.0 - INFO - Using dictionary class "org.apache.openjpa.jdbc.sql.HSQLDictionary" (HSQL Database Engine 2.3.2 ,HSQL Database Engine Driver 2.3.2). - INFO - Connected to HSQL Database Engine version 2.2 using JDBC driver HSQL Database Engine Driver version 2.3.2. - INFO - Undeploying app: /tomee/examples/multi-jpa-provider-testing/450e397e-de39-49eb-837f-7b066fc9f248.war - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.666 sec - in org.superbiz.JPATest - INFO - Destroying container system - INFO - Closing DataSource: Default JDBC Database - INFO - Closing DataSource: Default Unmanaged JDBC Database - - Results : - - Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 - -From the log you can see that both implementations are used: INFO - Using 'javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl', INFO - Using 'javax.persistence.provider=org.hibernate.ejb.HibernatePersistence'. - -## Inside the jar - -If we look at the jar built by maven, we'll see the application itself is quite small: - - jar tvf multi-jpa-provider-testing-8.0.0-SNAPSHOT.jar - 0 Wed Dec 26 17:55:40 CET 2018 META-INF/ - 134 Wed Dec 26 17:55:38 CET 2018 META-INF/MANIFEST.MF - 0 Wed Dec 26 17:55:30 CET 2018 org/ - 0 Wed Dec 26 17:55:30 CET 2018 org/superbiz/ - 0 Wed Dec 26 17:55:30 CET 2018 org/superbiz/model/ - 780 Wed Dec 26 17:55:30 CET 2018 org/superbiz/model/Person.class - 1554 Wed Dec 26 17:55:30 CET 2018 META-INF/persistence.xml - 0 Wed Dec 26 17:55:40 CET 2018 META-INF/maven/ - 0 Wed Dec 26 17:55:40 CET 2018 META-INF/maven/org.superbiz/ - 0 Wed Dec 26 17:55:40 CET 2018 META-INF/maven/org.superbiz/multi-jpa-provider-testing/ - 5696 Wed Dec 26 17:41:54 CET 2018 META-INF/maven/org.superbiz/multi-jpa-provider-testing/pom.xml - 132 Wed Dec 26 17:55:38 CET 2018 META-INF/maven/org.superbiz/multi-jpa-provider-testing/pom.properties - - -Inside the resources package there is only a java class and the persistence.xml and the only dependency is javaee-api:8.0. \ No newline at end of file From d1bf250eb6b2a6fe6e56ce42ab095a230a46f991 Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 13:44:26 -0200 Subject: [PATCH 09/10] Adding to jpa group and converting to adoc --- examples/persistence-fragment/README.adoc | 131 ++++++++++++++++++++++ examples/persistence-fragment/README.md | 130 --------------------- 2 files changed, 131 insertions(+), 130 deletions(-) create mode 100644 examples/persistence-fragment/README.adoc delete mode 100644 examples/persistence-fragment/README.md diff --git a/examples/persistence-fragment/README.adoc b/examples/persistence-fragment/README.adoc new file mode 100644 index 00000000000..d9fac04696c --- /dev/null +++ b/examples/persistence-fragment/README.adoc @@ -0,0 +1,131 @@ += Persistence Fragment +:index-group: JPA +:jbake-type: page +:jbake-status: published + +The JPA provides Java developers with an object/relational mapping facility for managing relational data in Java applications. + +@Entity define the entity class that you want to convert into a table in a database. +@Id define the main key of the table. +@GeneratedValue provides for the specification of generation strategies for the values of primary keys. + +== Movie + +.... +package org.superbiz.injection.jpa; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Movie { + @Id + @GeneratedValue + private long id; + private String director; + private String title; + private int year; + + public Movie() { + // no-op + } + + public Movie(String director, String title, int year) { + this.director = director; + this.title = title; + this.year = year; + } + + public long getId() { + return id; + } + + public String getDirector() { + return director; + } + + public void setDirector(String director) { + this.director = director; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } +} +.... + +== persistence-fragment.xml + + + + org.superbiz.injection.jpa.Movie + true + + + +== MoviesTest + +.... +package org.superbiz.injection.jpa; + +import org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory; +import org.junit.Test; + +import javax.ejb.embeddable.EJBContainer; +import javax.naming.Context; +import javax.persistence.EntityManagerFactory; +import javax.persistence.PersistenceUnit; +import java.util.Properties; + +import static org.junit.Assert.assertTrue; + +public class MoviesTest { + @PersistenceUnit + private EntityManagerFactory emf; + + @Test + public void test() throws Exception { + final Properties p = new Properties(); + p.put("movieDatabase", "new://Resource?type=DataSource"); + p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); + p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); + + final EJBContainer container = EJBContainer.createEJBContainer(p); + final Context context = container.getContext(); + context.bind("inject", this); + + assertTrue(((ReloadableEntityManagerFactory) emf).getManagedClasses().contains(Movie.class.getName())); + + container.close(); + } +} +.... + +== persistence.xml + + + + movieDatabase + movieDatabaseUnmanaged + + + + + diff --git a/examples/persistence-fragment/README.md b/examples/persistence-fragment/README.md deleted file mode 100644 index a1424a93003..00000000000 --- a/examples/persistence-fragment/README.md +++ /dev/null @@ -1,130 +0,0 @@ -index-group=Unrevised -type=page -status=published -title=Persistence Fragment -~~~~~~ - -The JPA provides Java developers with an object/relational mapping facility for managing relational data in Java applications. - -@Entity define the entity class that you want to convert into a table in a database. -@Id define the main key of the table. -@GeneratedValue provides for the specification of generation strategies for the values of primary keys. - -## Movie - - package org.superbiz.injection.jpa; - - import javax.persistence.Entity; - import javax.persistence.GeneratedValue; - import javax.persistence.Id; - - @Entity - public class Movie { - @Id - @GeneratedValue - private long id; - private String director; - private String title; - private int year; - - public Movie() { - // no-op - } - - public Movie(String director, String title, int year) { - this.director = director; - this.title = title; - this.year = year; - } - - public long getId() { - return id; - } - - public String getDirector() { - return director; - } - - public void setDirector(String director) { - this.director = director; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public int getYear() { - return year; - } - - public void setYear(int year) { - this.year = year; - } - } - -## persistence-fragment.xml - - - - org.superbiz.injection.jpa.Movie - true - - - - -## MoviesTest - - package org.superbiz.injection.jpa; - - import org.apache.openejb.assembler.classic.ReloadableEntityManagerFactory; - import org.junit.Test; - - import javax.ejb.embeddable.EJBContainer; - import javax.naming.Context; - import javax.persistence.EntityManagerFactory; - import javax.persistence.PersistenceUnit; - import java.util.Properties; - - import static org.junit.Assert.assertTrue; - - public class MoviesTest { - @PersistenceUnit - private EntityManagerFactory emf; - - @Test - public void test() throws Exception { - final Properties p = new Properties(); - p.put("movieDatabase", "new://Resource?type=DataSource"); - p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); - p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb"); - - final EJBContainer container = EJBContainer.createEJBContainer(p); - final Context context = container.getContext(); - context.bind("inject", this); - - assertTrue(((ReloadableEntityManagerFactory) emf).getManagedClasses().contains(Movie.class.getName())); - - container.close(); - } - } - -## persistence.xml - - - - movieDatabase - movieDatabaseUnmanaged - - - - - - From 44d4053576fc1930f972a919428b1ed3bfaf8d45 Mon Sep 17 00:00:00 2001 From: ivanjunckes Date: Wed, 2 Jan 2019 14:09:04 -0200 Subject: [PATCH 10/10] Fixing bugs with headers --- examples/cdi-alternative-and-stereotypes/README.adoc | 1 - examples/connector-war/README.adoc | 8 +++----- examples/decorators/README.adoc | 7 +++---- examples/simple-mdb/README.adoc | 1 - examples/simple-remote-tomcatusers/README.adoc | 8 +++----- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/examples/cdi-alternative-and-stereotypes/README.adoc b/examples/cdi-alternative-and-stereotypes/README.adoc index 456ff4a2fbb..3b365e1ca24 100644 --- a/examples/cdi-alternative-and-stereotypes/README.adoc +++ b/examples/cdi-alternative-and-stereotypes/README.adoc @@ -1,5 +1,4 @@ = CDI Alternative and Stereotypes - :index-group: CDI :jbake-type: page :jbake-status: published diff --git a/examples/connector-war/README.adoc b/examples/connector-war/README.adoc index 18c654eff19..18e006b6853 100644 --- a/examples/connector-war/README.adoc +++ b/examples/connector-war/README.adoc @@ -1,9 +1,7 @@ -index-group=Java EE Connectors -type=page -status=published - = Connectors in WAR Files - +:index-group: Java EE Connectors +:jbake-type: page +:jbake-status: published == AddInterceptor diff --git a/examples/decorators/README.adoc b/examples/decorators/README.adoc index b2be25f5454..e42967c47c9 100644 --- a/examples/decorators/README.adoc +++ b/examples/decorators/README.adoc @@ -1,8 +1,7 @@ -index-group=CDI -type=page -status=published - = Decorators +:index-group: CDI +:jbake-type: page +:jbake-status: published == AccessDeniedException diff --git a/examples/simple-mdb/README.adoc b/examples/simple-mdb/README.adoc index f0e5d353337..8fe7cb7bee3 100644 --- a/examples/simple-mdb/README.adoc +++ b/examples/simple-mdb/README.adoc @@ -1,5 +1,4 @@ = Simple MDB - :index-group: JMS and MDBs :jbake-type: page :jbake-status: published diff --git a/examples/simple-remote-tomcatusers/README.adoc b/examples/simple-remote-tomcatusers/README.adoc index 642a2a0254c..8242b2d5e9a 100644 --- a/examples/simple-remote-tomcatusers/README.adoc +++ b/examples/simple-remote-tomcatusers/README.adoc @@ -1,12 +1,10 @@ -index-group=Unrevised -type=page -status=published - = Simple Remote Tomcatusers +:index-group: Security +:jbake-type: page +:jbake-status: published This is an example on how to use JNDI with security restrictions in TomEE. - == Contract In our example Contract is an interface annotated with @Remote which indicates that all methods of this interface can be accessed by client code.