[jboss-cvs] JBossAS SVN: r82605 - in projects/ejb3/trunk/docs/tutorial/guide/en: modules and 1 other directory.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Mon Jan 5 02:49:01 EST 2009
Author: jaikiran
Date: 2009-01-05 02:49:00 -0500 (Mon, 05 Jan 2009)
New Revision: 82605
Added:
projects/ejb3/trunk/docs/tutorial/guide/en/modules/embeddable.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/entity.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/extended_pc.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/injection.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/interceptor.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/jndibinding.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb_deployment_descriptor.xml
Modified:
projects/ejb3/trunk/docs/tutorial/guide/en/master.xml
projects/ejb3/trunk/docs/tutorial/guide/en/modules/todo.xml
Log:
Added more tutorials to the guide
Modified: projects/ejb3/trunk/docs/tutorial/guide/en/master.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/master.xml 2009-01-05 04:12:59 UTC (rev 82604)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/master.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -6,6 +6,12 @@
<!ENTITY blob SYSTEM "modules/blob.xml">
<!ENTITY callbacks SYSTEM "modules/callbacks.xml">
<!ENTITY composite SYSTEM "modules/composite.xml">
+<!ENTITY embeddable SYSTEM "modules/embeddable.xml">
+<!ENTITY entity SYSTEM "modules/entity.xml">
+<!ENTITY extended_pc SYSTEM "modules/extended_pc.xml">
+<!ENTITY injection SYSTEM "modules/injection.xml">
+<!ENTITY interceptor SYSTEM "modules/interceptor.xml">
+<!ENTITY jndibinding SYSTEM "modules/jndibinding.xml">
<!ENTITY todo SYSTEM "modules/todo.xml">
]>
<book lang="en">
@@ -19,5 +25,5 @@
<title>Target Audience</title>
<para>This tutorial is meant for EJB3 application developers on JBoss Application Server. The tutorial walks you through the EJB 3.0 features and how they deploy to JBoss. Please check the <xref linkend="Installation">install guide</xref> for system requirements.</para>
</preface>
-&installing;&stateless;&stateful;&blob;&callbacks;&composite;&todo;
+&installing;&stateless;&stateful;&blob;&callbacks;&composite;&embeddable;&entity;&extended_pc;&injection;&interceptor;&jndibinding;&todo;
</book>
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/embeddable.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/embeddable.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/embeddable.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,89 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="Embeddable Objects in EJB3 Entities">
+ <title>Introduction to embedding objects in EJB3 entities</title>
+ <para>
+ The EJB3 specification allows you to embed plain Java objects within your entities
+ and map the properties of this embedded value object to columns within the entity's
+ table.
+ </para>
+
+ <para>
+ The <literal>org.jboss.tutorial.embeddable.bean.Customer</literal> entity encapsulates the name of the customer
+ in the <literal>org.jboss.tutorial.embeddable.bean.Name</literal> value object. The
+ <literal>org.jboss.tutorial.embeddable.bean.Name</literal> value object must be tagged with the <literal>@Embeddable</literal>
+ annotation.
+
+ <programlisting>
+ <![CDATA[
+ at Embeddable
+public class Name implements java.io.Serializable
+ ]]>
+ </programlisting>
+
+ The properties of Name must then be mapped to columns within Customer's table.
+
+ <programlisting>
+ <![CDATA[
+ at Embedded
+ at AttributeOverrides({
+ @AttributeOverride(name = "first", column = {@Column(name = "FIRST_NAME")}),
+ @AttributeOverride(name = "last", column = {@Column(name = "LAST_NAME")})
+})
+public Name getName()
+{
+ return name;
+}
+ ]]>
+ </programlisting>
+ </para>
+
+ <sect5>
+Building and Running
+ </sect5>
+
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] Create Bill Burke and Monica Smith
+ [java] Bill and Monica get married
+ [java] Get all the Burkes
+ [java] There are now 2 Burkes
+ ]]>
+ </programlisting>
+
+ <sect5>
+Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+
+ <sect5>
+View the tables and rows:
+ </sect5>
+ <para>
+ You can view the tables created by JBoss by going to the
+ <ulink url="http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB">Hypersonic Service</ulink>,
+ scrolling down to the <literal>startDatabaseManager</literal> button and clicking it.
+ A Hypersonic SQL window will be minimized, but you can open it up to look at the tables and do queries.
+
+ </para>
+
+</chapter>
\ No newline at end of file
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/entity.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/entity.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/entity.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,221 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="EJB3 Entities">
+ <title>Introduction to Entities in EJB3</title>
+ <para>
+ Entity Beans of EJB2.x have been given a complete overhaul in EJB 3.0.
+ Entity beans (or Entities, as they are now called) are plain Java objects that can be allocated
+ with <literal>new</literal> and attached/detached/reattached to persistence storage.
+ Entities are not remotable and must be accessed through the new <literal>javax.persistence.EntityManager</literal> service.
+ JBoss's EJB 3.0 entity implementation is built on top of Hibernate.
+ </para>
+
+ <sect5>
+ O/R Mapping :
+ </sect5>
+ <para>
+ First let's look at the example implementation of two related Entities.
+ <literal>org.jboss.tutorial.entity.bean.Order</literal> and <literal>org.jboss.tutorial.entity.bean.LineItem</literal>.
+ These two entities form a one-to-many relationship.
+ </para>
+
+ <para>
+ The persistence determines the persistent properties by looking for all getter/setter method pairs.
+ By default, all getter/setter methods will be treated as persistence properties.
+ </para>
+
+ <para>
+ Defining an Entity is easy. First, annotate the class as an <literal>@Entity</literal>. In the minimum, you must at
+ least define a primary key field using the <literal>@Id</literal> annotation.
+
+ <programlisting>
+ <![CDATA[
+ at Id @GeneratedValue
+public int getId()
+{
+ return id;
+}
+ ]]>
+ </programlisting>
+ <note>
+ <para>
+ Annotations must be defined on the getter method or on the field. However, you cannot have a mix of annotations
+ on the field and on the methods. The following example where we are mapping the <literal>name</literal> through
+ the field and mapping the <literal>age</literal> through the method is not allowed:
+
+ <programlisting>
+ <![CDATA[
+ at Entity
+public class Employee implements java.io.Serializable
+{
+
+ @Id
+ @GeneratedValue(strategy=GenerationType.AUTO)
+ private long id;
+
+ @Column (name="NAME")
+ private String name;
+
+ private int age;
+
+ @Column (name="AGE")
+ public int getAge()
+ {
+ return this.age
+ }
+
+ public String getName()
+ {
+
+ }
+ // other getter/setters
+}
+ ]]>
+ </programlisting>
+ </para>
+
+ </note>
+
+ The <literal>@Id</literal> annotation tells the container that <literal>id</literal> is the primary key property.
+ The <literal>@GeneratedValue</literal> tells that it should be automatically generated by the container.
+ The table name is specified using the <literal>@Table</literal> annotation
+
+ <programlisting>
+ <![CDATA[
+ at Table(name = "PURCHASE_ORDER")
+ ]]>
+ </programlisting>
+
+ If the table name isn't specified it defaults to the simple name of the class. For instance, the LineItem entity would be
+ mapped to the LINEITEM table.
+ </para>
+
+ <sect5>
+ One to Many Relationship :
+ </sect5>
+ <para>
+ The Order bean also defines a one to many relationship.
+
+ <programlisting>
+ <![CDATA[
+ at OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy="order")
+public Collection<LineItem> getLineItems()
+{
+ return lineItems;
+}
+ ]]>
+ </programlisting>
+ Generics must be used so that the container can determine what the entity Order is related to.
+ <para>
+ <literal>CascadeType.ALL</literal> specifies that when an Order is created, any LineItems held in the <literal>lineItems</literal>
+ collection will be created as well (<literal>CascadeType.PERSIST</literal>). If the Order is deleted from persistence storage,
+ all related LineItems will be deleted (<literal>CascadeType.REMOVE</literal>). If an Order instance is reattached to persistence
+ storage, any changes to the LineItems collection will be merged with persistence storage (<literal>CascadeType.MERGE</literal>).
+ </para>
+
+ <para>
+ <literal>FetchType.EAGER</literal> specifies that when the Order is loaded whether or not to pre-fetch the relationship as well.
+ If you want the LineItems to be loaded on demand, then specify <literal>FetchType.LAZY</literal>.
+ </para>
+
+ <para>
+ The <literal>mappedBy</literal> attribute specifies that this is a bi-directional relationship that is managed by the order property
+ on the LineItem entity.
+ </para>
+
+ </para>
+
+ <sect5>
+ Many to One Relationship :
+ </sect5>
+ <para>
+ <programlisting>
+ <![CDATA[
+ at ManyToOne
+ at JoinColumn(name = "order_id")
+public Order getOrder()
+{
+ return order;
+}
+ ]]>
+ </programlisting>
+
+ The <literal>@JoinColumn</literal> specifies the foreign key column within the LineItem table.
+
+ </para>
+
+ <sect5>
+ EntityManager :
+ </sect5>
+ <para>
+ The <literal>org.jboss.tutorial.entity.bean.ShoppingCartBean</literal> allocates and stores all instances
+ of Orders and LineItems. If you look at the example you can see that ShoppingCart interacts with Order as a plain Java object.
+ It allocates it with <literal>new</literal>. It can pass the Order back to the client. The <literal>checkout()</literal>
+ method actually stores it with persistence storage by using the required EntityManager service.
+
+ The EntityManager service is injected using field injection and the <literal>@PersistenceContext</literal> annotation.
+ <programlisting>
+ <![CDATA[
+ at PersistenceContext
+private EntityManager manager;
+
+ ]]>
+ </programlisting>
+
+ The EntityManager is central to EJB 3.0 as there are no homes. The EntityManager is used to do querying, creating,
+ find by primary key, and removal of entities in EJB3.
+ </para>
+
+ <sect5>
+Building and Running
+ </sect5>
+
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] Buying 2 memory sticks
+ [java] Buying a laptop
+ [java] Print cart:
+ [java] Total: $3000.0
+ [java] 2 Memory stick 1000.0
+ [java] 1 Laptop 2000.0
+ [java] Checkout
+
+ ]]>
+ </programlisting>
+
+ <sect5>
+Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+
+ <sect5>
+View the tables and rows:
+ </sect5>
+ <para>
+ You can view the tables created by JBoss by going to the
+ <ulink url="http://localhost:8080/jmx-console/HtmlAdaptor?action=inspectMBean&name=jboss%3Aservice%3DHypersonic%2Cdatabase%3DlocalDB">Hypersonic Service</ulink>,
+ scrolling down to the <literal>startDatabaseManager</literal> button and clicking it.
+ A Hypersonic SQL window will be minimized, but you can open it up to look at the tables and do queries.
+
+ </para>
+
+</chapter>
\ No newline at end of file
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/extended_pc.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/extended_pc.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/extended_pc.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,163 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="Extended Persistence Contexts">
+ <title>Introduction to Extended Persistence Contexts</title>
+ <para>
+ Usually, an EntityManager in JBoss EJB 3.0 lives and dies within a JTA transaction. Once the transaction is finished,
+ all persistent objects are detached from the EntityManager and are no longer managed.
+ Any local caching the EntityManager instance had done is lost. JBoss EJB 3.0 allows you to define long-living EntityManagers
+ that live beyond the scope of a JTA transaction. This is called an Extended Persistence Context.
+
+ When you specify that an injected EntityManager is an extended persistence context, all object instances remain managed.
+
+ </para>
+
+ <para>
+ Extended persistence contexts can only be used within Stateful session beans. Take a look at
+ <literal>org.jboss.tutorial.extended.bean.ShoppingCartBean</literal>.
+
+ <programlisting>
+ <![CDATA[
+ at Stateful
+ at Remote(ShoppingCart.class)
+public class ShoppingCartBean implements ShoppingCart
+{
+ @PersistenceContext(type=PersistenceContextType.EXTENDED)
+ EntityManager em;
+
+ @EJB StatelessLocal stateless;
+
+ private Customer customer;
+
+ public long createCustomer()
+ {
+ customer = new Customer();
+ customer.setName("William");
+ em.persist(customer);
+ return customer.getId();
+ }
+
+ public void update()
+ {
+ customer.setName("Bill");
+ }
+...
+}
+
+ ]]>
+ </programlisting>
+
+ To inject an extended persistence context, you use the <literal>type()</literal> attribute and set it to <literal>EXTENDED</literal>.
+ If you look at the <literal>createCustomer()</literal> method you notice that it is persisting a <literal>Customer</literal> object
+ and storing a reference to that created object within a member variable of the stateful bean. When the update() method is called,
+ you see that the customer's state is modified. Since the entity manager used is EXTENDED, the customer member variable remains
+ managed by the entitymanager and the modified state will be synchronized with the database.
+
+ </para>
+
+ <sect5>
+ Conversations :
+ </sect5>
+
+ <para>
+ An even more interesting use case is when you combine extended persistence contexts with non-transactional methods.
+ If you interact with an extended persistence context outside of a transaction, the inserts, updates, and deletes
+ will be queued until you access the persistence context within a transaction. This means that any persist(), merge(),
+ or remove() method you call will not actually result in a JDBC execution and thus an update of the database until
+ you manually call EntityManager.flush().
+ <para>
+ Why is this useful? Consider the usecase of a Setup Wizard on a website. The Wizard has seven steps, seven web pages to enter
+ stuff in. It is extremely unwise to have a JTA transaction that spans multiple http requests, yet you do not want to commit
+ anything to the database until all steps are complete. Your code can interact with the EntityManager as it wants and you
+ do not have to worry about updates or writing a lot of gluecode in your application to do all the entity manager's work in the
+ final step of the wizard. Efficient and highly performant. Because the managed persistent objects remain attached to the
+ persistent context, all optmistic versioning checks can also be maintained within the application transaction.
+ Here's an example on how to do this.
+
+ <programlisting>
+ <![CDATA[
+ at Stateful
+ at Remote(ShoppingCart.class)
+public class ShoppingCartBean implements ShoppingCart
+{
+ @PersistenceContext(type=PersistenceContextType.EXTENDED)
+ EntityManager em;
+
+ @EJB StatelessLocal stateless;
+
+ private Customer customer;
+
+ public long createCustomer()
+ {
+ customer = new Customer();
+ customer.setName("William");
+ em.persist(customer);
+ return customer.getId();
+ }
+
+ @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
+ public void never()
+ {
+ customer.setName("Bob");
+ }
+
+
+
+ @Remove
+ public void checkout()
+ {
+ }
+}
+
+ ]]>
+ </programlisting>
+ </para>
+ Calling the never() method will update the managed customer object reference, but will not result in a database update until
+ checkout() is called. The spec requires that any time you invoke a transactional method of a stateful bean,
+ that the EntityManager join the transaction. Therefore, our never() update will be committed at the end of the checkout() method
+ (which by default has the REQUIRED trasaction attribute).
+
+ </para>
+
+ <sect5>
+Building and Running
+ </sect5>
+
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] Created customer: William
+ [java] Customer's name should still be William as pc was not yet flushed: Customer.getName() == William
+ [java] Now that the pc has been flushed name should be 'Bob': Customer.getName() == Bob
+ [java] Created customer: William
+ [java] ShoppingCartBean.customer should stay managed because we're in an extended PC: Customer.getName() == Bill
+ [java] Extended persistence contexts are propagated to nested EJB calls: Customer.getName() == Bill Jr.
+
+ ]]>
+ </programlisting>
+
+ <sect5>
+Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+
+
+</chapter>
\ No newline at end of file
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/injection.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/injection.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/injection.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,127 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="Dependency Injection">
+ <title>Introduction to dependency injection</title>
+ <para>
+ To facilitate test driven development, the EJB 3.0 specification allows you to use annotations to inject
+ dependencies through annotations on fields or setter methods. Instead of complicated XML ejb-refs or resource refs,
+ you can use the <literal>@EJB</literal> and <literal>@Resource</literal> annotations to set the value of a
+ field or to call a setter method within your session bean with anything registered within JNDI.
+ You can use the <literal>@EJB</literal> annotation to inject EJB references and <literal>@Resource</literal> to access datasources.
+ </para>
+
+ <para>
+ Open up <literal>org.jboss.tutorial.injection.bean.ShoppingCartBean</literal>.
+ ShoppingCartBean uses the Calculator stateless session EJB to do calculations. The example shows two ways to get access
+ to the Calculator EJB. One is:
+
+ <programlisting>
+ <![CDATA[
+ at EJB
+private Calculator calculator;
+ ]]>
+ </programlisting>
+
+ When the ShoppingCartBean instance is created, the EJB container will set the calculator field using the jndiName
+ of that particular referenced EJB.
+ </para>
+
+ <para>
+ You are not limited to injecting dependencies on fields. You can also use @EJB on a setter method. The below example from
+ ShoppingCartBean uses the <literal>@EJB</literal> annotation to inject the reference to the Calculator session bean:
+
+ <programlisting>
+ <![CDATA[
+private Calculator set;
+
+ at EJB(beanName="org.jboss.tutorial.injection.bean.CalculatorBean")
+public void setCalculator(Calculator c)
+{
+ set = c;
+}
+
+ ]]>
+ </programlisting>
+ </para>
+
+ <para>
+ The <literal>@javax.annotation.Resource</literal> annotation allows you to inject resources.
+
+ <programlisting>
+ <![CDATA[
+ at Resource(mappedName="DefaultDS")
+private javax.sql.DataSource ds;
+ ]]>
+ </programlisting>
+
+ <note>
+ <para>
+ In JBoss, whenever the mappedName() attribute is specified (with @Resource, @EJB), JBoss will use that as the GLOBAL jndi name to look it up.
+ </para>
+ </note>
+
+ The @Resource annotation is used to inject these singletons as well:
+
+ <programlisting>
+ <![CDATA[
+ at Resource
+javax.ejb.SessionContext ctx;
+
+ at Resource
+javax.ejb.TimerService timer;
+
+ at Resource
+javax.ejb.UserTransaction ut;
+
+ ]]>
+ </programlisting>
+
+ </para>
+
+ <para>
+ <literal>@EJB</literal> and <literal>@Resource</literal> also create an entry within the JNDI ENC of the bean. So, the above @EJB
+ injection will create an entry for the reference calculator bean under "java:comp/env/ejb/calculator".
+ </para>
+
+ <sect5>
+Building and Running
+ </sect5>
+
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] Buying 1 memory stick
+ [java] Buying another memory stick
+ [java] Buying a laptop
+ [java] Print cart:
+ [java] 2 Memory stick
+ [java] 1 Laptop
+ [java] Checkout
+
+ ]]>
+ </programlisting>
+
+ <sect5>
+Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+
+</chapter>
\ No newline at end of file
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/interceptor.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/interceptor.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/interceptor.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,978 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="EJB3 Interceptors">
+ <title>Introduction to EJB3 Interceptors</title>
+ <para>
+ The EJB 3.0 spec defines the ability to apply custom made interceptors
+ to the business methods
+ of your session and message driven beans. EJB
+ 3.0 interceptors take the form of methods annotated with
+ the
+ <literal>@javax.ejb.AroundInvoke</literal>
+ annotation. These methods must have the following signature:
+
+ <programlisting>
+ <![CDATA[
+ at javax.ejb.AroundInvoke
+public Object <Arbitrary method name>(javax.ejb.InvocationContext ctx) throws java.lang.Exception
+
+ ]]>
+ </programlisting>
+
+ <note>
+ <para>
+ You can apply interceptors to JBoss specific @Service and
+ @Consumer beans
+ </para>
+ </note>
+
+ You can either define an interceptor method in the bean class itself,
+ or in separate classes.
+ There can only be one interceptor method per
+ class.
+ </para>
+
+ <sect5>
+ Interceptor method in bean class :
+ </sect5>
+
+ <para>
+ Take a look at
+ <literal>org.jboss.tutorial.interceptor.bean.EmailMDB
+ </literal>
+ . It contains this method:
+
+ <programlisting>
+ <![CDATA[
+ at AroundInvoke
+public Object mdbInterceptor(InvocationContext ctx) throws Exception
+{
+ System.out.println("*** Intercepting call to EmailMDB.mdbInterceptor()");
+ return ctx.proceed();
+}
+ ]]>
+ </programlisting>
+
+ This method will wrap the call to EmailMDB.onMessage(). The call to
+ ctx.proceed() causes the next object in the chain of
+ interceptors to
+ get invoked. At the end of the chain of interceptors, the actual bean
+ method gets called.
+ <para>
+ Similarly
+ <literal>org.jboss.tutorial.interceptor.bean.EmailSystemBean
+ </literal>
+ has a method annotated with
+ <literal>@AroundInvoke</literal>
+
+ <programlisting>
+ <![CDATA[
+ at AroundInvoke
+public Object myBeanInterceptor(InvocationContext ctx) throws Exception
+{
+ if (ctx.getMethod().getName().equals("emailLostPassword"))
+ {
+ System.out.println("*** EmailSystemBean.myBeanInterceptor - username: " + ctx.getParameters()[0]);
+ }
+
+ return ctx.proceed();
+}
+
+ ]]>
+ </programlisting>
+ </para>
+ </para>
+
+ <sect5>
+ External interceptors :
+ </sect5>
+
+ <para>
+ The rest of this example will be looking at adding interceptors
+ external to the bean class, more specifically to
+ <literal>EmailSystemBean</literal>
+ . Interceptors can be bound in three different ways:
+ <itemizedlist mark="opencircle">
+ <listitem>
+ <para>
+ Default
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Class level
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Method level
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ An external interceptor instance follows the lifecycle of the target
+ bean instance.
+ </para>
+
+ <sect5>
+ Default interceptors :
+ </sect5>
+
+ <para>
+ We will see how class and method-level interceptors can be bound to a
+ bean or a bean's method using annotations or xml.
+ Default interceptors
+ can only be bound via xml. A Default interceptor is an interceptor
+ that is invoked whenever a business method
+ is invoked on any bean
+ within the deployment.
+ <para>
+ <literal>org.jboss.tutorial.interceptor.bean.DefaultInterceptor
+ </literal>
+ defines an
+ <literal>@AroundInvoke</literal>
+ method with the required method signature.
+
+ <programlisting>
+ <![CDATA[
+ at AroundInvoke
+public Object intercept(InvocationContext ctx) throws Exception
+{
+ System.out.println("*** DefaultInterceptor intercepting " + ctx.getMethod().getName());
+ try
+ {
+ return ctx.proceed();
+ }
+ finally
+ {
+ System.out.println("*** DefaultInterceptor exiting");
+ }
+}
+
+ ]]>
+ </programlisting>
+
+ As mentioned, default interceptors can only be applied via xml. In
+ <literal>META-INF/ejb-jar.xml</literal>
+ we have the following:
+
+ <programlisting>
+ <![CDATA[
+<assembly-descriptor>
+ <!-- Default interceptor that will apply to all methods for all beans in deployment -->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>
+ </interceptor-binding>
+ ...
+</assembly-descriptor>
+
+ ]]>
+ </programlisting>
+
+ Using <literal>*</literal> for the ejb-name says that <literal>DefaultInterceptor</literal> is a default interceptor,
+ i.e. it should intercept all calls to all beans within the deployment unit. We could have added more
+ <literal>interceptor-class</literal> entries to bind more interceptors, as shown here:
+
+ <programlisting>
+ <![CDATA[
+<assembly-descriptor>
+ <!-- Default interceptor that will apply to all methods for all beans in deployment -->
+ <interceptor-binding>
+ <ejb-name>*</ejb-name>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.AnotherInterceptor</interceptor-class>
+ </interceptor-binding>
+ ...
+</assembly-descriptor>
+
+ ]]>
+ </programlisting>
+ In this case <literal>DefaultInterceptor</literal> would be invoked before <literal>AnotherInterceptor</literal>.
+
+ </para>
+ </para>
+
+ <sect5>
+ Class-level interceptors :
+ </sect5>
+
+ <para>
+ Class-level interceptors can be bound using xml or annotations.
+ <sect5>
+ Class-level using annotations :
+ </sect5>
+ <para>
+ <literal>org.jbos.tutorial.interceptor.EmailSystemBean</literal> has been annotated:
+
+ <programlisting>
+ <![CDATA[
+ at Stateless
+ at Interceptors ({TracingInterceptor.class})
+public class EmailSystemBean
+{
+ ...
+}
+
+ ]]>
+ </programlisting>
+ This says that the <literal>@AroundInvoke</literal> annotated method of <literal>org.jboss.tutorial.interceptor.bean.TracingInterceptor</literal> should wrap all calls
+ to <literal>EmailSystemBean</literal>'s business methods. The <literal>@Interceptors</literal> annotation can take an
+ array of classes, so you can bind more than one class-level interceptor this way, e.g.
+ <programlisting>
+ <![CDATA[
+ at Stateless
+ at Interceptors ({TracingInterceptor.class, SomeInterceptor.class})
+public class EmailSystemBean
+{
+ ...
+}
+
+ ]]>
+ </programlisting>
+
+ </para>
+
+ <sect5>
+ Class-level using xml :
+ </sect5>
+ <para>
+ In the <literal>META-INF/ejb-jar.xml</literal> we have the following:
+
+ <programlisting>
+ <![CDATA[
+<assembly-descriptor>
+ ...
+ <!-- Class interceptor that will apply to all methods for EmailSystemBean -->
+ <interceptor-binding>
+ <ejb-name>EmailSystemBean</ejb-name>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.OtherInterceptor</interceptor-class>
+ </interceptor-binding>
+ ...
+</assembly-descriptor>
+
+ ]]>
+ </programlisting>
+
+ Note that here we are specifying the ejb-name of the bean we want to apply the interceptor to.
+ Hence, the <literal>@AroundInvoke</literal> annotated method of <literal>org.jboss.tutorial.interceptor.bean.OtherInterceptor</literal>
+ will wrap all calls to <literal>EmailSystemBean</literal>'s business methods.
+ </para>
+
+ </para>
+
+ <sect5>
+ Method-level interceptors :
+ </sect5>
+
+ <para>
+ Just as we can define default and class-level interceptors, we can also bind an interceptor to a particular business method
+ of a bean
+ <sect5>
+ Method-level using annotations :
+ </sect5>
+ <para>
+ <literal>org.jboss.tutorial.interceptor.bean.EmailSystemBean</literal>'s <literal>sendBookingConfirmationMessage()</literal>
+ method has been annotated with the @Interceptors annotation specifying interceptors that will intercept when this perticular
+ method is invoked.
+ <programlisting>
+ <![CDATA[
+ at Interceptors({AccountsConfirmInterceptor.class})
+public void sendBookingConfirmationMessage(long orderId)
+{
+ ...
+}
+
+ ]]>
+ </programlisting>
+
+ Method-level interceptors are in addition to default and class-level interceptors, meaning that when we call
+ <literal>EmailSystemBean.sendBookingConfirmationMessage()</literal> we get intercepted by
+
+ <itemizedlist mark="opencircle">
+ <listitem>
+ <para>
+ DefaultInterceptor (default)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ TracingInterceptor (class-level)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ OtherInterceptor (class-level)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ AccountsConfirmInterceptor (method-level)
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ An interceptor method can choose to abort an invocation, by not calling
+ <literal>InvocationContext.proceed()</literal> as is done in <literal>AccountConfirmInterceptor</literal>'s interceptor method
+ when a confirmation already exists.
+ </para>
+
+ <sect5>
+ Method-level using xml :
+ </sect5>
+ <para>
+ We can also bind interceptors to a single business method within a bean using xml.
+ But first let's define an interceptor using xml. All the examples we have looked at so far have used the <literal>@AroundInvoke</literal>
+ annotation to mark the interceptor methods. In <literal>META-INF/ejb-jar.xml</literal> we have the following:
+ <programlisting>
+ <![CDATA[
+<interceptors>
+ <interceptor>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
+ <around-invoke>
+ <method-name>sendCancelMessage</method-name>
+ </around-invoke>
+ ...
+
+ </interceptor>
+</interceptors>
+
+ ]]>
+ </programlisting>
+ This tells us that the <literal>sendCancelMessage()</literal> method of <literal>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</literal>
+ is the interceptor method of this interceptor class. To bind interceptors to a particular method using xml, is much the same as how
+ this was done for class-level interceptors apart from that we specify the <literal>method-name</literal> of the method we want to intercept.
+ From our <literal>META-INF/ejb-jar.xml</literal>:
+ <programlisting>
+ <![CDATA[
+ <assembly-descriptor>
+ ...
+ <!-- Method interceptor will apply to sendBookingCancellationMessage for EmailSystemBean -->
+ <interceptor-binding>
+ <ejb-name>EmailSystemBean</ejb-name>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
+ <method>
+ <method-name>sendBookingCancellationMessage</method-name>
+ </method>
+ </interceptor-binding>
+
+ ...
+ </assembly-descriptor>
+
+ ]]>
+ </programlisting>
+ In the case of overloaded methods, we can further narrow down the method by specifying the method parameters, as in this example:
+ <programlisting>
+ <![CDATA[
+<assembly-descriptor>
+ ...
+ <!-- Method interceptor will apply to sendBookingCancellationMessage for EmailSystemBean -->
+ <interceptor-binding>
+ <ejb-name>SomeBean</ejb-name>
+ <interceptor-class>SomeInterceptor</interceptor-class>
+ <method>
+ <method-name>methodWithParam</method-name>
+ <method-params>
+ <method-param>int</method-param>
+ <method-param>java.lang.String[]</method-param>
+ </method-params>
+ </method>
+ </interceptor-binding>
+</assembly-descriptor>
+
+ ]]>
+ </programlisting>
+ <literal>SomeInterceptor</literal> will only get applied to the method of <literal>SomeBean</literal> that matches the signature,
+ i.e. <literal>methodWithParam(int, java.lang.String[])</literal>
+ </para>
+
+ </para>
+
+ <sect5>
+ Exclusion of default and class interceptors :
+
+ <para>
+ For some beans we may want to exclude the default interceptors configured for the deployment, and for some methods
+ within a bean class we may want to exclude the class interceptors for the bean (and/or the default interceptors)
+
+ <sect5>
+ Annotations :
+
+ <para>
+ The <literal>@javax.ejb.ExcludeDefaultInterceptors</literal> annotation can be applied to a bean class or a method.
+ If applied to a bean class, default interceptors will not get invoked for any of that bean class's methods. If applied
+ to a bean business method, default interceptors will not get invoked when calling that method.
+ </para>
+
+ <para>
+ The <literal>@javax.ejb.ExcludeClassInterceptors</literal> annotation can be applied to a bean method. When this annotation
+ is used class-level interceptors will not get invoked when calling that method.
+
+ </para>
+
+ <para>
+ <literal>org.jboss.tutorial.interceptor.bean.EmailMDB</literal> defines
+
+ <programlisting>
+ <![CDATA[
+ at ExcludeDefaultInterceptors
+public class EmailMDB implements MessageListener
+{
+ ...
+}
+
+ ]]>
+ </programlisting>
+ so <literal>DefaultInterceptor</literal> is not invoked when invoking the <literal>EmailMDB.onMessage()</literal>
+ </para>
+
+ <para>
+ <literal>org.jboss.tutorial.interceptor.bean.EmailSystemBean</literal>'s <literal>noop</literal> method is annotated with both
+ <literal>@ExcludeClassInterceptors</literal> and <literal>@ExcludeDefaultInterceptors</literal> and so will not get intercepted
+ by any of these.
+
+ <programlisting>
+ <![CDATA[
+ at ExcludeClassInterceptors
+ at ExcludeDefaultInterceptors
+public void noop()
+{
+ System.out.println("<In EmailSystemBean.noop business method");
+ System.out.println("Exiting EmailSystemBean.noop business method>");
+}
+
+ ]]>
+ </programlisting>
+ </para>
+ </sect5>
+
+ <sect5>
+ XML :
+
+ <para>
+ We can also exclude class and method-level interceptors within an <literal>interceptor-binding</literal> by specifying the
+ <literal>exclude-class-interceptors</literal> and <literal>exclude-default-interceptors</literal> elements.
+
+ <programlisting>
+ <![CDATA[
+<assembly-descriptor>
+ ...
+
+ <interceptor-binding>
+ <ejb-name>EmailSystemBean</ejb-name>
+ <exclude-default-interceptors>true</exclude-default-interceptors>
+ <exclude-class-interceptors>true</exclude-class-interceptors>
+ <method>
+ <method-name>noop2</method-name>
+ </method>
+ </interceptor-binding>
+ ...
+</assembly-descriptor>
+ ]]>
+ </programlisting>
+ </para>
+ </sect5>
+
+ </para>
+ </sect5>
+
+ <sect5>
+ Inheritance Ordering :
+
+ <para>
+ If an interceptor (or bean class) inherits from another class which has a method declared to be an interceptor method,
+ the interceptor methods from the super class will be invoked first. However, if the interceptor method in the superclass
+ has been overridden (regardless of if the overriding method is declared to be an interceptor method or not) the superclass
+ method is not invoked.
+ </para>
+
+ <para>
+ Both <literal>org.jboss.tutorial.interceptor.bean.AccountsConfirmInterceptor</literal> and
+ <literal>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</literal> inherit from
+ <literal>org.jboss.tutorial.interceptor.bean.AccountsInterceptor</literal>.
+ </para>
+
+ <para>
+ AccountsInterceptor declares the following interceptor method:
+
+ <programlisting>
+ <![CDATA[
+ at AroundInvoke
+public Object intercept(InvocationContext ctx) throws Exception
+{
+ System.out.println("*** AccountsInterceptor intercepting " + ctx.getMethod().getName());
+ try
+ {
+ return ctx.proceed();
+ }
+ finally
+ {
+ System.out.println("*** AccountsInterceptor exiting");
+ }
+}
+
+ ]]>
+ </programlisting>
+ This method is overridden by <literal>AccountsConfirmInterceptor</literal>, even though it is not <literal>AccountsConfirmInterceptor</literal>'s
+ interceptor method:
+
+ <programlisting>
+ <![CDATA[
+public class AccountsConfirmInterceptor extends AccountsInterceptor
+{
+ ...
+ public Object intercept(InvocationContext ctx) throws Exception
+ {
+ //overrides AccountsInterceptor.intercept() so that will not be invoked
+ return null;
+ }
+
+
+ @AroundInvoke
+ public Object sendConfirmMessage(InvocationContext ctx) throws Exception
+ {
+ ...
+ }
+}
+ ]]>
+ </programlisting>
+ So when invoking <literal>AccountsConfirmInterceptor</literal>, we simply invoke its <literal>sendConfirmMessage()</literal> method.
+ <literal>AccountsCancelInterceptor</literal>, on the other hand, does not override <literal>AccountsInterceptor.intercept()</literal>,
+ so when invoking <literal>AccountsCancelInterceptor</literal>, we first get intercepted by <literal>AccountsInterceptor.intercept()</literal>
+ followed by <literal>AccountsCancelInterceptor.sendCancelMessage()</literal>.
+
+ </para>
+
+ </sect5>
+
+ <sect5>
+ Injection in interceptors:
+ <sect5>
+ Using Annotations :
+ <para>
+ Just like a bean class, an interceptor can be the target of dependency injection (see the "injection" tutorial for
+ details about injection). The format for how this works is the same, and the injection works off the same ENC as
+ the bean to which the interceptor is bound.
+ </para>
+ <para>
+ <literal>org.jboss.tutorial.interceptor.bean.AccountsConfirmInterceptor</literal> has dependency injection set up using annotations:
+ <programlisting>
+ <![CDATA[
+public class AccountsConfirmInterceptor extends AccountsInterceptor
+{
+ @Resource(mappedName="java:ConnectionFactory")
+ QueueConnectionFactory cf;
+
+ @Resource(mappedName="queue/tutorial/accounts")
+ Queue queue;
+
+ @PersistenceContext
+ EntityManager em;
+
+ ...
+
+ ]]>
+ </programlisting>
+ </para>
+ Remember that interceptors follow the same lifecycle as the bean they are bound to. The interceptors are created at the same
+ time as the bean instance is created, and dependecy injection occurs before the first business method is called. In the example
+ just shown, the container:
+ <itemizedlist mark="opencircle">
+ <listitem>
+ <para>
+ Looks up <literal>java:ConnectionFactory</literal>, binds it in the ENC and injects this into the field <literal>cf</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Looks up <literal>queue/tutorial/accounts</literal>, binds it in the ENC and injects this into the field <literal>queue</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Obtains the default EntityManager and injects this into the field <literal>em</literal>
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect5>
+
+ <sect5>
+ Using XML :
+ <para>
+ Injection, into interceptors, can also be configured via xml, using the traditional <literal>ejb-ref</literal>, <literal>ejb-local-ref</literal>,
+ <literal>resource-ref</literal>, <literal>resource-env-ref</literal> etc. which bind the global names. The only difference
+ from beans is that we put this into the {{interceptors}} element defining the interceptor.
+ <programlisting>
+ <![CDATA[
+<interceptors>
+ <interceptor>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
+ <around-invoke>
+ <method-name>sendCancelMessage</method-name>
+ </around-invoke>
+ <resource-ref>
+ <res-ref-name>jms/ConnFactory</res-ref-name>
+ <res-type>javax.jms.QueueConnectionFactory</res-type>
+ <res-auth>Container</res-auth>
+ <mapped-name>java:/ConnectionFactory</mapped-name>
+ <injection-target>
+ <injection-target-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</injection-target-class>
+ <injection-target-name>cf</injection-target-name>
+ </injection-target>
+ </resource-ref>
+ <resource-env-ref>
+ <resource-env-ref-name>accountsQueue</resource-env-ref-name>
+ <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
+ <mapped-name>queue/tutorial/accounts</mapped-name>
+ <injection-target>
+ <injection-target-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</injection-target-class>
+ <injection-target-name>queue</injection-target-name>
+ </injection-target>
+ </resource-env-ref>
+ </interceptor>
+</interceptors>
+
+ ]]>
+ </programlisting>
+ <itemizedlist mark="opencircle">
+ <listitem>
+ <para>
+ The container looks up <literal>java:/ConnectionFactory</literal> in JNDI and creates the <literal>java:comp/env/jms/ConnFactory</literal>
+ entry in the bean's ENC, and following bean creation it injects the connection factory into <literal>AccountsCancelInterceptor</literal>'s
+ <literal>cf</literal> field.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ The container looks up <literal>queue/tutorial/accounts</literal> in JNDI and creates the <literal>java:comp/env/accountsQueue</literal>
+ entry in the bean's ENC, and following bean creation it injects the queue into <literal>AccountsCancelInterceptor</literal>'s
+ <literal>queue</literal> field. </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect5>
+ </sect5>
+
+ <sect5>
+ Interceptor Ordering :
+ <para>
+ By default the ordering of interceptors when invoking a method are
+ <itemizedlist mark="number">
+ <listitem>
+ <para>
+ External interceptors
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Default interceptors, if present
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Class interceptors, if present
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Method interceptors, if present
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Interceptor method on the bean class (using @AroundInvoke)
+ </para>
+ </listitem>
+
+ </itemizedlist>
+ Within each group (default, class, method) the order of the interceptors are from left to right as defined in the @Interceptors annotation,
+ and then the xml interceptors.
+ </para>
+
+ <sect5>
+ Overriding interceptor ordering :
+
+ <para>
+ You can override the default sort order of the external interceptors by specifiying an <literal>interceptor-binding</literal> with an <literal>interceptor-order</literal>
+ specifying the order of the interceptors
+ <programlisting>
+ <![CDATA[
+<assembly-descriptor>
+ <interceptor-binding>
+ <ejb-name>EmailSystemBean</ejb-name>
+ <interceptor-order>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.AccountsCancelInterceptor</interceptor-class>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.DefaultInterceptor</interceptor-class>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.OtherInterceptor</interceptor-class>
+ <interceptor-class>org.jboss.tutorial.interceptor.bean.TracingInterceptor</interceptor-class>
+ </interceptor-order>
+ <method>
+ <method-name>sendBookingCancellationMessage</method-name>
+ </method>
+ </interceptor-binding>
+ ...
+</assembly-descriptor>
+
+ ]]>
+ </programlisting>
+ </para>
+ So when invoking <literal>EmailSystemBean.sendBookingCancellationMessage</literal> we will get the following interception order,
+ quite different from the default sort order
+ <itemizedlist mark="number">
+ <listitem>
+ <para>
+ AccountsCancelInterceptor (method-level)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ DefaultInterceptor (default interceptor)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ OtherInterceptor (2nd class-level interceptor)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ TracingInterceptor (1st class-level interceptor)
+ </para>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect5>
+
+ </sect5>
+
+ <sect5>
+ InvocationContext :
+ <para>
+ As you have seen the <literal>@AroundInvoke</literal> annotated interceptor methods all take a parameter of type
+ <literal>javax.ejb.InvocationContext</literal>. The definition of InvocationContext is:
+
+ <programlisting>
+ <![CDATA[
+
+package javax.interceptor;
+
+public interface InvocationContext {
+
+ public java.lang.Object getTarget();
+
+ public java.lang.reflect.Method getMethod();
+
+ public java.lang.Object[] getParameters();
+
+ public void setParameters(java.lang.Object[] arg0);
+
+ public java.util.Map getContextData();
+
+ public java.lang.Object proceed() throws java.lang.Exception;
+}
+ ]]>
+
+ </programlisting>
+
+ <para>
+ <literal>getBean()</literal> - returns the bean instance on which we are calling a method
+ </para>
+ <para>
+ <literal>getMethod()</literal> - returns the method we are calling on the bean instance
+ </para>
+ <para>
+ <literal>getParameters()</literal> - returns the parameters for the method call
+ </para>
+ <para>
+ <literal>setParameters()</literal> - allows you to modify the parameters for the method call
+ </para>
+ <para>
+ <literal>getContextData</literal> - The EJB interceptions are stateless, but the same InvocationContext instance
+ is used for each interceptor method in a chain. If you want to pass values between interceptor methods in the
+ business method invocation you can store them in the Map retured by getContextData().
+ </para>
+ <para>
+ <literal>proceed</literal> - As discussed, invokes the next interceptor, or if we are in the last interceptor
+ invokes the target bean method.
+ </para>
+
+ In some case we might want access to the EJBContext, this can be injected into the interceptor instance using the
+ <literal>@Resource</literal> annotation. The AroundInvoke methods share the JNDI name space of the bean for whose
+ methods they are invoked and execute within the same transaction and security context as the business methods for
+ which they are invoked.
+
+ </para>
+ </sect5>
+
+ <sect5>
+
+Building and Running
+ <para>
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+ Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] Starting
+ [java]
+ [java] Calling emailLostPassword
+ [java] Waiting 2 seconds
+ [java]
+ [java] Calling sendBookingConfirmationMessage
+ [java] Waiting 2 seconds
+ [java]
+ [java] Calling sendBookingConfirmationMessage
+ [java] Waiting 2 seconds
+ [java]
+ [java] Calling sendBookingCancellationMessage
+ [java] Waiting 2 seconds
+ [java]
+ [java] Calling noop
+ [java] Waiting 2 seconds
+ [java]
+ [java] Calling noop2
+ [java] Waiting 2 seconds
+ [java] Done
+
+ ]]>
+ </programlisting>
+
+ <sect5>
+ Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+
+ <para>
+ <programlisting>
+ <![CDATA[
+21:49:01,888 INFO [STDOUT] *** DefaultInterceptor intercepting emailLostPassword
+21:49:01,889 INFO [STDOUT] *** TracingInterceptor intercepting emailLostPassword
+21:49:01,889 INFO [STDOUT] *** OtherInterceptor intercepting emailLostPassword
+21:49:01,889 INFO [STDOUT] *** EmailSystemBean.myBeanInterceptor - username: whatever
+21:49:01,889 INFO [STDOUT] <In EmailSystemBean.emailLostPassword business method
+21:49:02,083 INFO [STDOUT] Message sent successfully to remote queue.
+21:49:02,130 INFO [STDOUT] Exiting EmailSystemBean.emailLostPassword business method>
+21:49:02,130 INFO [STDOUT] *** OtherInterceptor exiting
+21:49:02,130 INFO [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.emailLostPassword() took 241ms
+21:49:02,130 INFO [STDOUT] *** DefaultInterceptor exiting
+21:49:02,179 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
+21:49:02,180 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
+21:49:02,180 WARN [InterceptorRegistry] applicable interceptors is non-existent for public void org.jboss.tutorial.interceptor.bean.EmailMDB.onMessage(javax.jms.Message)
+21:49:02,181 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.lang.Object org.jboss.tutorial.interceptor.bean.EmailMDB.mdbInterceptor(javax.interceptor.InvocationContext) throws java.lang.Exception
+21:49:02,182 WARN [InterceptorRegistry] applicable interceptors is non-existent for public void org.jboss.tutorial.interceptor.bean.EmailMDB.onMessage(javax.jms.Message)
+21:49:02,184 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.lang.Object org.jboss.tutorial.interceptor.bean.EmailMDB.mdbInterceptor(javax.interceptor.InvocationContext) throws java.lang.Exception
+21:49:02,185 INFO [STDOUT] *** EmailMDB.mdbInterceptor intercepting
+21:49:02,185 INFO [STDOUT]
+----------------
+EMailMDB - Got message, sending email
+----------------
+21:49:04,251 INFO [STDOUT] *** DefaultInterceptor intercepting sendBookingConfirmationMessage
+21:49:04,251 INFO [STDOUT] *** TracingInterceptor intercepting sendBookingConfirmationMessage
+21:49:04,251 INFO [STDOUT] *** OtherInterceptor intercepting sendBookingConfirmationMessage
+21:49:04,251 INFO [STDOUT] *** AccountsConfirmInterceptor intercepting
+21:49:04,395 INFO [STDOUT] *** AccountsConfirmInterceptor - recording confirmation
+21:49:04,431 INFO [STDOUT] *** AccountsConfirmInterceptor - notifying accounts dept sendBookingConfirmationMessage
+21:49:04,440 INFO [STDOUT] <In EmailSystemBean.sendBookingConfirmationMessage business method
+21:49:04,455 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
+21:49:04,455 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
+21:49:04,455 WARN [InterceptorRegistry] applicable interceptors is non-existent for public void org.jboss.tutorial.interceptor.bean.AccountsMDB.onMessage(javax.jms.Message)
+21:49:04,457 WARN [InterceptorRegistry] applicable interceptors is non-existent for public void org.jboss.tutorial.interceptor.bean.AccountsMDB.onMessage(javax.jms.Message)
+21:49:04,458 INFO [STDOUT] *** DefaultInterceptor intercepting onMessage
+21:49:04,459 INFO [STDOUT]
+----------------
+AccountsMDB - Got message Confirming order 100
+----------------
+21:49:04,459 INFO [STDOUT] *** DefaultInterceptor exiting
+21:49:04,466 INFO [STDOUT] Message sent successfully to remote queue.
+21:49:04,467 INFO [STDOUT] Exiting EmailSystemBean.sendBookingConfirmationMessage business method>
+21:49:04,467 INFO [STDOUT] *** AccountsConfirmInterceptor exiting
+21:49:04,467 INFO [STDOUT] *** OtherInterceptor exiting
+21:49:04,467 INFO [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.sendBookingConfirmationMessage() took 216ms
+21:49:04,467 INFO [STDOUT] *** DefaultInterceptor exiting
+21:49:04,478 INFO [STDOUT] *** EmailMDB.mdbInterceptor intercepting
+21:49:04,478 INFO [STDOUT]
+----------------
+EMailMDB - Got message, sending email
+----------------
+21:49:06,533 INFO [STDOUT] *** DefaultInterceptor intercepting sendBookingConfirmationMessage
+21:49:06,533 INFO [STDOUT] *** TracingInterceptor intercepting sendBookingConfirmationMessage
+21:49:06,533 INFO [STDOUT] *** OtherInterceptor intercepting sendBookingConfirmationMessage
+21:49:06,533 INFO [STDOUT] *** AccountsConfirmInterceptor intercepting
+21:49:06,547 INFO [STDOUT] *** AccountsConfirmInterceptor - order has already been confirmed aborting
+21:49:06,548 INFO [STDOUT] *** AccountsConfirmInterceptor exiting
+21:49:06,548 INFO [STDOUT] *** OtherInterceptor exiting
+21:49:06,548 INFO [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.sendBookingConfirmationMessage() took 15ms
+21:49:06,548 INFO [STDOUT] *** DefaultInterceptor exiting
+21:49:08,577 INFO [STDOUT] *** AccountsInterceptor intercepting sendBookingCancellationMessage
+21:49:08,577 INFO [STDOUT] *** AccountsCancelInterceptor intercepting sendBookingCancellationMessage
+21:49:08,577 INFO [STDOUT] *** AccountsConfirmInterceptor - notifying accounts dept
+21:49:08,593 INFO [STDOUT] *** DefaultInterceptor intercepting sendBookingCancellationMessage
+21:49:08,593 INFO [STDOUT] *** OtherInterceptor intercepting sendBookingCancellationMessage
+21:49:08,593 INFO [STDOUT] *** TracingInterceptor intercepting sendBookingCancellationMessage
+21:49:08,593 INFO [STDOUT] <In EmailSystemBean.sendBookingCancellationMessage business method
+21:49:08,605 INFO [STDOUT] Message sent successfully to remote queue.
+21:49:08,606 INFO [STDOUT] Exiting EmailSystemBean.sendBookingCancellationMessage business method>
+21:49:08,606 INFO [STDOUT] *** TracingInterceptor invocation of org.jboss.tutorial.interceptor.bean.EmailSystemBean.sendBookingCancellationMessage() took 13ms
+21:49:08,606 INFO [STDOUT] *** OtherInterceptor exiting
+21:49:08,606 INFO [STDOUT] *** DefaultInterceptor exiting
+21:49:08,606 INFO [STDOUT] *** AccountsCancelInterceptor exiting
+21:49:08,606 INFO [STDOUT] *** AccountsInterceptor exiting
+21:49:08,617 INFO [STDOUT] *** EmailMDB.mdbInterceptor intercepting
+21:49:08,617 INFO [STDOUT]
+----------------
+EMailMDB - Got message, sending email
+----------------
+21:49:08,620 INFO [STDOUT] *** DefaultInterceptor intercepting onMessage
+21:49:08,620 INFO [STDOUT]
+----------------
+AccountsMDB - Got message Cancelling order 100
+----------------
+21:49:08,620 INFO [STDOUT] *** DefaultInterceptor exiting
+21:49:10,628 INFO [STDOUT] <In EmailSystemBean.noop business method
+21:49:10,628 INFO [STDOUT] Exiting EmailSystemBean.noop business method>
+21:49:12,648 INFO [STDOUT] <In EmailSystemBean.noop2 business method
+21:49:12,648 INFO [STDOUT] Exiting EmailSystemBean.noop2 business method>
+
+ ]]>
+ </programlisting>
+ </para>
+ <note>
+ <para>
+ Look at the JBoss console window to see the output of the interceptions taking place, the EmailMDB and AccountsMDB
+ might occur in slightly different places since they execute asynchronously.
+ </para>
+ <para>
+ You can ignore the [WARN] messages:
+ <programlisting>
+21:49:02,179 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
+21:49:02,180 WARN [InterceptorsFactory] EJBTHREE-1246: Do not use InterceptorsFactory with a ManagedObjectAdvisor, InterceptorRegistry should be used via the bean container
+21:49:02,180 WARN [InterceptorRegistry] applicable interceptors is non-existent for public void org.jboss.tutorial.interceptor.bean.EmailMDB.onMessage(javax.jms.Message)
+21:49:02,181 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.lang.Object org.jboss.tutorial.interceptor.bean.EmailMDB.mdbInterceptor(javax.interceptor.InvocationContext) throws java.lang.Exception
+21:49:02,182 WARN [InterceptorRegistry] applicable interceptors is non-existent for public void org.jboss.tutorial.interceptor.bean.EmailMDB.onMessage(javax.jms.Message)
+21:49:02,184 WARN [InterceptorRegistry] applicable interceptors is non-existent for public java.lang.Object org.jboss.tutorial.interceptor.bean.EmailMDB.mdbInterceptor(javax.interceptor.InvocationContext) throws java.lang.Exception
+
+ </programlisting>
+ </para>
+ </note>
+ </para>
+ </sect5>
+</chapter>
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/jndibinding.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/jndibinding.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/jndibinding.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,128 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="JNDI Bindings">
+ <title>Binding your beans in JNDI</title>
+ <para>
+ By default, when the application is deployed in a jar, session beans will bind to JNDI in the form <literal>ejbName/remote</literal> for remote
+ interfaces and <literal>ejbName/local</literal> in the case of local interfaces. When the EJBs are deployed in an .ear file, the default
+ jndi binding will be prepended by the name of the .ear file. So if the ear file name is <literal>foo.ear</literal> the default jndi
+ names would be <literal>foo/EJB-NAME/remote</literal> and <literal>foo/EJB-NAME/local</literal>. You can override this behavior
+ by defining your own <literal>@org.jboss.ejb3.annotation.LocalBinding</literal> and/or <literal>@org.jboss.ejb3.annotation.RemoteBinding</literal>.
+
+ </para>
+
+ <sect5>
+ Local Interface JNDI Binding :
+ <para>
+ To change the JNDI name for your local interface use the <literal>@org.jboss.ejb3.annotation.LocalBinding</literal> annotation.
+ <programlisting>
+ <![CDATA[
+ at Stateless
+ at LocalBinding(jndiBinding="custom/MySession")
+public class MySessionBean implements MySession
+{
+}
+
+ ]]>
+ </programlisting>
+ </para>
+
+ </sect5>
+
+ <sect5>
+ Remote Interface JNDI Binding :
+ <para>
+ To change the JNDI name for your remote interface use the <literal>@org.jboss.ejb3.annotation.RemoteBinding</literal> annotation.
+
+ <programlisting>
+ <![CDATA[
+ at Stateless
+ at RemoteBinding(jndiBinding="custom/remote/MySession")
+public class MySessionBean implements MySession
+{
+}
+
+ ]]>
+ </programlisting>
+ </para>
+ </sect5>
+
+ <sect5>
+ Persistence unit JNDI Bindings :
+ <para>
+ Persistence units are not bound into JNDI by default. You can bind them by defining some jboss specific properties
+ in persistence.xml.
+ <programlisting>
+ <![CDATA[
+<persistence>
+ <persistence-unit name="manager1">
+ <jta-data-source>java:/DefaultDS</jta-data-source>
+ <jar-file>MyApp.jar</jar-file>
+ <class>org.acme.Employee</class>
+ <class>org.acme.Person</class>
+ <class>org.acme.Address</class>
+ <properties>
+ <property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
+ <property name="jboss.entity.manager.factory.jndi.name" value="java:/Manager1Factory"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+
+ ]]>
+ </programlisting>
+ <note>
+
+ <xref linkend="JNDIBinding">Not supported in JBossAS-5.0 GA</xref>
+
+ </note>
+
+ </para>
+ </sect5>
+
+ <sect5>
+ Client :
+ <para>
+ Open up <literal>org.jboss.tutorial.jndibinding.client.Client</literal>.
+ You'll see that it looks up the stateless bean under "Calculator". Also notice that there is no Home interface
+ and you can begin executing on the stateless bean right away.
+ </para>
+ </sect5>
+
+ <sect5>
+
+Building and Running
+ <para>
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+ Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] 1 + 1 = 2
+ [java] 1 - 1 = 0
+
+ ]]>
+ </programlisting>
+
+ <sect5>
+ Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+ </para>
+ </sect5>
+</chapter>
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="Message Driven Beans">
+ <title>Introduction to Message Driven Beans in EJB3</title>
+ <para>
+ This example shows you how to implement an MDB with EJB 3.0 using annotations.
+
+ </para>
+ <para>
+ Take a look at <literal>org.jboss.tutorial.mdb.bean.ExampleMDB</literal>. The @MessageDriven annotation
+ defines the bean as an MDB. The <literal>activationConfig</literal> attribute contains much of the MDB configuration via
+ <literal>@ActivationConfigProperty</literal>. Also notice that the MDB source contains properties for
+ <literal>destinationType</literal> and <literal>destination</literal>
+
+ </para>
+
+ <para>
+ The following is the list of standard Activation Config Properties available from the JCA 1.5 specification.
+ Also listed are the respective types and default values where defined.
+
+
+ </para>
+</chapter>
Added: projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb_deployment_descriptor.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb_deployment_descriptor.xml (rev 0)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/mdb_deployment_descriptor.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -0,0 +1,89 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<chapter id="Message Driven Beans with deployment descriptor">
+ <title>Configuring Message Driven Beans through deployment descriptors</title>
+ <para>
+ You configure properties by using the <message-driven> element and sub elements which correspond to the
+ <literal>@ActivationConfigProperty</literal> annotation.
+ <para>ejb-jar.xml:</para>
+ <programlisting>
+ <![CDATA[
+<message-driven>
+ <ejb-name>ExampleMDB</ejb-name>
+ <ejb-class>org.jboss.tutorial.mdb_deployment_descriptor.bean.ExampleMDB</ejb-class>
+ <transaction-type>Bean</transaction-type>
+ <message-destination-type>javax.jms.Queue</message-destination-type>
+ <activation-config>
+ <activation-config-property>
+ <activation-config-property-name>acknowledgeMode</activation-config-property-name>
+ <activation-config-property-value>AUTO_ACKNOWLEDGE</activation-config-property-value>
+ </activation-config-property>
+ </activation-config>
+
+</message-driven>
+
+ ]]>
+ </programlisting>
+
+ <para>jboss.xml</para>
+ <programlisting>
+ <![CDATA[
+<message-driven>
+ <ejb-name>ExampleMDB</ejb-name>
+ <destination-jndi-name>queue/tutorial/example</destination-jndi-name>
+</message-driven>
+ ]]>
+ </programlisting>
+
+ The <literal>queue/tutorial/example</literal> is configured through the <literal>queue-example-service.xml</literal>
+ </para>
+
+ <sect5>
+
+Building and Running
+ <para>
+ <note>
+ <para>
+ To build and run the example, make sure you have installed JBoss 5.x.
+ See the <xref linkend="JBossAS5">installation section</xref> for details.
+ </para>
+ </note>
+
+ <sect5>
+ Ant Users:
+ </sect5>
+ <para>
+ Make sure your JBossAS-5.x is running
+ </para>
+ <programlisting>
+ <![CDATA[
+$ ant
+$ ant run
+
+run:
+ [java] Message sent successfully to remote queue.
+
+
+ ]]>
+ </programlisting>
+
+ <sect5>
+ Maven Users: <xref linkend="Maven_Users_TODO">TODO</xref>
+ </sect5>
+
+ <programlisting>
+$ mvn clean install
+ </programlisting>
+
+ On the server console, you will notice the following logs:
+ <programlisting>
+ <![CDATA[
+23:37:38,175 INFO [STDOUT] ----------------
+23:37:38,175 INFO [STDOUT] Received message
+23:37:38,175 INFO [STDOUT] ----------------
+
+ ]]>
+ </programlisting>
+ </para>
+ </sect5>
+
+</chapter>
\ No newline at end of file
Modified: projects/ejb3/trunk/docs/tutorial/guide/en/modules/todo.xml
===================================================================
--- projects/ejb3/trunk/docs/tutorial/guide/en/modules/todo.xml 2009-01-05 04:12:59 UTC (rev 82604)
+++ projects/ejb3/trunk/docs/tutorial/guide/en/modules/todo.xml 2009-01-05 07:49:00 UTC (rev 82605)
@@ -12,4 +12,35 @@
</section>
+ <section id="JNDIBinding">
+ <title>TODO - Support for binding the EntityManager and EntityManagerFactory in JNDI</title>
+ <para>
+ JBoss-5.0 GA does NOT support binding the EntityManager and EntityManagerFactory in JNDI, using
+ the following properties in persistence.xml:
+
+ <programlisting>
+ <![CDATA[
+<persistence>
+ <persistence-unit name="manager1">
+ ...
+ <properties>
+ <property name="jboss.entity.manager.jndi.name" value="java:/Manager1"/>
+ <property name="jboss.entity.manager.factory.jndi.name" value="java:/Manager1Factory"/>
+ </properties>
+ </persistence-unit>
+</persistence>
+
+ ]]>
+ </programlisting>
+ We are tracking this in our EJBTHREE JIRA.
+ </para>
+
+ </section>
+
+ <section id="InvocationContext_Javadoc">
+ <title>Point to the javadocs of InvocationContext in the "interceptor" tutorial guide</title>
+ <para>
+ Better point to javadocs instead of the listing the methods in the guide
+ </para>
+ </section>
</chapter>
\ No newline at end of file
More information about the jboss-cvs-commits
mailing list