Author: dan.j.allen
Date: 2009-10-27 14:36:17 -0400 (Tue, 27 Oct 2009)
New Revision: 4352
Added:
doc/trunk/reference/en-US/images/m2eclipse-wicket-numberguess-import.png
Modified:
doc/trunk/reference/en-US/Author_Group.xml
doc/trunk/reference/en-US/Book_Info.xml
doc/trunk/reference/en-US/environments.xml
doc/trunk/reference/en-US/example.xml
doc/trunk/reference/en-US/gettingstarted.xml
doc/trunk/reference/en-US/intro.xml
doc/trunk/reference/en-US/master.xml
doc/trunk/reference/en-US/part1.xml
Log:
first round of updates title, part1, example, intro and getting started, as well as some
tweaks here and there
Modified: doc/trunk/reference/en-US/Author_Group.xml
===================================================================
--- doc/trunk/reference/en-US/Author_Group.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/Author_Group.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -6,7 +6,7 @@
<surname>King</surname>
<affiliation>
<jobtitle>JSR-299 specification lead</jobtitle>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</author>
<author>
@@ -15,10 +15,18 @@
<affiliation>
<jobtitle>Web Beans (JSR-299 Reference Implementation) lead
</jobtitle>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</author>
<author>
+ <firstname>Dan</firstname>
+ <surname>Allen</surname>
+ <affiliation>
+ <jobtitle>Senior Software Engineer</jobtitle>
+ <orgname>Red Hat, Inc.</orgname>
+ </affiliation>
+ </author>
+ <author>
<firstname>David</firstname>
<surname>Allen</surname>
</author>
@@ -32,7 +40,7 @@
<surname>Guerrero</surname>
<contrib>Spanish Translation</contrib>
<affiliation>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</othercredit>
<othercredit>
@@ -40,7 +48,7 @@
<surname>Ki,</surname>
<contrib>Korean Translation</contrib>
<affiliation>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</othercredit>
<othercredit>
@@ -48,7 +56,7 @@
<surname>Chuang</surname>
<contrib>Traditional Chinese Translation</contrib>
<affiliation>
- <orgname>Red Hat Inc.</orgname>
+ <orgname>Red Hat, Inc.</orgname>
</affiliation>
</othercredit>
<othercredit>
Modified: doc/trunk/reference/en-US/Book_Info.xml
===================================================================
--- doc/trunk/reference/en-US/Book_Info.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/Book_Info.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,8 +1,13 @@
-<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
+<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<bookinfo>
- <title>Web Beans: Java Contexts and Dependency Injection</title>
- <subtitle>The new standard for dependency injection and contextual state
management</subtitle>
+ <title>Weld - JSR-299 Reference Implementation</title>
+ <subtitle>
+ JSR-299: The new Java standard for dependency injection and contextual life cycle
management
+ </subtitle>
- <xi:include href="Author_Group.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="Author_Group.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
</bookinfo>
Modified: doc/trunk/reference/en-US/environments.xml
===================================================================
--- doc/trunk/reference/en-US/environments.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/environments.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -272,7 +272,7 @@
</listitem>
</itemizedlist>
- <section>
+ <section id="weld-se">
<title>Web Beans SE Module</title>
<para>To make life easy for developers Web Beans provides a special
module with a
Modified: doc/trunk/reference/en-US/example.xml
===================================================================
--- doc/trunk/reference/en-US/example.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/example.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,16 +1,15 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="example">
- <title>JSF web application example</title>
+ <title>JSF web application example</title>
- <para>Let's illustrate these ideas with a full example. We're going
- to implement user login/logout for an application that uses JSF. First,
- we'll define a Web Bean to hold the username and password entered during
- login:</para>
+ <para>
+ Let's illustrate these ideas with a full example. We're going to implement
a user login/logout for an application
+ that uses JSF. First, we'll define a request-scoped bean to hold the username
and password entered during login:
+ </para>
<programlisting role="JAVA"><![CDATA[@Named @RequestScoped
public class Credentials {
-
private String username;
private String password;
@@ -19,86 +18,110 @@
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
-
}]]></programlisting>
- <para>This Web Bean is bound to the login prompt in the following JSF
form:</para>
+ <para>This bean is bound to the login prompt in the following JSF
form:</para>
-<programlisting role="JAVA"><![CDATA[<h:form>
- <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
- <h:outputLabel for="username">Username:</h:outputLabel>
- <h:inputText id="username"
value="#{credentials.username}"/>
- <h:outputLabel for="password">Password:</h:outputLabel>
- <h:inputText id="password"
value="#{credentials.password}"/>
- </h:panelGrid>
- <h:commandButton value="Login" action="#{login.login}"
rendered="#{!login.loggedIn}"/>
- <h:commandButton value="Logout" acion="#{login.logout}"
rendered="#{login.loggedIn}"/>
+ <programlisting role="JAVA"><![CDATA[<h:form>
+ <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
+ <h:outputLabel for="username">Username:</h:outputLabel>
+ <h:inputText id="username"
value="#{credentials.username}"/>
+ <h:outputLabel for="password">Password:</h:outputLabel>
+ <h:inputText id="password"
value="#{credentials.password}"/>
+ </h:panelGrid>
+ <h:commandButton value="Login" action="#{login.login}"
rendered="#{!login.loggedIn}"/>
+ <h:commandButton value="Logout" action="#{login.logout}"
rendered="#{login.loggedIn}"/>
</h:form>]]></programlisting>
- <para>The actual work is done by a session scoped Web Bean that maintains
- information about the currently logged-in user and exposes the
<literal>User</literal>
- entity to other Web Beans:</para>
+ <para>
+ The actual work is done by a session-scoped bean that maintains information
about the currently logged-in user
+ and exposes the <literal>User</literal> entity to other beans:
+ </para>
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Named
+ <programlisting role="JAVA"><![CDATA[@SessionScoped @Named
public class Login {
- @Current Credentials credentials;
- @PersistenceContext EntityManager userDatabase;
+ @Inject Credentials credentials;
+ @Inject @UserDatabase EntityManager userDatabase;
- private User user;
+ private User user;
- public void login() {
-
- List<User> results = userDatabase.createQuery(
- "select u from User u where u.username=:username and
u.password=:password")
- .setParameter("username", credentials.getUsername())
- .setParameter("password", credentials.getPassword())
- .getResultList();
+ public void login() {
+ List<User> results = userDatabase.createQuery(
+ "select u from User u where u.username = :username and u.password =
:password")
+ .setParameter("username", credentials.getUsername())
+ .setParameter("password", credentials.getPassword())
+ .getResultList();
- if ( !results.isEmpty() ) {
- user = results.get(0);
- }
-
- }
+ if (!results.isEmpty()) {
+ user = results.get(0);
+ }
+ else {
+ // perhaps add code here to report a failed login
+ }
+ }
- public void logout() {
- user = null;
- }
+ public void logout() {
+ user = null;
+ }
- public boolean isLoggedIn() {
- return user!=null;
- }
+ public boolean isLoggedIn() {
+ return user != null;
+ }
- @Produces @LoggedIn User getCurrentUser() {
- return user;
- }
+ @Produces @LoggedIn User getCurrentUser() {
+ return user;
+ }
}]]></programlisting>
- <para>Of course, <literal>@LoggedIn</literal> is a binding
annotation:</para>
+ <para><literal>@LoggedIn</literal> and
<literal>@UserDatabase</literal> are custom qualifier
annotations:</para>
-<programlisting role="JAVA"><![CDATA[@Retention(RUNTIME)
-@Target({TYPE, METHOD, FIELD})
-@BindingType
+ <programlisting role="JAVA"><![CDATA[@Retention(RUNTIME)
+@Target({TYPE, METHOD, PARAMETER, FIELD})
+@Documented
+@Qualifier
public @interface LoggedIn {}]]></programlisting>
- <para>Now, any other Web Bean can easily inject the current user:</para>
+ <programlisting role="JAVA"><![CDATA[@Retention(RUNTIME)
+@Target({METHOD, PARAMETER, FIELD})
+@Documented
+@Qualifier
+public @interface UserDatabase {}]]></programlisting>
-<programlisting role="JAVA"><![CDATA[public class DocumentEditor {
+ <para>
+ We need an adapter bean to expose our typesafe
<literal>EntityManager</literal>:
+ </para>
- @Current Document document;
- @LoggedIn User currentUser;
- @PersistenceContext EntityManager docDatabase;
+ <programlisting role="JAVA"><![CDATA[public class
UserDatabaseProducer {
+ @Produces @UserDatabase @PersistenceContext EntityManager userDatabase;
+}]]></programlisting>
+
+ <para>Now, any other bean can easily inject the current user, as well as other
beans:</para>
+
+ <programlisting role="JAVA"><![CDATA[public class DocumentEditor {
+ @Inject Document document;
+ @Inject @LoggedIn User currentUser;
+ @Inject @DocumentDatabase EntityManager docDatabase;
- public void save() {
- document.setCreatedBy(currentUser);
- docDatabase.persist(document);
- }
-
+ public void save() {
+ document.setCreatedBy(currentUser);
+ docDatabase.persist(document);
+ }
}]]></programlisting>
- <para>Hopefully, this example gives a flavor of the Web Bean programming model.
- In the next chapter, we'll explore Web Beans dependency injection in greater
- depth.</para>
+ <para>Or we can reference the current user in a JSF view:</para>
-</chapter>
\ No newline at end of file
+ <programlisting role="XML"><![CDATA[<h:panelGroup
rendered="#{login.loggedIn}">
+ signed in as #{currentUser.username}
+</h:panelGroup>]]></programlisting>
+
+ <para>
+ Hopefully, this example gives a flavor of the CDI services. In the next chapter,
we'll explore examples from the
+ CDI reference implementation, Weld, in greater depth.
+ </para>
+
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</chapter>
Modified: doc/trunk/reference/en-US/gettingstarted.xml
===================================================================
--- doc/trunk/reference/en-US/gettingstarted.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/gettingstarted.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,293 +1,617 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<chapter id="gettingstarted">
+<!-- TODO
+Explain use of war:inplace to use jetty
+Java SE numberguess example
+-->
-<chapter id="ri">
- <title>Getting started with Web Beans, the Reference Implementation of
JSR-299</title>
+ <title>Getting started Weld, the JSR-299 reference implementation</title>
<para>
- The Web Beans is being developed at
- <ulink
url="http://seamframework.org/WebBeans">the Seam
project</ulink>.
- You can download the latest developer release of Web Beans from the
- <ulink
url="http://seamframework.org/Download">the downloads
page</ulink>.
- </para>
+ Weld, the JSR-299 RI (Reference Implementation), is being developed as part of the
<ulink
+
url="http://seamframework.org/Weld">Seam project</ulink>. You
can download the latest community release of Weld
+ from the <ulink
url="http://seamframework.org/Download">download
page</ulink>. Information about the Weld source
+ code repository and instructions about how to obtain and build the source can be
found on the same page.
+ </para>
- <para>
- Web Beans comes with a two deployable example applications:
- <literal>webbeans-numberguess</literal>, a war example which runs on
- JBoss AS, Tomcat, Jetty and Google App Engine, containing only
- simple beans, and <literal>webbeans-translator</literal> an ear
example,
- containing enterprise beans.
- To run the examples you'll need the following:
+ <para>
+ Weld comes with two starter example applications, in addition to more specialized
examples. The first,
+ <literal>weld-numberguess</literal>, is a web (WAR) example containing
only non-transactional managed beans.
+ This example can be run on a wide range of servers, including JBoss AS, GlassFish,
Apache Tomcat, Jetty, Google
+ App Engine, and any compliant Java EE 6 container. The second example,
<literal>weld-translator</literal>, is
+ an enterprise (EAR) example that contains session beans. This example must be run
on JBoss AS 5.2 or any compliant
+ Java EE 6 container.
</para>
- <itemizedlist>
- <listitem>
- <para>the latest release of Web Beans,</para>
- </listitem>
- <listitem>
- <para>JBoss AS 5.2.0, or</para>
- </listitem>
- <listitem>
- <para>Jetty 6.1.x, or</para>
- </listitem>
- <listitem>
- <para>Apache Tomcat 6.0.x, and</para>
- </listitem>
- <listitem>
- <para>Ant 1.7.0.</para>
- </listitem>
- </itemizedlist>
+ <para>
+ Both examples use JSF 2.0 as the web framework and, as such, can be found in the
examples/jsf directory of the
+ Weld distribution.
+ </para>
+
+ <section id="prerequisites">
+ <title>Prerequisites</title>
+
+ <para>
+ To run the examples with the provided build scripts, you'll need the
following:
+ </para>
- <section>
- <title>Using JBoss AS 5</title>
+ <itemizedlist>
+ <listitem>
+ <para>the latest release of Weld, which contains the
examples</para>
+ </listitem>
+ <listitem>
+ <para>Ant 1.7.0, to build and deploy the examples</para>
+ </listitem>
+ <listitem>
+ <para>a supported runtime environment (minimum versions
shown)</para>
+ <itemizedlist>
+ <listitem>
+ <para>JBoss AS 5.2.0 (currenly only nightly builds of JBoss AS
5.2.0.Beta1 are available), or</para>
+ </listitem>
+ <listitem>
+ <para>GlassFish 3.0, or</para>
+ </listitem>
+ <listitem>
+ <para>Apache Tomcat 6.0.x (WAR example only), or</para>
+ </listitem>
+ <listitem>
+ <para>Jetty 6.1.x (WAR example only)</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <para>(optionally) Maven 2.x, to run the examples in an embedded
servlet container</para>
+ </listitem>
+ </itemizedlist>
- <para>
- You'll need to download JBoss AS 5.2.0 from
- <ulink
url="http://www.jboss.org/jbossas/downloads/">jboss.org</...;,
- and unzip it. For example:
+ <note>
+ <para>
+ You'll need a full install of Ant 1.7.0. Some linux distributions only
supply a partial installation of Ant
+ which cause the build to fail. If you encounter problems, verify that
ant-nodeps.jar is on the classpath.
+ </para>
+ </note>
+
+ <para>
+ In the next few sections, you'll be using the Ant command (ant) to invoke
the Ant build script in each of the two
+ examples to compile, assemble and deploy the example to JBoss AS and, for the
WAR example, Apache Tomcat. You can
+ also deploy the generated artifact (WAR or EAR) to any other container that
supports Java EE 6, such as GlassFish V3.
</para>
+
+ <para>
+ If you have Maven installed, you can also use the Maven command (mvn) to compile
and assemble the standalone
+ artifact (WAR or EAR) and, for the WAR example, run it in an embedded
container.
+ </para>
- <programlisting><![CDATA[$ cd /Applications
-$ unzip ~/jboss-5.2.0.Beta.zip]]></programlisting>
+ <para>The sections below cover the steps for deploying with both Ant and
Maven in detail. Let's start with JBoss AS.</para>
+ </section>
+
+ <section id="jbossas">
+ <title>Deploying to JBoss AS</title>
+
+ <para>
+ To deploy the examples to JBoss AS, you'll need <ulink
src="http://jboss.org/jbossas/">JBoss AS
+ 5.2.0.Beta1</ulink> or above. If a release of the JBoss AS 5.2 line
isn't yet available, you can download a
+ <ulink
src="http://hudson.jboss.org/hudson/view/JBoss%20AS/job/JBoss-AS-5.x...
snapshot</ulink>.
+ The reason JBoss AS 5.2.0.Beta1 or above is required is because it's the
first release that has both CDI and
+ Bean Validation support built-in, making it close enough to Java EE 6 to run the
examples. The good news is
+ that there are no additional modifications you have to make to the server.
It's ready to go!
+ </para>
+
+ <para>
+ After you have downloaded JBoss AS, extract it. (We recommended renaming the
folder to include the
+ <literal>as</literal> qualifier so it's clear that it's the
application server). You can move the extracted
+ folder anywhere you like. Whereever it lays to rest, that's what we'll
call the JBoss AS installation
+ directory, or <literal>JBOSS_HOME</literal>.
+ </para>
+
+ <programlisting><![CDATA[$> unzip jboss-5.2.*.zip
+$> mv jboss-5.2.*/ jboss-as-5.2]]></programlisting>
+
+ <para>
+ In order for the build scripts to know where to deploy the example, you have to
tell them where to find your
+ JBoss AS installation (i.e., <literal>JBOSS_HOME</literal>). Create
a new file named local.build.properties in
+ the examples directory of the Weld distribution and assign the path of your
JBoss AS installation to the property
+ key <literal>jboss.home</literal>, as follows:
+ </para>
+
+
<programlisting><![CDATA[jboss.home=/path/to/jboss-as-5.2]]></programlisting>
+
+ <para>
+ You're now ready to deploy your first example!
+ </para>
+
+ <para>
+ Switch to the examples/jsf/numberguess directory and execute the Ant deploy
target:
+ </para>
+
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess
+$> ant deploy]]></programlisting>
+
+ <para>
+ If you haven't already, start JBoss AS. You can either start JBoss AS from a
Linux shell:
+ </para>
+
+ <programlisting><![CDATA[$> cd /path/to/jboss-as-5.2
+$> ./bin/run.sh]]></programlisting>
+
+ <para>
+ a Windows command window:
+ </para>
+
+ <programlisting><![CDATA[$> cd c:\path\to\jboss-as-5.2\bin
+$> run]]></programlisting>
+
+ <para>
+ or you can start the server using an IDE, like Eclipse.
+ </para>
+
<note>
<para>
- JBoss AS 5.2.0 comes with Web Beans built in.
+ If you are using Eclipse, you should seriously consider installing the
<ulink
+
src="http://www.jboss.org/tools">JBoss Tools</ulink>
add-ons, which include a wide variety of tooling for
+ JSR-299 and Java EE development, as well as an enhanced JBoss AS server
view.
</para>
</note>
-
+
<para>
- Now, you're ready to deploy your first example!
+ Wait a few seconds for the application to deploy (or the application server to
start) and see if you can
+ determine the most efficient approach to pinpoint the random number at the local
URL <ulink
+
src="http://localhost:8080/weld-numberguess">http://localhost:8080/weld-numberguess</ulink>.
</para>
-
+
<tip>
<para>
- The build scripts for the examples offer a number of targets for
- JBoss AS, these are:
+ The Ant build script includes additional targets for JBoss AS to deploy and
undeploy the archive in either exploded or packaged format and to tidy things up.
</para>
<itemizedlist>
<listitem>
<para>
- <literal>ant restart</literal> - deploy the example in
exploded
- format
+ <literal>ant restart</literal> - deploy the example in
exploded format to JBoss AS
</para>
</listitem>
<listitem>
<para>
- <literal>ant explode</literal> - update an exploded
example, without
- restarting the deployment
+ <literal>ant explode</literal> - update an exploded
example, without restarting the deployment
</para>
</listitem>
<listitem>
<para>
- <literal>ant deploy</literal> - deploy the example in
compressed jar format
+ <literal>ant deploy</literal> - deploy the example in
compressed jar format to JBoss AS
</para>
</listitem>
<listitem>
<para>
- <literal>ant undeploy</literal> - remove the example from
the server
+ <literal>ant undeploy</literal> - remove the example from
JBoss AS
</para>
</listitem>
<listitem>
<para>
<literal>ant clean</literal> - clean the example
- </para>
+ </para>
</listitem>
</itemizedlist>
</tip>
-
+
<para>
- To deploy the numberguess example:
+ The second starter example, <literal>weld-translator</literal>, will
translate your text into Latin. (Well,
+ not really, but the stub is there for you to implement, at least. Good luck!) To
try it out, switch to the
+ translator example directory and execute the deploy target:
</para>
- <programlisting>$ cd examples/jsf/numberguess
-ant deploy</programlisting>
+ <programlisting><![CDATA[$> cd examples/jsf/translator
+$> ant deploy]]></programlisting>
+ <note>
+ <para>
+ The translator uses session beans, which are packaged in an EJB module within
an EAR. Java EE 6 will allow
+ session beans to be deployed in WAR modules, but that's a topic for
future chapter.
+ </para>
+ </note>
+
<para>
- Start JBoss AS:
+ Again, wait a few seconds for the application to deploy (if you are bored, read
the log messages), and visit
+ <ulink
src="http://localhost:8080/weld-translator">http://localhost:8080/weld-translator</ulink>
to begin
+ pseudo-translating.
</para>
-
- <programlisting>$
/Application/jboss-5.2.0.Beta/bin/run.sh</programlisting>
-
- <tip>
- <para>
- If you use Windows, use the <literal>run.bat</literal>script.
- </para>
- </tip>
+
+ <para>
+ TODO Insert note about upgrading the Weld deployer that directs reader to
section on the JBoss AS environment
+ </para>
+ </section>
+
+ <section id="glassfish">
+ <title>Deploying to GlassFish</title>
+
<para>
- Wait for the application to deploy, and enjoy hours of fun at
- <ulink url="http://localhost:8080/webbeans-numberguess" />!
+ Deploying to GlassFish should be easy, right? After all, it's the Java EE 6
reference implementation. Since
+ it's the Java EE 6 reference implementation, that means it also bundles the
JSR-299 reference implementation,
+ Weld! So yes, it's very easy.
</para>
-
+
<para>
- Web Beans includes a second simple example that will translate your text
- into Latin. The numberguess example is a war example, and uses only simple
- beans; the translator example is an ear example, and includes enterprise
- beans, packaged in an EJB module. To try it out:
+ To deploy the examples to GlassFish, you'll need the final <ulink
+
src="https://glassfish.dev.java.net/">GlassFish V3</ulink>
release (the preview release won't do). If the final
+ release isn't yet available, you can download a <ulink
+
src="http://download.java.net/glassfish/v3/promoted/">promoted
build</ulink> in the meantime. Select the b69
+ preview release or above that ends in either -unix.sh or -windows.exe depending
on your platform. After the
+ download is complete, execute the installer. On Linux/Unix, you'll need to
first make the script executable.
</para>
+
+ <programlisting><![CDATA[$> chmod 755 glassfish-v3-b69-unix.sh
+$> ./glassfish-v3-b69-unix.sh]]></programlisting>
+
+ <para>
+ On Windows you can just click on the executable. Follow the instructions in the
installer. It will create a
+ single domain named <literal>domain1</literal>. You'll use that
domain to deploy the example. We recommend that
+ you choose 7070 as the main HTTP port to avoid conflicts with a running instance
of JBoss AS (or Apache
+ Tomcat).
+ </para>
- <programlisting>$ cd examples/translator
-ant deploy</programlisting>
-
<para>
- Wait for the application to deploy, and visit
- <ulink url="http://localhost:8080/webbeans-translator" />!
+ If you've deployed either of the starter examples,
<literal>weld-numberguess</literal> or
+ <literal>weld-translator</literal>, to JBoss AS, then you already
have the deployable artifact you need.
+ If not, switch to either of the two directories and build it.
</para>
-
+
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess (or
examples/jsf/translator)
+$> ant package]]></programlisting>
+
+ <para>
+ The deployable archive for the <literal>weld-numberguess</literal>,
named weld-numberguess.war, ends up in the
+ example's target directory. The archive for the
<literal>weld-translator</literal> example, named
+ weld-translator.ear, ends up in the example's ear/target directory. All you
need to do now is deploy them to
+ GlassFish.
+ </para>
+
+ <para>
+ You deploy applications to GlassFish using the <ulink
src="http://localhost:4848">GlassFish Admin
+ Console</ulink>. To get the Admin Console running, you need to start a
GlassFish domain, in our case
+ <literal>domain1</literal>. Switch to the bin folder in the
directory where you installed GlassFish and execute
+ the following command:
+ </para>
+
+ <programlisting><![CDATA[$> asadmin start-domain
domain1]]></programlisting>
+
+ <para>
+ After a few seconds you can visit the Admin Console in the browser at the URL
<ulink
+ src="http://localhost:4848">http://localhost:4848</ulink>. In
the tree on the left-hand
+ side of the page, click on "Applications", then click on the
"Deploy..." button under
+ the heading "Applications" and select the deployable artifact for
either of the two examples.
+ The deployer should recognize that you have selected a Java EE artifact and
allow you to
+ start it. You can see the examples running at either <ulink
+
src="http://localhost:7070/weld-numberguess">http://localhost:7070/weld-numberguess</ulink>
or <ulink
+
src="http://localhost:7070/weld-translator">http://localhost:7070/weld-translator</ulink>,
+ depending on which example you deployed.
+ </para>
+
+ <para>
+ The reason the same artifact can be deployed to both JBoss AS and GlassFish,
without any modifications, is
+ because all of the features being used are part of the standard platform. And
what a capable platform it has
+ become!
+ </para>
+
</section>
- <section>
- <title>Using Apache Tomcat 6.0</title>
-
- <para>
- You'll need to download Tomcat 6.0.18 or later from
- <ulink
url="http://tomcat.apache.org/download-60.cgi">tomcat.apache...;,
- and unzip it. For example:
+ <section id="tomcat">
+ <title>Deploying to Apache Tomcat</title>
+
+ <para>
+ Technically, CDI doesn't support servlet containers. That's because the
contexts and dependency injection
+ services are provided by the Java EE container, not the Servlet API. However,
CDI implementations can choose to
+ support servlet containers through an extension. Weld does this.</para>
+
+ <para>
+ Weld ships with a Servlet listener which bootstraps the CDI environment,
registers the BeanManager in JNDI and
+ provides injection into servlets. Basically, it emulates the work done by the
Java EE container. The only
+ limitation is that you cannot use enterprise features such as session beans and
container-managed transactions.
</para>
-
- <programlisting><![CDATA[$ cd /Applications
-$ unzip ~/apache-tomcat-6.0.18.zip]]></programlisting>
<para>
- Next, download Web Beans from
- <ulink
url="http://seamframework.org/Download">seamframework.org<...;,
- and unzip it. For example
+ Let's give the Weld servlet extension a spin on Apache Tomcat. First,
you'll need to download Tomcat 6.0.18 or later
+ from <ulink
src="http://tomcat.apache.org/download-60.cgi">tomcat.apache...
and extract it.
</para>
+
+ <programlisting><![CDATA[$> unzip
apache-tomcat-6.0.18.zip]]></programlisting>
+
+ <para>
+ You have two choices for how you can deploy the application to Tomcat. You can
deploy it by pushing the
+ artifact to the hot deploy directory using Ant or you can deploy to the server
across HTTP using a Maven
+ plugin. The Ant approach doesn't require that you have Maven installed, so
we'll start there. If you want to
+ use Maven, you can just skip ahead.
+ </para>
+
+ <section id="tomcat-ant">
+ <title>Deploying with Ant</title>
+
+ <para>
+ In order for Ant to push the artifact to the Tomcat hot deploy directory, it
needs to know where the Tomcat
+ installation is located. Again, we need to setup a propery in the
local.build.properties file in the
+ examples directory of the Weld distribution. If you haven't yet created
this file, do so now. Then assign
+ the path of your Tomcat installation to the property key tomcat.home.
+ </para>
+
+
<programlisting><![CDATA[tomcat.home=/path/to/apache-tomcat-6]]></programlisting>
+
+ <para>
+ Now you're ready to deploy the numberguess example to Tomcat!
+ </para>
+
+ <para>
+ Change to the examples/jsf/numberguess directory again and run the Ant deploy
target for Tomcat:
+ </para>
+
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess
+$> ant tomcat.deploy]]></programlisting>
+
+ <tip>
+ <para>
+ The Ant build script includes additional targets for Tomcat to deploy and
undeploy the archive in either
+ exploded or packaged format. They are the same target names used for JBoss
AS, prefixed with "tomcat.".
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>ant tomcat.restart</literal> - deploy the
example in exploded format to Tomcat
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.explode</literal> - update an
exploded example, without restarting the deployment
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.deploy</literal> - deploy the
example in compressed jar format to Tomcat
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.undeploy</literal> - remove the
example from Tomcat
+ </para>
+ </listitem>
+ </itemizedlist>
+ </tip>
+
+ <para>
+ If you haven't already, start Tomcat. You can either start Tomcat from a
Linux shell:
+ </para>
+
+ <programlisting><![CDATA[$> cd /path/to/apache-tomcat-6
+$> ./bin/start.sh]]></programlisting>
+
+ <para>
+ a Windows command window:
+ </para>
+
+ <programlisting><![CDATA[$> cd c:\path\to\apache-tomcat-6\bin
+$> start]]></programlisting>
+
+ <para>
+ or you can start the server using an IDE, like Eclipse.
+ </para>
+
+ <para>
+ Wait a few seconds for the application to deploy (or the application server
to start) and see if you can figure
+ out the most efficient approach to pinpoint the random number at the local
URL
+ <ulink
src="http://localhost:8080/weld-numberguess">http://localhost:8080/weld-numberguess</ulink>!
+ </para>
+
+ </section>
- <programlisting><![CDATA[$ cd ~/
-$ unzip ~/webbeans-$VERSION.zip]]></programlisting>
-
-
<programlisting>tomcat.home=/Applications/apache-tomcat-6.0.18</programlisting>
+ <section id="tomcat-maven">
+ <title>Deploying with Maven</title>
- <tip>
<para>
- The build scripts for the examples offer a number of targets for
- Tomcat, these are:
+ You can also deploy the application to Tomcat using Maven. This section is a
bit more advanced, so skip it
+ unless you are itching to use Maven natively. Of course, you'll first
need to make sure that you have Maven
+ installed on your path, similar to how you setup Ant.
</para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>mvn war:inplace tomcat:run -Ptomcat</literal> -
deploy the example in an embedded Tomcat
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>mvn compile war:exploded tomcat:exploded
-Ptomcat</literal> - deploy the example to a running Tomcat install
- </para>
- </listitem>
- </itemizedlist>
+
<para>
- See the <code>jsf/numberguess/readme.txt</code> for more
details.
+ The Maven plugin communicates with Tomcat over HTTP, so it doesn't care
where you have installed Tomcat.
+ However, the plugin configuration assumes you are running Tomcat in its
default configuration, with a hostname
+ of localhost and port 8080. The readme.txt file in the example directory has
information about how to modify
+ the Maven settings to accomodate a different setup.
</para>
- </tip>
-
+
+ <para>
+ To allow Maven to communicate with Tomcat over HTTP, edit the
conf/tomcat-users.xml file in your Tomcat
+ installation and add the following line:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<user
username="admin" password=""
roles="manager"/>]]></programlisting>
+
+ <para>
+ Restart Tomcat. You can now deploy the application to Tomcat with Maven using
this command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn compile war:exploded tomcat:exploded
-Ptomcat]]></programlisting>
+
+ <para>
+ Once the application is deployed, you can redeploy it using this command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn tomcat:redeploy
-Ptomcat]]></programlisting>
+
+ <para>
+ The <literal>-Ptomcat</literal> argument activates the tomcat
profile defined in the Maven POM (pom.xml).
+ Among other things, this profile activates the Tomcat plugin.
+ </para>
+
+ <para>
+ Rather than shipping the container off to a standalone Tomcat installation,
you can also execute the
+ application in an embedded Tomcat 6 container:
+ </para>
+
+ <programlisting><![CDATA[$> mvn war:inplace tomcat:run
-Ptomcat]]></programlisting>
+
+ <para>
+ The advantage of using the embedded server is that changes to assets in
src/main/webapp take affect
+ immediately. If a change to a webapp configuration file is made, the
application may automatically redeploy
+ (depending on the plugin configuration). If you make a change to a classpath
resource, you need to execute a
+ build:
+ </para>
+
+ <programlisting><![CDATA[$> mvn compile war:inplace
-Ptomcat]]></programlisting>
+
+ <para>
+ There are several other Maven goals that you can use if you are hacking on
the example, which are documented in
+ the example's readme.txt file.
+ </para>
+
+ </section>
+
+ </section>
+
+ <section id="jetty">
+ <title>Deploying to Jetty</title>
+
+ <!-- subsections? -->
+
<para>
- To deploy the numberguess example for tomcat:
+ Support for Jetty in the examples is a more recent addition. Since Jetty is
traditionally used with Maven,
+ there are no Ant targets. You must invoke the Maven build directly to deploy the
examples to Jetty out of the
+ box. Also, only the <literal>weld-numberguess</literal> example is
configured for Jetty support at the time of
+ this writing.
</para>
-
- <programlisting>$ cd examples/jsf/numberguess
-ant tomcat.deploy</programlisting>
<para>
- Edit <code>$TOMCAT_HOME/conf/tomcat-users.xml</code> and add
+ If you've read through the entire Tomcat section, then you're all ready
to go. The Maven build parallels the
+ embedded Tomcat deployment. If not, don't worry. We'll still go over
everything in this section that you need
+ to know.
</para>
-
- <programlisting><![CDATA[<user username="admin"
password="" roles="manager"/>]]></programlisting>
-
- <para>This allows Maven to communicate with Tomcat.</para>
-
+
<para>
- Start Tomcat:
+ The Maven POM (pom.xml) includes a profile named jetty that activates the Maven
Jetty plugin, which you can use
+ to start Jetty in embedded mode and deploy the application in place. You
don't need anything else installed
+ except to have the Maven command (mvn) on your path. The rest will be downloaded
from the internet when the
+ build is run.
</para>
-
- <programlisting>$
/Applications/apache-tomcat-6.0.18/bin/startup.sh</programlisting>
-
- <tip>
- <para>
- If you use Windows, use the
<literal>startup.bat</literal>script.
- </para>
- </tip>
-
- <para>Deploy the application</para>
-
- <programlisting>$ mvn compile war:exploded tomcat:exploded
-Ptomcat</programlisting>
-
+
<para>
- Wait for the application to deploy, and enjoy hours of fun at
- <ulink url="http://localhost:8080/webbeans-numberguess" />!
+ To run the <literal>weld-numberguess</literal> example on Jetty,
switch to the example directory and execute
+ the inplace goal of the Maven WAR plugin followed by the run goal of the Maven
Jetty plugin with the jetty
+ profile enabled, as follows:
</para>
+ <programlisting><![CDATA[$> cd examples/jsf/numberguess
+$> mvn war:inplace jetty:run -Pjetty]]></programlisting>
+
+ <para>
+ The log output of Jetty will be shown in the console. Once Jetty reports that
the application has deployed, you
+ can access it at the following local URL: <ulink
+
src="http://localhost:9090/weld-numberguess">http://localhost:9090/weld-numberguess</ulink>.
The port is
+ defined in the Maven Jetty plugin configuration within the jetty profile.
+ </para>
+
+ <para>
+ Any changes to assets in src/main/webapp take affect immediately. If a change to
a webapp configuration file is
+ made, the application may automatically redeploy. The redeploy behavior can be
fined tuned in the plugin
+ configuration. If you make a change to a classpath resource, you need to execute
a build and the inplace goal
+ of the Maven WAR plugin, again with the jetty profile enabled.
+ </para>
+
+ <programlisting><![CDATA[$> mvn compile war:inplace
-Pjetty]]></programlisting>
+
+ <para>
+ The war:inplace goal copies the compiled classes and JARs inside
src/main/webapp, under WEB-INF/classes and
+ WEB-INF/lib, respectively, mixing source and compiled files. However, the build
does work around these
+ temporary files by excluding them from the packaged WAR and cleaning them during
the Maven clean phase.
+ </para>
+
+ <para>
+ You have two options if you want to run the example on Jetty from the IDE. You
can either install the
+ m2eclispe[link] plugin and run the goals as described above. Your other option
is to start the Jetty container
+ from a Java application.
+ </para>
+
+ <para>
+ First, initialize the Eclipse project:
+ </para>
+
+ <programlisting><![CDATA[$> mvn clean eclipse:clean eclipse:eclipse
-Pjetty-ide]]></programlisting>
+
+ <para>
+ Next, assemble all the necessary resources under src/main/webapp:
+ </para>
+
+ <programlisting><![CDATA[$> mvn war:inplace
-Pjetty-ide]]></programlisting>
+
+ <para>
+ Now, you are ready to run the server in Eclipse. Import the project into your
Eclipse workspace using "Import
+ Existing Project into Workspace. Then, find the start class in src/jetty/java
and run its main method as a Java
+ Application. Jetty will launch. You can view the application at the following
local URL: <ulink
+ src="http://localhost:8080">http://localhost:8080</ulink>.
Pay particular attention to the port in the URL and
+ the lack of a trailing context path.
+ </para>
+
+ <!-- NOTE Transition paragraph into the example explanation sections. -->
+ <para>
+ Now that you have gotten the starter applications deployed on the server of your
choice, you probably want to
+ know a little bit about how they actually work. It's time to pull the covers
back and dive into the internals
+ of these two examples. Let's start with the simpler of the two examples,
<literal>weld-numberguess</literal>.
+ </para>
+
</section>
- <section>
- <title>Using GlassFish</title>
+ <section id="numberguess">
+ <title>The numberguess example in depth</title>
- <para>TODO</para>
- </section>
-
- <section>
- <title>The numberguess example</title>
-
<para>
- In the numberguess application you get given 10 attempts to guess a
- number between 1 and 100. After each attempt, you will be told whether
- you are too high, or too low.
+ In the numberguess application you get given 10 attempts to guess a number
between 1 and 100. After each
+ attempt, you will be told whether you are too high or too low.
</para>
<para>
- The numberguess example is comprised of a number of Web Beans,
- configuration files, and Facelet JSF pages, packaged as a war. Let's
- start with the configuration files.
+ The numberguess example is comprised of a number of beans, configuration files
and Facelets (JSF) views,
+ packaged as a WAR module. Let's start by examining the configuration files.
</para>
<para>
- All the configuration files for this example are located in
- <literal>WEB-INF/</literal>, which is stored in
- <literal>WebContent</literal> in the source tree. First, we have
- <literal>faces-config.xml</literal>, in which we tell JSF to use
- Facelets:
+ All the configuration files for this example are located in
<literal>WEB-INF/</literal>, which can be found in
+ the <literal>src/main/webapp</literal> directory of the example.
First, we have the JSF 2.0 version of
+ <literal>faces-config.xml</literal>. A standardized version of
Facelets is the default view handler in JSF
+ 2.0, so there's really nothing that we have to configure. Thus, the
configuration consists of only the root
+ element.
</para>
- <programlisting role="XML"><![CDATA[<?xml
version='1.0' encoding='UTF-8'?>
-<faces-config version="1.2"
-
xmlns="http://java.sun.com/xml/ns/javaee"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
-
- <application>
- <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>
- </application>
-
+ <programlisting role="XML"><![CDATA[<faces-config
version="2.0"
+
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+
http://java.sun.com/xml/ns/javaee
+
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
</faces-config>]]></programlisting>
<para>
- There is an empty <literal>web-beans.xml</literal> file, which
marks
- this application as a Web Beans application.
+ There's also an empty <literal>beans.xml</literal> file, which
tells the container to look for beans in this
+ application and to activate the CDI services.
</para>
<para>
- Finally there is <literal>web.xml</literal>:
+ Finally, there's the familiar <literal>web.xml</literal>:
</para>
<programlistingco>
<areaspec>
- <area id="faces.servlet" coords="12" />
- <area id="faces.servlet.mapping" coords="18" />
- <area id="faces.default.suffix" coords="23" />
- <area id="session.timeout" coords="28" />
- <area id="webbeans.listener" coords="32" />
+ <area id="faces.servlet" coords="10" />
+ <area id="faces.servlet.mapping" coords="16" />
+ <area id="faces.default.suffix" coords="21" />
+ <area id="session.timeout" coords="26" />
</areaspec>
- <programlisting><![CDATA[<?xml version="1.0"
encoding="UTF-8"?>
-
-<web-app version="2.5"
-
xmlns="http://java.sun.com/xml/ns/javaee"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
+ <programlisting role="XML"><![CDATA[<web-app
version="2.5"
+
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+
http://java.sun.com/xml/ns/javaee
+
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <display-name>Web Beans Numbergues example</display-name>
+ <display-name>weld-jsf-numberguess-war</display-name>
+ <description>Weld JSF numberguess example (WAR)</description>
- <!-- JSF -->
-
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
@@ -312,18 +636,18 @@
<calloutlist>
<callout arearefs="faces.servlet">
<para>
- Enable and load the JSF servlet
+ Enable and initialize the JSF servlet
</para>
</callout>
<callout arearefs="faces.servlet.mapping">
<para>
- Configure requests to <literal>.jsf</literal> pages to be
+ Configure requests for URLs ending in
<literal>.jsf</literal> to be
handled by JSF
</para>
</callout>
<callout arearefs="faces.default.suffix">
<para>
- Tell JSF that we will be giving our source files (facelets) an
+ Tell JSF that we will be giving our JSF views (Facelets templates) an
extension of <literal>.xhtml</literal>
</para>
</callout>
@@ -337,76 +661,71 @@
<note>
<para>
- Whilst this demo is a JSF demo, you can use Web Beans with any
- Servlet based web framework.
+ This demo uses JSF 2 as the view framework, but you can use Weld with any
Servlet-based web framework, such
+ as JSF 1.2 or Wicket.
</para>
</note>
<para>
- Let's take a look at the Facelet view:
+ Let's take a look at the main JSF view, src/main/webapp/home.xhtml.
</para>
<programlistingco>
<areaspec>
<area id="template" coords="8" />
- <area id="messages2" coords="12" />
- <area id="instructions" coords="19" />
- <area id="guess" coords="25" />
- <area id="validator" coords="30" />
- <area id="submit" coords="33" />
+ <area id="statusMessages" coords="12" />
+ <area id="instructions" coords="20" />
+ <area id="guess" coords="27" />
+ <area id="validator" coords="29" />
+ <area id="submit" coords="30" />
</areaspec>
- <programlisting><![CDATA[<!DOCTYPE html PUBLIC "-//W3C//DTD
XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+ <programlisting role="HTML"><![CDATA[<!DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xmlns="http://www.w3.org/1999/xhtml"
-
xmlns:ui="http://java.sun.com/jsf/facelets"
-
xmlns:h="http://java.sun.com/jsf/html"
-
xmlns:f="http://java.sun.com/jsf/core"
-
xmlns:s="http://jboss.com/products/seam/taglib">
+
xmlns:ui="http://java.sun.com/jsf/facelets"
+
xmlns:h="http://java.sun.com/jsf/html"
+
xmlns:f="http://java.sun.com/jsf/core">
- <ui:composition template="template.xhtml">
- <ui:define name="content">
- <h1>Guess a number...</h1>
- <h:form id="NumberGuessMain">
- <div style="color: red">
- <h:messages id="messages" globalOnly="false"/>
- <h:outputText id="Higher" value="Higher!"
rendered="#{game.number gt game.guess and game.guess ne 0}"/>
- <h:outputText id="Lower" value="Lower!"
rendered="#{game.number lt game.guess and game.guess ne 0}"/>
- </div>
-
- <div>
- I'm thinking of a number between #{game.smallest} and #{game.biggest}.
- You have #{game.remainingGuesses} guesses.
- </div>
-
- <div>
- Your guess:
- <h:inputText id="inputGuess"
- value="#{game.guess}"
- required="true"
- size="3"
- disabled="#{game.number eq game.guess}">
- <f:validateLongRange maximum="#{game.biggest}"
- minimum="#{game.smallest}"/>
- </h:inputText>
- <h:commandButton id="GuessButton"
- value="Guess"
- action="#{game.check}"
- disabled="#{game.number eq game.guess}"/>
- </div>
- <div>
- <h:commandButton id="RestartButton" value="Reset"
action="#{game.reset}" immediate="true" />
- </div>
- </h:form>
- </ui:define>
- </ui:composition>
+ <ui:composition template="/template.xhtml">
+ <ui:define name="content">
+ <h1>Guess a number...</h1>
+ <h:form id="numberGuess">
+ <div style="color: red">
+ <h:messages id="messages" globalOnly="false"/>
+ <h:outputText id="Higher" value="Higher!"
+ rendered="#{game.number gt game.guess and game.guess ne
0}"/>
+ <h:outputText id="Lower" value="Lower!"
+ rendered="#{game.number lt game.guess and game.guess ne
0}"/>
+ </div>
+
+ <div>
+ I'm thinking of a number between #{game.smallest} and
#{game.biggest}.
+ You have #{game.remainingGuesses} guesses remaining.
+ </div>
+
+ <div>
+ Your guess:
+ <h:inputText id="inputGuess" value="#{game.guess}"
+ size="3" required="true"
disabled="#{game.number eq game.guess}"
+ validator="#{game.validateNumberRange}"/>
+ <h:commandButton id="guessButton" value="Guess"
+ action="#{game.check}" disabled="#{game.number eq
game.guess}"/>
+ </div>
+ <div>
+ <h:commandButton id="restartButton" value="Reset"
action="#{game.reset}" immediate="true"/>
+ </div>
+ </h:form>
+ </ui:define>
+ </ui:composition>
</html>]]></programlisting>
<calloutlist>
<callout arearefs="template">
<para>
- Facelets is a templating language for JSF, here we are
- wrapping our page in a template which defines the header.
+ Facelets is the built-in templating language for JSF. Here we are
+ wrapping our page in a template which defines the layout.
</para>
</callout>
- <callout arearefs="messages2">
+ <callout arearefs="statusMessages">
<para>
There are a number of messages which can be sent to the user,
"Higher!", "Lower!" and "Correct!"
@@ -415,73 +734,69 @@
<callout arearefs="instructions">
<para>
As the user guesses, the range of numbers they can guess gets
- smaller - this sentance changes to make sure they know what
- range to guess in.
+ smaller - this sentance changes to make sure they know the
+ number range of a valid guess.
</para>
</callout>
<callout arearefs="guess">
<para>
- This input field is bound to a Web Bean, using the value
+ This input field is bound to a bean property using a value
expression.
</para>
</callout>
<callout arearefs="validator">
<para>
- A range validator is used to make sure the user doesn't
+ A validator binding is used to make sure the user doesn't
accidentally input a number outside of the range in which they
can guess - if the validator wasn't here, the user might use
- up a guess on an out of range number.
+ up a guess on an out of bounds number.
</para>
</callout>
<callout arearefs="submit">
<para>
And, of course, there must be a way for the user to send their
- guess to the server. Here we bind to an action method on the
- Web Bean.
+ guess to the server. Here we bind to an action method on the bean.
</para>
</callout>
</calloutlist>
</programlistingco>
<para>
- The example exists of 4 classes, the first two of which are binding
- types. First, there is the <literal>@Random</literal> binding type,
- used for injecting a random number:
+ The example exists of 4 classes, the first two of which are qualifiers. First,
there is the
+ <literal>@Random</literal> qualifier, used for injecting a random
number:
</para>
<programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD,
PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
-@BindingType
+@Qualifier
public @interface Random {}]]></programlisting>
<para>
- There is also the <literal>@MaxNumber</literal> binding type, used
for
+ There is also the <literal>@MaxNumber</literal> qualifier, used for
injecting the maximum number that can be injected:
</para>
<programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD,
PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
-@BindingType
+@Qualifier
public @interface MaxNumber {}
]]></programlisting>
<para>
- The <literal>Generator</literal> class is responsible for creating
the
- random number, via a producer method. It also exposes the maximum
- possible number via a producer method:
+ The application-scoped <literal>Generator</literal> class is
responsible for creating the random number, via a
+ producer method. It also exposes the maximum possible number via a producer
method:
</para>
<programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Generator {
+public class Generator implements Serializable {
+
+ private java.util.Random random = new java.util.Random(System.currentTimeMillis());
- private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
-
private int maxNumber = 100;
- java.util.Random getRandom()
- {
+ java.util.Random getRandom() {
return random;
}
@@ -489,117 +804,65 @@
return getRandom().nextInt(maxNumber);
}
- @Produces @MaxNumber int getMaxNumber()
- {
+ @Produces @MaxNumber int getMaxNumber() {
return maxNumber;
}
}]]></programlisting>
<para>
- You'll notice that the <literal>Generator</literal> is
application
- scoped; therefore we don't get a different random each time.
+ The <literal>Generator</literal> is application scoped, so we
don't get a different random each time.
</para>
+
+ <note>
+ <para>
+ The package declaration and imports have been excluded from these listings.
The complete listing is
+ available in the example source code.
+ </para>
+ </note>
<para>
- The final Web Bean in the application is the session scoped
- <literal>Game</literal>.
+ The final bean in the application is the session-scoped
<literal>Game</literal> class. This is the primary
+ entry point of the application. It's responsible for setting up or resetting
the game, capturing and validating
+ the user's guess and providing feedback to the user with a
<literal>FacesMessage</literal>. We've used
+ constructor injection to initialize the game with a random number.
</para>
-
+
<para>
- You'll note that we've used the <literal>@Named</literal>
- annotation, so that we can use the bean through EL in the JSF page.
- Finally, we've used constructor injection to initialize the game with
- a random number. And of course, we need to tell the player when they've
- won, so we give feedback with a <literal>FacesMessage</literal>.
+ You'll notice that we've also added the
<literal>@Named</literal> annotation to this class. This annotation is
+ only required when you want to make the bean accessible to a JSF view via EL
(i.e., #{game}).
</para>
-
- <programlisting role="JAVA"><![CDATA[package
org.jboss.webbeans.examples.numberguess;
+
+ <programlisting role="JAVA"><![CDATA[@Named
+@SessionScoped
+public class Game implements Serializable {
-import java.io.Serializable;
-
-import javax.annotation.PostConstruct;
-import javax.enterprise.context.SessionScoped;
-import javax.enterprise.inject.Instance;
-import javax.faces.application.FacesMessage;
-import javax.faces.component.UIComponent;
-import javax.faces.component.UIInput;
-import javax.faces.context.FacesContext;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-@Named
-@SessionScoped
-public class Game implements Serializable
-{
private int number;
-
private int guess;
private int smallest;
-
- @Inject @MaxNumber
- private int maxNumber;
-
private int biggest;
private int remainingGuesses;
-
+
+ @Inject @MaxNumber private int maxNumber;
@Inject @Random Instance<Integer> randomNumber;
- public Game()
- {
- }
-
- public int getNumber()
- {
- return number;
- }
+ public Game() {}
- public int getGuess()
- {
- return guess;
- }
-
- public void setGuess(int guess)
- {
- this.guess = guess;
- }
-
- public int getSmallest()
- {
- return smallest;
- }
-
- public int getBiggest()
- {
- return biggest;
- }
-
- public int getRemainingGuesses()
- {
- return remainingGuesses;
- }
-
- public String check()
- {
- if (guess>number)
- {
+ public void check() {
+ if (guess > number) {
biggest = guess - 1;
}
- if (guess<number)
- {
+ else if (guess < number) {
smallest = guess + 1;
}
- if (guess == number)
- {
+ else if (guess == number) {
FacesContext.getCurrentInstance().addMessage(null, new
FacesMessage("Correct!"));
}
remainingGuesses--;
- return null;
}
@PostConstruct
- public void reset()
- {
+ public void reset() {
this.smallest = 0;
this.guess = 0;
this.remainingGuesses = 10;
@@ -607,108 +870,164 @@
this.number = randomNumber.get();
}
- public void validateNumberRange(FacesContext context, UIComponent toValidate, Object
value)
- {
- if (remainingGuesses <= 0)
- {
+ public void validateNumberRange(FacesContext context, UIComponent toValidate, Object
value) {
+ if (remainingGuesses <= 0) {
FacesMessage message = new FacesMessage("No guesses left!");
context.addMessage(toValidate.getClientId(context), message);
- ((UIInput)toValidate).setValid(false);
+ ((UIInput) toValidate).setValid(false);
return;
}
int input = (Integer) value;
- if (input < smallest || input > biggest)
- {
- ((UIInput)toValidate).setValid(false);
+ if (input < smallest || input > biggest) {
+ ((UIInput) toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid guess");
context.addMessage(toValidate.getClientId(context), message);
}
}
-}
-]]></programlisting>
- <section>
- <title>The numberguess example in Tomcat</title>
+ public int getNumber() {
+ return number;
+ }
+
+ public int getGuess() {
+ return guess;
+ }
+
+ public void setGuess(int guess) {
+ this.guess = guess;
+ }
+
+ public int getSmallest() {
+ return smallest;
+ }
+
+ public int getBiggest() {
+ return biggest;
+ }
+
+ public int getRemainingGuesses() {
+ return remainingGuesses;
+ }
+
+}]]></programlisting>
+
+ <section id="numberguess-servlet">
+ <title>The numberguess example in Apache Tomcat or Jetty</title>
<para>
- The numberguess for Tomcat differs in a couple of ways. Firstly,
- Web Beans should be deployed as a Web Application library in
- <literal>WEB-INF/lib</literal>. For your convenience we provide
a
- single jar suitable for running Web Beans in any servlet container
- <literal>webbeans-servlet.jar</literal>.
+ A couple of modifications must be made to the numberguess artifact in order
to deploy it to Tomcat or Jetty.
+ First, Weld must be deployed as a Web Application library under
<literal>WEB-INF/lib</literal> since the
+ servlet container does not provide the CDI services. For your convenience we
provide a single JAR suitable
+ for running Weld in any servlet container (including Jetty),
<literal>weld-servlet.jar</literal>.
</para>
<tip>
<para>
- Of course, you must also include JSF and EL, as well common
- annotations (<literal>jsr250-api.jar</literal>) which a JEE
server
- includes by default.
+ You must also include the JARs for JSF, EL, and the common annotations
+ (<literal>jsr250-api.jar</literal>), all of which are provided
by the Java EE platorm (a Java EE
+ application server). Are you starting to appreciate why a Java EE platform
is worth using?
</para>
</tip>
<para>
- Secondly, we need to explicitly specify the servlet listener
- (used to boot Web Beans, and control it's interaction with requests)
- in <literal>web.xml</literal>:
+ Second, we need to explicitly specify the servlet listener in
<literal>web.xml</literal>, again because the
+ container isn't doing this stuff for you. The servlet listener boots Weld
and controls it's interaction with
+ requests.
</para>
- <programlisting><![CDATA[<listener>
-
<listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+ <programlisting role="XML"><![CDATA[<listener>
+
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>]]></programlisting>
-
+
+ <para>
+ When Weld boots, it places the
<literal>javax.enterprise.inject.spi.BeanManager</literal>, the portable SPI
+ for obtaining bean instances, in the ServletContext under a variable name
equal to the fully-qualified
+ interface name. You generally don't need to access this interface, but
Weld makes use of it.
+ </para>
+
</section>
- <section id="numberguessWicket">
- <title>The numberguess example for Apache Wicket</title>
+ <section id="numberguess-wicket">
+ <title>The numberguess example for Apache Wicket</title>
<para>
- Whilst JSR-299 specifies integration with Java ServerFaces, Web
- Beans allows you to inject into Wicket components, and also allows
- you to use a conversation context with Wicket. In this section,
- we'll walk you through the Wicket version of the numberguess
- example.
+ Weld includes a number of portable extensions for JSR-299, including an
extension for Wicket, which allows
+ you to inject beans into Wicket components and leverage the conversation
context. In this section, we'll
+ walk you through the Wicket version of the numberguess example.
</para>
- <note>
+ <tip>
<para>
- You may want to review the Wicket documentation at
- <ulink
url="http://wicket.apache.org/">http://wicket.apache.org/<...;.
+ You may want to review the Wicket documentation at <ulink
+
url="http://wicket.apache.org/">http://wicket.apache.org/<...
before reading this section, if you
+ aren't already familiar with the framework.
</para>
- </note>
+ </tip>
<para>
- Like the previous example, the Wicket WebBeans examples make use of
- the <literal>webbeans-servlet</literal> module. The use of the
- <ulink
url="http://jetty.mortbay.org/">Jetty servlet
container</ulink>
- is common in the Wicket community, and is chosen here as the
- runtime container in order to facilitate comparison between the
- standard Wicket examples and these examples, and also to show how
- the webbeans-servlet integration is not dependent upon Tomcat as the
- servlet container.
+ Wicket is another environment that relies on the Weld servlet extension. The
use of <ulink
+ url="http://jetty.mortbay.org">Jetty</ulink> is common in
the Wicket community, and is thus chosen here as
+ the runtime container. You've seen already that Jetty is perfectly
capable of running CDI applications with
+ Weld add-ons, and this environment is no different.
</para>
- <para>
- These examples make use of the Eclipse IDE; instructions are also
- given to deploy the application from the command line.
- </para>
+ <note>
+ <para>
+ We'll also be using the Eclipse IDE in these examples. Instructions
are provided later for running the
+ example from the commandline, but since you'll likely need to do more
than just deploy examples, we'll get
+ setup in this full development environment.
+ </para>
+ </note>
<section>
<title>Creating the Eclipse project</title>
<para>
- To generate an Eclipse project from the example:
+ To use the Wicket example in Eclipse, you have one of two choices. You can
either use a Maven plugin to
+ generate a regular Eclipse Web project, or you can open the example
natively using the <ulink
+
src="http://m2eclipse.sonatype.org/">m2eclipse
plugin</ulink>. Since the Weld source code relies so
+ heavily on Maven, we encourage you to bite the bullet and adopt the
m2eclipse plugin. Both approaches are
+ described here for your convenience..
</para>
+
+ <para>
+ If you have m2eclipse installed, you can open any Maven project directly.
From within Eclipse, select
+ <emphasis>File -> Import... -> Maven
Projects</emphasis>. Then, browse to the location of the Wicket
+ numberguess example. You should see that Eclipse recognizes the existance
of a Maven project.
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata
fileref="images/m2eclipse-wicket-numberguess-import.png"
format="PNG"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ This will create a project in your workspace called
<literal>weld-wicket-numberguess</literal>.
+ </para>
+
+ <para>
+ You'll notice after importing, the project has a build error.
That's because we need to enable a Maven
+ profile. Right-click on the project and select
<emphasis>Properties</emphasis>, then select the
+ <emphasis>Maven</emphasis> tab in the window that appears. In
the form field labeled "Active Maven
+ Profiles (comma separated):", type
<literal>jetty</literal>. That will enable some extra dependencies
+ that allow the project to compile. You're now ready to develop!
+ </para>
+
+ <para>
+ If you are not using the m2eclipse plugin, you have to follow different
steps to import the project.
+ First, switch into the Wicket numberguess example, then execute the Maven
Eclipse plugin with the jetty
+ profile activated, as follows:
+ </para>
- <programlisting><![CDATA[cd examples/wicket/numberguess
+ <programlisting><![CDATA[$> cd examples/wicket/numberguess
mvn -Pjetty eclipse:eclipse]]></programlisting>
<para>
- Then, from eclipse, choose <emphasis>File -> Import -> General
-> Existing Projects into Workspace</emphasis>,
- select the root directory of the numberguess example, and click
- finish. Note that if you do not intend to run the example with jetty from
- within eclipse, omit the "-Pjetty." This will create a project
in your
- workspace called
<literal>webbeans-wicket-numberguess</literal>
+ Then, from Eclipse, choose <emphasis>File -> Import... ->
General -> Existing Projects into
+ Workspace</emphasis>, select the root directory of the numberguess
example, and click Finish. This will
+ create a project in your workspace called
<literal>weld-wicket-numberguess</literal>.
</para>
<mediaobject>
@@ -716,22 +1035,23 @@
<imagedata fileref="images/wicket-numberguess-project.png"
format="PNG"/>
</imageobject>
</mediaobject>
+
+ <para>
+ It's time to get the example running!
+ </para>
+
</section>
<section>
<title>Running the example from Eclipse</title>
<para>
- This project follows the <literal>wicket-quickstart</literal>
- approach of creating an instance of Jetty in the
- <literal>Start</literal> class. So running the example is as
- simple as right-clicking on that Start class in
- <literal>src/test/java</literal> in the
- <emphasis>Package Explorer</emphasis> and choosing
- <emphasis>Run as Java Application</emphasis>. You should
- see console output related to Jetty starting up; then visit able
- <literal>http://localhost:8080</literal> to view the app. To
- debug choose <emphasis>Debug as Java Application</emphasis>.
+ This project follows the <literal>wicket-quickstart</literal>
approach of creating an instance of Jetty
+ in the <literal>Start</literal> class. So running the example
is as simple as right-clicking on that
+ Start class in <literal>src/test/java</literal> in the
<emphasis>Package Explorer</emphasis> and choosing
+ <emphasis>Run as Java Application</emphasis>. You should see
console output related to Jetty starting up;
+ then visit able <literal>http://localhost:8080</literal> to
view the app. To debug choose <emphasis>Debug
+ as Java Application</emphasis> instead.
</para>
</section>
@@ -739,144 +1059,179 @@
<title>Running the example from the command line in JBoss AS or
Tomcat</title>
<para>
- This example can also be deployed from the command line in a
- (similar to the other examples). Assuming you have set up the
- <literal>build.properties</literal> file in the
- <literal>examples</literal> directory to specify the location
of
- JBoss AS or Tomcat, as previously described, you can run
- <literal>ant deploy</literal> from the
- <literal>examples/wicket/numberguess</literal> directory, and
- access the application at
-
<literal>http://localhost:8080/webbeans-numberguess-wicket</literal>.
+ This example can also be deployed from the command line in a (similar to
the other examples). Assuming
+ you have set up the <literal>local.build.properties</literal>
file in the <literal>examples</literal>
+ directory to specify the location of JBoss AS or Tomcat, as previously
described, you can run:
</para>
+
+ <programlisting><![CDATA[$> ant
deploy]]></programlisting>
+
+ <para>to deploy the example to JBoss AS, and:</para>
+
+ <programlisting><![CDATA[$> ant
tomcat.deploy]]></programlisting>
+
+ <para>
+ to deploy the example to Tomcat. You can then access application at
+
<literal>http://localhost:8080/weld-numberguess-wicket</literal>.
+ </para>
+
+ <para>
+ Alternatively, you can run the application in place on an embedded Jetty
container using the following
+ Maven command:
+ </para>
+
+ <programlisting><![CDATA[$> mvn jetty:run
-Pjetty]]></programlisting>
+
+ <para>
+ Enough toying with deployment, let's dive into the code.
+ </para>
+
</section>
<section>
<title>Understanding the code</title>
<para>
- JSF uses Unified EL expressions to bind view layer components in
- JSP or Facelet views to beans, Wicket defines it's components in
- Java. The markup is plain html with a one-to-one mapping between
- html elements and the view components. All view logic, including
- binding of components to models and controlling the response of
- view actions, is handled in Java. The integration of Web Beans
- with Wicket takes advantage of the same binding annotations used
- in your business layer to provide injection into your WebPage
- subclass (or into other custom wicket component subclasses).
+ The code in the wicket numberguess example is very similar to the
JSF-based numberguess example. The
+ business layer is identical! Where things differ is in view binding. JSF
uses Unified EL expressions to
+ bind XML-based view layer components in JSF views to beans. In contrast,
Wicket defines its components in
+ Java. These Java-based view components have a one-to-one mapping with HTML
elements in an adjacent (pure)
+ HTML file. All view logic, including binding of components to models and
controlling the response of view
+ actions, is handled in Java.
</para>
-
+
<para>
- The code in the wicket numberguess example is very similar to the
- JSF-based numberguess example. The business layer is identical!
+ The integration of Weld with Wicket takes advantage of the same qualifier
annotations used in your
+ business layer to provide injection into your
<literal>WebPage</literal> subclass (or into other custom
+ Wicket component subclasses).
</para>
-
+
<para>
- Differences are:
+ Here's where things differ from the JSF numberguess example:
</para>
+
<itemizedlist>
<listitem>
<para>
- Each wicket application must have a
- <literal>WebApplication</literal> subclass, In our
case,
- our application class is
- <literal>SampleApplication</literal>:
+ Each wicket application must have a
<literal>WeldApplication</literal> subclass. In our case, our
+ application class is
<literal>NumberGuessApplication</literal>:
</para>
- <programlisting><![CDATA[public class SampleApplication
extends WebBeansApplication {
- @Override
- public Class getHomePage() {
+ <programlisting role="JAVA"><![CDATA[public class
NumberGuessApplication extends WeldApplication {
+ @Override public Class getHomePage() {
return HomePage.class;
}
}]]></programlisting>
<para>
- This class specifies which page wicket should treat as our
- home page, in our case,
<literal>HomePage.class</literal>
+ This class specifies which page Wicket should treat as our home
page, in our case,
+ <literal>HomePage.class</literal>
</para>
</listitem>
<listitem>
<para>
- In <literal>HomePage</literal> we see typical wicket
code
- to set up page elements. The bit that is interesting is
- the injection of the <literal>Game</literal> bean:
+ In <literal>HomePage</literal>, we see typical Wicket
code to set up page elements. The bit that is
+ interesting is the injection of the
<literal>Game</literal> bean:
</para>
- <programlisting><![CDATA[ @Current Game
game;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject Game
game;]]></programlisting>
<para>
- The <literal>Game</literal> bean is can then be used,
for
- example, by the code for submitting a guess:
+ The <literal>Game</literal> bean is can then be used,
for example, by the code for submitting a
+ guess:
</para>
- <programlisting><![CDATA[final Component guessButton = new
AjaxButton("GuessButton") {
+ <programlisting role="JAVA"><![CDATA[final Component
guessButton = new AjaxButton("GuessButton") {
protected void onSubmit(AjaxRequestTarget target, Form form) {
- if (game.check()) {]]></programlisting>
+ if (game.check()) {
+ info("Correct!");
+ setVisible(false);
+ prompt.setVisible(false);
+ guessLabel.setVisible(false);
+ inputGuess.setVisible(false);
+ }
+ else if (game.getRemainingGuesses() == 0) {
+ info("Sorry, the answer was " + game.getNumber());
+ setVisible(false);
+ guessLabel.setVisible(false);
+ inputGuess.setVisible(false);
+ }
+ else if (game.getNumber() > game.getGuess()) {
+ info("Higher!");
+ }
+ else if (game.getNumber() < game.getGuess()) {
+ info("Lower");
+ }
+ target.addComponent(form);
+ }
+}; ]]></programlisting>
<note>
<para>
- All injections may be serialized; actual storage of the
- bean is managed by JSR-299. Note that Wicket
- components, like the HomePage and it subcomponents, are
+ All injections may be serialized; actual storage of the bean is
managed by JSR-299. Note that
+ Wicket components, like the
<literal>HomePage</literal> and it subcomponents, are
<emphasis>not</emphasis> JSR-299 beans.
</para>
<para>
- Wicket components allow injection, but they
- <emphasis>cannot</emphasis> use interceptors,
decorators
- and lifecycle callbacks such as
- <literal>@PostConstruct</literal> or
- <literal>@Initializer</literal> methods.
+ Wicket components allow injection, but they
<emphasis>cannot</emphasis> use interceptors,
+ decorators and lifecycle callbacks such as
<literal>@PostConstruct</literal> or
+ <literal>@Initializer</literal> methods. The
components would need to delegate to actual beans
+ to leverage these features.
</para>
</note>
</listitem>
<listitem>
<para>
- The example uses AJAX for processing of button events, and
- dynamically hides buttons that are no longer relevant, for
- example when the user has won the game.
+ The example uses AJAX for processing of button events, and
dynamically hides buttons that are no
+ longer relevant, for example when the user has won the game.
</para>
</listitem>
<listitem>
<para>
- In order to activate wicket for this webapp, the Wicket
- filter is added to web.xml, and our application class is
- specified:
+ In order to activate Wicket for this webapp, the Wicket filter is
added to web.xml, and our
+ application class is specified in web.xml:
</para>
- <programlisting><![CDATA[<filter>
- <filter-name>wicket.numberguess-example</filter-name>
+
+ <programlisting role="XML"><![CDATA[<filter>
+ <filter-name>Wicket Filter</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
-
<param-value>org.jboss.webbeans.examples.wicket.SampleApplication</param-value>
+
<param-value>org.jboss.weld.examples.wicket.NumberGuessApplication</param-value>
</init-param>
</filter>
<filter-mapping>
- <filter-name>wicket.numberguess-example</filter-name>
+ <filter-name>Wicket Filter</filter-name>
<url-pattern>/*</url-pattern>
-</filter-mapping>
-
-<listener>
-
<listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
-</listener>]]></programlisting>
+</filter-mapping>]]></programlisting>
+
<para>
- Note that the servlet listener is also added, as in the
- Tomcat example, in order to boostrap Web Beans when Jetty
- starts, and to hook Web Beans into the Jetty servlet
- request and session lifecycles.
+ The servlet listener is still required, as in the Tomcat example, to
bootstrap CDI when Jetty
+ starts and to hook CDI into the Jetty servlet request and session
life cycles. However, rather than
+ putting it into the web.xml, it is placed into an override file,
+ src/main/webapp/WEB-INF/jetty-additions-to-web.xml, that is passed
to Jetty as extra descriptor to
+ be appended to the web.xml configuration.
</para>
+
+ <programlisting role="XML"><![CDATA[<web-app
version="2.4" ...>
+ <listener>
+
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
+ </listener>
+</web-app>]]></programlisting>
+
</listitem>
</itemizedlist>
</section>
</section>
- <section>
+ <section id="numberguess-se">
<title>The numberguess example for Java SE with Swing</title>
<para>
This example can be found in the
- <literal>examples/se/numberguess</literal> folder of the Web
- Beans distribution.
+ <literal>examples/se/numberguess</literal> folder of the Weld
+ distribution.
</para>
@@ -906,7 +1261,7 @@
<para>
execute the following command
</para>
- <programlisting>mvn -Drun</programlisting>
+ <programlisting>$> mvn -Drun</programlisting>
</listitem>
</itemizedlist>
@@ -915,7 +1270,7 @@
<para>
There is an empty <literal>beans.xml</literal> file in the root
package (<literal>src/main/resources/beans.xml</literal>), which
- marks this application as a Web Beans application.
+ marks this application as a CDI application.
</para>
<para>
@@ -933,57 +1288,46 @@
<area id="reset" coords="68" />
</areaspec>
<programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Game implements Serializable
-{
+public class Game implements Serializable {
private int number;
private int guess;
private int smallest;
-
- @MaxNumber
- private int maxNumber;
-
private int biggest;
private int remainingGuesses;
private boolean validNumberRange = true;
- @Current Generator rndGenerator;
+ @Inject @MaxNumber private int maxNumber;
+ @Inject Generator rndGenerator;
+
...
- public boolean isValidNumberRange()
- {
+ public boolean isValidNumberRange() {
return validNumberRange;
}
- public boolean isGameWon()
- {
+ public boolean isGameWon() {
return guess == number;
}
- public boolean isGameLost()
- {
+ public boolean isGameLost() {
return guess != number && remainingGuesses <= 0;
}
- public boolean check()
- {
+ public boolean check() {
boolean result = false;
- if ( checkNewNumberRangeIsValid() )
- {
- if ( guess > number )
- {
+ if (checkNewNumberRangeIsValid()) {
+ if (guess > number) {
biggest = guess - 1;
}
- if ( guess < number )
- {
+ if (guess < number) {
smallest = guess + 1;
}
- if ( guess == number )
- {
+ if (guess == number) {
result = true;
}
@@ -993,14 +1337,12 @@
return result;
}
- private boolean checkNewNumberRangeIsValid()
- {
- return validNumberRange = ( ( guess >= smallest ) && ( guess <=
biggest ) );
+ private boolean checkNewNumberRangeIsValid() {
+ return validNumberRange = ((guess >= smallest) && (guess <=
biggest));
}
@PostConstruct
- public void reset()
- {
+ public void reset() {
this.smallest = 0;
...
this.number = rndGenerator.next();
@@ -1084,12 +1426,10 @@
<area id="challenge" coords="5" />
<area id="result" coords="16" />
</areaspec>
- <programlisting role="JAVA"><![CDATA[public class
MessageGenerator
-{
- @Current Game game;
+ <programlisting role="JAVA"><![CDATA[public class
MessageGenerator {
+ @Inject Game game;
- public String getChallengeMessage()
- {
+ public String getChallengeMessage() {
StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a
number between " );
challengeMsg.append( game.getSmallest() );
challengeMsg.append( " and " );
@@ -1099,35 +1439,33 @@
return challengeMsg.toString();
}
- public String getResultMessage()
- {
- if ( game.isGameWon() )
- {
+ public String getResultMessage() {
+ if ( game.isGameWon() ) {
return "You guess it! The number was " + game.getNumber();
- } else if ( game.isGameLost() )
- {
+ }
+ else if ( game.isGameLost() ) {
return "You are fail! The number was " + game.getNumber();
- } else if ( ! game.isValidNumberRange() )
- {
+ }
+ else if ( ! game.isValidNumberRange() ) {
return "Invalid number range!";
- } else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
- {
+ }
+ else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES ) {
return "What is your first guess?";
- } else
- {
+ }
+ else {
String direction = null;
- if ( game.getGuess() < game.getNumber() )
- {
+ if ( game.getGuess() < game.getNumber() ) {
direction = "Higher";
- } else
- {
+ }
+ else {
direction = "Lower";
}
return direction + "! You have " + game.getRemainingGuesses() +
" guesses left.";
}
}
+
}]]></programlisting>
<calloutlist>
<callout arearefs="game">
@@ -1166,13 +1504,12 @@
<area id="replay" coords="44" />
<area id="refresh" coords="50" />
</areaspec>
- <programlisting role="JAVA"><![CDATA[public class
NumberGuessFrame extends javax.swing.JFrame
-{
- private @Current Game game;
- private @Current MessageGenerator msgGenerator;
+ <programlisting role="JAVA"><![CDATA[public class
NumberGuessFrame extends javax.swing.JFrame {
- public void start( @Observes @Deployed Manager manager )
- {
+ private @Inject Game game;
+ private @Inject MessageGenerator msgGenerator;
+
+ public void start( @Observes @Deployed Manager manager ) {
java.awt.EventQueue.invokeLater( new Runnable()
{
public void run()
@@ -1199,8 +1536,7 @@
...
}
- private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
- {
+ private void guessButtonActionPerformed( java.awt.event.ActionEvent evt ) {
int guess = Integer.parseInt(guessText.getText());
game.setGuess( guess );
@@ -1209,14 +1545,12 @@
}
- private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
- {
+ private void replayBtnActionPerformed( java.awt.event.ActionEvent evt ) {
game.reset();
refreshUI();
}
- private void refreshUI()
- {
+ private void refreshUI() {
mainLabel.setText( msgGenerator.getChallengeMessage() );
messageLabel.setText( msgGenerator.getResultMessage() );
guessText.setText( "" );
@@ -1243,7 +1577,7 @@
</callout>
<callout arearefs="start">
<para>
- This application is started in the usual Web Beans SE way,
+ This application is started in the usual CDI SE way,
by observing the <literal>@Deployed Manager</literal>
event.
</para>
</callout>
@@ -1309,30 +1643,29 @@
</section>
</section>
- <section>
- <title>The translator example</title>
+ <section id="translator">
+ <title>The translator example in depth</title>
<para>
- The translator example will take any sentences you enter, and translate
- them to Latin.
+ The translator example will take any sentences you enter, and translate them to
Latin. (Well, not really, but
+ the stub is there for you to implement, at least. Good luck!)
</para>
<para>
- The translator example is built as an ear, and contains EJBs. As a result,
it's structure is more complex than
+ The translator example is built as an EAR and contains EJBs. As a result,
it's structure is more complex than
the numberguess example.
</para>
<note>
<para>
- EJB 3.1 and Jave EE 6 allow you to package EJBs in a war, which will
- make this structure much simpler!
+ Jave EE 6, which bundles EJB 3.1, allows you to package EJBs in a WAR, which
will make this structure much
+ simpler! Still, there are other advantages of using an EAR.
</para>
</note>
<para>
- First, let's take a look at the ear aggregator, which is located in
- <literal>webbeans-translator-ear</literal> module. Maven
automatically
- generates the <literal>application.xml</literal> for us:
+ First, let's take a look at the EAR aggregator, which is located in the
example's <literal>ear</literal> directory. Maven
+ automatically generates the <literal>application.xml</literal> for
us from this plugin configuration:
</para>
<programlisting role="XML"><![CDATA[<plugin>
@@ -1341,62 +1674,62 @@
<configuration>
<modules>
<webModule>
- <groupId>org.jboss.webbeans.examples.translator</groupId>
- <artifactId>webbeans-translator-war</artifactId>
- <contextRoot>/webbeans-translator</contextRoot>
+ <groupId>org.jboss.weld.examples.jsf.translator</groupId>
+ <artifactId>weld-jsf-translator-war</artifactId>
+ <contextRoot>/weld-translator</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>]]></programlisting>
<para>
- Here we set the context path, which gives us a nice url
- (<ulink
url="http://localhost:8080/webbeans-translator">http://localhost:8080/webbeans-translator</ulink>).
+ This configuration overrides the web context path, resulting in this application
URL: <ulink
+
url="http://localhost:8080/weld-translator">http://localhost:8080/weld-translator</ulink>.
</para>
<tip>
<para>
- If you aren't using Maven to generate these files, you would need
+ If you weren't using Maven to generate these files, you would need
<literal>META-INF/application.xml</literal>:
</para>
- <programlisting role="XML"><![CDATA[<?xml
version="1.0" encoding="UTF-8"?>
-<application
xmlns="http://java.sun.com/xml/ns/javaee"
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/application_5.xsd"
- version="5">
- <display-name>webbeans-translator-ear</display-name>
- <description>Ear Example for the reference implementation of JSR 299: Web
Beans</description>
+ <programlisting role="XML"><![CDATA[<application
version="5"
+
xmlns="http://java.sun.com/xml/ns/javaee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+
http://java.sun.com/xml/ns/javaee
+
http://java.sun.com/xml/ns/javaee/application_5.xsd">
+
+ <display-name>weld-jsf-translator-ear</display-name>
+ <description>The Weld JSF translator example (EAR)</description>
<module>
<web>
- <web-uri>webbeans-translator.war</web-uri>
- <context-root>/webbeans-translator</context-root>
+ <web-uri>weld-translator.war</web-uri>
+ <context-root>/weld-translator</context-root>
</web>
</module>
<module>
- <ejb>webbeans-translator.jar</ejb>
+ <ejb>weld-translator.jar</ejb>
</module>
</application>]]></programlisting>
</tip>
<para>
- Next, lets look at the war. Just as in the numberguess example, we have
- a <literal>faces-config.xml</literal> (to enable Facelets) and a
- <literal>web.xml</literal> (to enable JSF) in
- <literal>WebContent/WEB-INF</literal>.
+ Next, lets look at the WAR, which is located in the example's
<literal>war</literal> directory. Just as in the
+ numberguess example, we have a <literal>faces-config.xml</literal>
for JSF 2.0 and a <literal>web.xml</literal>
+ (to activate JSF) under WEB-INF, both sourced from
<literal>src/main/webapp/WEB-INF</literal>.
</para>
<para>
- More intersting is the facelet used to translate text. Just as in
- the numberguess example we have a template, which surrounds the form
- (ommitted here for brevity):
+ More intersting is the JSF view used to translate text. Just as in the
numberguess example we have a template,
+ which surrounds the form (ommitted here for brevity):
</para>
- <programlisting role="XML"><![CDATA[<h:form
id="NumberGuessMain">
-
+ <programlisting role="XML"><![CDATA[<h:form
id="translator">
+
<table>
- <tr align="center" style="font-weight: bold" >
+ <tr align="center" style="font-weight: bold">
<td>
Your text
</td>
@@ -1406,10 +1739,10 @@
</tr>
<tr>
<td>
- <h:inputTextarea id="text" value="#{translator.text}"
required="true" rows="5" cols="80" />
+ <h:inputTextarea id="text" value="#{translator.text}"
required="true" rows="5" cols="80"/>
</td>
<td>
- <h:outputText value="#{translator.translatedText}" />
+ <h:outputText value="#{translator.translatedText}"/>
</td>
</tr>
</table>
@@ -1420,93 +1753,128 @@
</h:form>]]></programlisting>
<para>
- The user can enter some text in the lefthand textarea, and hit the
- translate button to see the result to the right.
+ The user can enter some text in the left-hand textarea, and hit the translate
button to see the result to the
+ right.
</para>
<para>
- Finally, let's look at the ejb module,
- <literal>webbeans-translator-ejb</literal>.
- In <literal>src/main/resources/META-INF</literal> there is just an
- empty <literal>web-beans.xml</literal>, used to mark the archive as
- containing Web Beans.
+ Finally, let's look at the EJB module, which is located in the example's
<literal>ejb</literal> directory. In
+ <literal>src/main/resources/META-INF</literal> there is just an
empty <literal>beans.xml</literal>, used to
+ mark the archive as containing beans.
</para>
<para>
- We've saved the most interesting bit to last, the code! The project has
- two simple beans, <literal>SentenceParser</literal> and
- <literal>TextTranslator</literal> and two enterprise beans,
- <literal>TranslatorControllerBean</literal> and
- <literal>SentenceTranslator</literal>. You should be getting quite
- familiar with what a Web Bean looks like by now, so we'll just
- highlight the most interesting bits here.
+ We've saved the most interesting bit to last, the code! The project has two
simple beans,
+ <literal>SentenceParser</literal> and
<literal>TextTranslator</literal> and two enterprise beans,
+ <literal>TranslatorControllerBean</literal> and
<literal>SentenceTranslator</literal>. You should be getting
+ quite familiar with what a bean looks like by now, so we'll just highlight
the most interesting bits here.
</para>
<para>
- Both <literal>SentenceParser</literal> and
- <literal>TextTranslator</literal> are dependent beans, and
- <literal>TextTranslator</literal> uses constructor initialization:
+ Both <literal>SentenceParser</literal> and
<literal>TextTranslator</literal> are dependent beans, and
+ <literal>TextTranslator</literal> uses constructor injection:
</para>
- <programlisting role="JAVA"><![CDATA[public class TextTranslator
{
+ <programlisting role="JAVA"><![CDATA[public class TextTranslator
implements Serializable {
+
private SentenceParser sentenceParser;
- private Translator sentenceTranslator;
+
+ @EJB private Translator translator;
- @Initializer
- TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator)
- {
+ @Inject public TextTranslator(SentenceParser sentenceParser) {
this.sentenceParser = sentenceParser;
- this.sentenceTranslator = sentenceTranslator;]]></programlisting>
+ }
+
+ public String translate(String text) {
+ StringBuilder sb = new StringBuilder();
+ for (String sentence: sentenceParser.parse(text)) {
+ sb.append(translator.translate(sentence)).append(". ");
+ }
+ return sb.toString().trim();
+ }
+
+}]]></programlisting>
<para>
- <literal>TextTranslator</literal> is a stateless bean (with a local
- business interface), where the magic happens - of course, we couldn't
- develop a full translator, but we gave it a good go!
+ <literal>TextTranslator</literal> uses the simple bean (really just
a plain Java class!)
+ <literal>SentenceParser</literal> to parse the sentence and then
calls on the stateless bean with the local
+ business interface <literal>Translator</literal> to perform the
translation. That's where the magic happens.
+ Of course, we couldn't develop a full translator, but it's convincing
enough to anyone who doesn't understand
+ Latin!
</para>
-
+
+ <programlisting role="JAVA"><![CDATA[@Stateless
+public class SentenceTranslator implements Translator {
+
+ public String translate(String sentence) {
+ return "Lorem ipsum dolor sit amet";
+ }
+
+}]]></programlisting>
+
<para>
- Finally, there is UI orientated controller, that collects the text from
- the user, and dispatches it to the translator. This is a request
- scoped, named, stateful session bean, which injects the translator.
+ Finally, there is UI orientated controller. This is a request scoped, named,
stateful session bean, which
+ injects the translator. It collects the text from the user and dispatches it to
the translator. The bean also
+ has getters and setters for all the fields on the page.
</para>
<programlisting role="JAVA"><![CDATA[@Stateful
@RequestScoped
@Named("translator")
-public class TranslatorControllerBean implements TranslatorController
-{
+public class TranslatorControllerBean implements TranslatorController {
+
+ @Inject private TextTranslator translator;
- @Current TextTranslator translator;]]></programlisting>
+ private String inputText;
+ private String translatedText;
+
+ public void translate() {
+ translatedText = translator.translate(inputText);
+ }
+
+ public String getText() {
+ return inputText;
+ }
+
+ public void setText(String text) {
+ this.inputText = text;
+ }
+
+ public String getTranslatedText() {
+ return translatedText;
+ }
+
+ @Remove public void remove() {}
+
+}]]></programlisting>
+
<para>
- The bean also has getters and setters for all the fields on the page.
+ [CHECK is this still accurate?] Since this is a stateful session bean, we have
to have a remove method. The
+ bean manager will call the remove method for you when the bean is destroyed; in
this case at the end of the
+ request.
</para>
-
+
<para>
- As this is a stateful session bean, we have to have a remove method:
+ You'll notice in this example the smooth integration between the existing
<literal>@EJB</literal> resource
+ injection annotation and the new <literal>@Inject</literal>
annotation for injecting any managed or session
+ bean. The tight integration with Java EE is a key value proposition of CDI (not
to mention a requirement).
</para>
-
- <programlisting role="JAVA"><![CDATA[ @Remove
- public void remove()
- {
-
- }]]></programlisting>
-
- <para>
- The Web Beans manager will call the remove method for you when the bean
- is destroyed; in this case at the end of the request.
- </para>
+
</section>
<para>
- That concludes our short tour of the Web Beans examples. For more on Web
- Beans , or to help out, please visit
- <ulink
url="http://www.seamframework.org/WebBeans/Development">http...;.
+ That concludes our short tour of the Weld starter examples. For more information on
Weld, or to help out with
+ development, please visit <ulink
+
url="http://www.seamframework.org/Weld/Development">http://w...;.
</para>
<para>
- We need help in all areas - bug fixing, writing new features, writing
- examples and translating this reference guide.
+ We need help in all areas - bug fixing, writing new features, writing examples and
translating this reference
+ guide.
</para>
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
</chapter>
Added: doc/trunk/reference/en-US/images/m2eclipse-wicket-numberguess-import.png
===================================================================
(Binary files differ)
Property changes on:
doc/trunk/reference/en-US/images/m2eclipse-wicket-numberguess-import.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: doc/trunk/reference/en-US/intro.xml
===================================================================
--- doc/trunk/reference/en-US/intro.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/intro.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,538 +1,1000 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="intro">
- <title>Getting started with Web Beans</title>
+ <title>Getting started with JSR-299 (CDI)</title>
- <para>So you're already keen to get started writing your first Web Bean?
- Or perhaps you're skeptical, wondering what kinds of hoops the Web Beans
- specification will make you jump through! The good news is that you've
- probably already written and used hundreds, perhaps thousands of Web Beans.
- You might not even remember the first Web Bean you wrote.</para>
+ <para>
+ So you're keen to get started writing your first bean? Or perhaps you're
skeptical, wondering what kinds of hoops
+ the CDI specification will make you jump through! The good news is that you've
probably already written and used
+ hundreds, perhaps thousands of beans. CDI just helps you make use them in your web
or enterprise application.
+ </para>
+
+ <section id="bean-definition">
+ <title>What is a bean?</title>
+
+ <para>
+ In this section, you'll learn that a bean is exactly what you think it is.
Only now, it has a true identity in
+ Java EE.
+ </para>
+
+ <para>
+ Prior to Java EE 6, there existed no clear definition of a bean in the platform.
Of course, we've been calling
+ Java classes used in web and enterprise applications beans for years.
Third-party frameworks, such as Spring,
+ even have facilities for defining and creating beans; and there are a couple of
bean variants in the platform
+ itself, including EJB session beans and JSF managed beans. What was missing was
a common definition.
+ </para>
+
+ <para>
+ Java EE 6 finally lays down the definition of a bean in the Managed Bean
specification. Managed Beans are
+ defined as container-managed objects with minimal requirements, otherwise known
by their acronym, POJOs (Plain
+ Old Java Objects). They support a small set of basic services, such as resource
injection, lifecycle callbacks
+ and interceptors. Companion specifications, such as EJB and CDI, build on this
basic model. But, <emphasis>at
+ last</emphasis>, there is a universally accepted concept of a bean and a
lightweight component model that's
+ aligned across the Java EE platform.
+ </para>
+
+ <para>
+ With certain, unique exceptions, every Java class that has a constructor with no
parameters (or an alternate
+ constructor designated with the annotation
<literal>@Inject</literal>) is a candidate for becoming a bean. Any
+ EJB session bean is also a candidate. They become beans, specifically CDI beans,
if they reside in a Java EE
+ module that contains a special marker file (META-INF/beans.xml) and if instances
of those classes are managed
+ by the Java EE container. Just know that, for simple JavaBean classes,
there's no special metadata you need to
+ add to make them beans. They just are.
+ </para>
- <section>
- <title>Your first Web Bean</title>
+ <para>
+ The JavaBeans and EJBs you've been writing every day, up until now, have not
been able to take advantage of the
+ new services defined by the CDI specification. But you'll be able to use
every one of them with CDI --
+ allowing the container to create and destroy instances of your beans and
associate them with a designed context
+ (or scope), injecting them into other beans, using them in EL expressions,
specializing them with qualifier
+ annotations, even adding interceptors and decorators to them -- from this point
forward without modifying
+ your code. At most, you'll have to add some annotations.
+ </para>
+
+ <para>
+ Let's see how to create your first bean.
+ </para>
+
+ </section>
+
+ <section id="first-bean">
+ <title>Your first bean (or is it?)</title>
+
+ <para>
+ Suppose that we have two existing Java classes, that we've been using for
years in various applications. The
+ first class parses a string into a list of sentences:
+ </para>
- <para>With certain, very special exceptions, every Java class with a
- constructor that accepts no parameters is a Web Bean. That includes every
- JavaBean. Furthermore, every EJB 3-style session bean is a Web Bean. Sure,
- the JavaBeans and EJBs you've been writing every day have not been able to
- take advantage of the new services defined by the Web Beans specification,
- but you'll be able to use every one of them as Web Beans — injecting
them
- into other Web Beans, configuring them via the Web Beans XML configuration
- facility, even adding interceptors and decorators to them — without
- touching your existing code.</para>
-
- <para>Suppose that we have two existing Java classes, that we've been
using
- for years in various applications. The first class parses a string into a
- list of sentences:</para>
-
- <programlisting role="JAVA"><![CDATA[public class SentenceParser
{
- public List<String> parse(String text) { ... }
+ <programlisting role="JAVA"><![CDATA[public class SentenceParser
{
+ public List<String> parse(String text) { ... }
}]]></programlisting>
- <para>The second existing class is a stateless session bean front-end for an
- external system that is able to translate sentences from one language to
- another:</para>
+ <para>
+ The second existing class is a stateless session bean front-end for an external
system that is able to
+ translate sentences from one language to another:
+ </para>
- <programlisting role="JAVA"><![CDATA[@Stateless
+ <programlisting role="JAVA"><![CDATA[@Stateless
public class SentenceTranslator implements Translator {
- public String translate(String sentence) { ... }
+ public String translate(String sentence) { ... }
}]]></programlisting>
- <para>Where <literal>Translator</literal> is the local
interface:</para>
+ <para>Where <literal>Translator</literal> is the EJB local
interface:</para>
- <programlisting role="JAVA"><![CDATA[@Local
+ <programlisting role="JAVA"><![CDATA[@Local
public interface Translator {
- public String translate(String sentence);
+ public String translate(String sentence);
}]]></programlisting>
- <para>Unfortunately, we don't have a preexisting class that translates
whole
- text documents. So let's write a Web Bean that does this job:</para>
+ <para>
+ Unfortunately, we don't have a class that translates whole text documents.
So let's write a bean for this job:
+ </para>
- <programlisting role="JAVA"><![CDATA[public class TextTranslator
{
+ <programlisting role="JAVA"><![CDATA[public class TextTranslator
{
+ private SentenceParser sentenceParser;
+ private Translator sentenceTranslator;
- private SentenceParser sentenceParser;
- private Translator sentenceTranslator;
+ @Inject
+ TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
+ this.sentenceParser = sentenceParser;
+ this.sentenceTranslator = sentenceTranslator;
+ }
- @Initializer
- TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
- this.sentenceParser = sentenceParser;
- this.sentenceTranslator = sentenceTranslator;
- }
-
- public String translate(String text) {
- StringBuilder sb = new StringBuilder();
- for (String sentence: sentenceParser.parse(text)) {
- sb.append(sentenceTranslator.translate(sentence));
- }
- return sb.toString();
- }
-
+ public String translate(String text) {
+ StringBuilder sb = new StringBuilder();
+ for (String sentence: sentenceParser.parse(text)) {
+ sb.append(sentenceTranslator.translate(sentence));
+ }
+ return sb.toString();
+ }
}]]></programlisting>
- <para>We may obtain an instance of
<literal>TextTranslator</literal> by
- injecting it into a Web Bean, Servlet or EJB:</para>
+ <para>
+ But wait! <literal>TextTranslator</literal> does not have a
constructor with no parameters! Is it still a bean?
+ If you remember, a class that does not have a constructor with no parameters can
still be a bean if it has a
+ constructor annotated <literal>@Inject</literal>.
+ </para>
+
+ <para>
+ As you've guessed, the <literal>@Inject</literal> annotation has
something to do with dependency injection!
+ <literal>@Inject</literal> may be applied to a constructor or method
of a bean, and tells the bean manager to
+ call that constructor or method when instantiating the bean. The bean manager
will inject other beans it finds
+ into the parameters of the constructor or method.
+ </para>
+
+ <para>
+ We may obtain an instance of <literal>TextTranslator</literal> by
injecting it into a constructor, bean
+ "setter" method, producer method, observer method or field of a
JavaBean or EJB session, or a field of a
+ Servlet. The injection is based on the type of the injection point, not the name
of the field, method or
+ argument.
+ </para>
+
+ <para>
+ Let's create a UI controller bean that uses field injection to obtain an
instance of the
+ <literal>TextTranslator</literal>, translating the text entered by a
user:
+ </para>
- <programlisting role="JAVA"><![CDATA[@Initializer
-public setTextTranslator(TextTranslator textTranslator) {
- this.textTranslator = textTranslator;
+ <programlisting role="JAVA"><![CDATA[@Named @RequestScoped
+public class TranslateController {
+ @Inject private TextTranslator textTranslator;
+
+ private String inputText;
+ private String translation;
+
+ // action method, perhaps
+ public void translate() {
+ translation = textTranslator.translate(inputText);
+ }
+
+ public String getInputText() {
+ return inputText;
+ }
+
+ public void setInputText(String text) {
+ this.inputText = text;
+ }
+
+ public String getTranslation() {
+ return translation;
+ }
}]]></programlisting>
- <para>Alternatively, we may obtain an instance by directly calling a method
- of the Web Bean manager:</para>
+ <para>
+ Notice that it isn't necessary to create a getter or setter method to inject
one bean into another. CDI can
+ access the field directly (even if it's private!), which should help
eliminate some wasteful code. The name of
+ the field is arbitrary. It's the field's type that determines what is
injected.
+ </para>
+
+ <para>
+ At system initialization time, the bean manager must validate that exactly one
bean exists which satisfies each
+ injection point. In our example, if no implementation of
<literal>Translator</literal> is available -- if
+ the <literal>SentenceTranslator</literal> EJB was not deployed --
the bean manager would throw an
+ <literal>UnsatisfiedDependencyException</literal>. If more than one
implementation of
+ <literal>Translator</literal> were available, the bean manager would
throw an
+ <literal>AmbiguousDependencyException</literal>. The same for the
<literal>TextTranslator</literal> injection
+ point.
+ </para>
- <programlisting role="JAVA"><![CDATA[TextTranslator tt =
manager.getInstanceByType(TextTranslator.class);]]></programlisting>
+ <para>
+ Now we are starting to venture off into the details, so let's pause and
examine a bean's anatomy. What aspects
+ of the bean are significant, and what gives it its identity?
+ </para>
- <para>But wait: <literal>TextTranslator</literal> does not have a
constructor
- with no parameters! Is it still a Web Bean? Well, a class that does not have a
- constructor with no parameters can still be a Web Bean if it has a constructor
- annotated <literal>(a)Initializer</literal>.</para>
-
- <para>As you've guessed, the <literal>@Initializer</literal>
annotation has
- something to do with dependency injection!
<literal>@Initializer</literal>
- may be applied to a constructor or method of a Web Bean, and tells the
- Web Bean manager to call that constructor or method when instantiating the
- Web Bean. The Web Bean manager will inject other Web Beans to the parameters
- of the constructor or method.</para>
-
- <para>At system initialization time, the Web Bean manager must validate that
- exactly one Web Bean exists which satisfies each injection point. In our example,
- if no implementation of <literal>Translator</literal> available
— if the
- <literal>SentenceTranslator</literal> EJB was not deployed — the
Web Bean
- manager would throw an <literal>UnsatisfiedDependencyException</literal>.
If
- more than one implementation of <literal>Translator</literal> was
available,
- the Web Bean manager would throw an
- <literal>AmbiguousDependencyException</literal>.</para>
-
- </section>
+ </section>
+
+ <!-- mention alternatives here? -->
+ <section id="bean-anatomy">
+ <title>The anatomy of a bean</title>
-<section>
- <title>What is a Web Bean?</title>
+ <para>
+ A bean is an application class that contains business logic. It may be called
directly from Java code, or it
+ may be invoked via Unified EL. A bean may access transactional resources.
Dependencies between beans are
+ managed automatically by the bean manager. Most beans are
<emphasis>stateful</emphasis> and
+ <emphasis>contextual</emphasis>. The lifecycle of a bean is always
managed by the bean manager.
+ </para>
- <para>So what, <emphasis>exactly</emphasis>, is a Web
Bean?</para>
+ <para>
+ Let's back up a second. What does it really mean to be
<emphasis>contextual</emphasis>? Since beans may be
+ stateful, it matters <emphasis>which</emphasis> bean instance I
have. Unlike a stateless component model (for
+ example, stateless session beans) or a singleton component model (such as
servlets, or singleton beans),
+ different clients of a bean see the bean in different states. The client-visible
state depends upon which
+ instance of the bean the client has a reference to.
+ </para>
- <para>A Web Bean is an application class that contains business logic. A Web
- Bean may be called directly from Java code, or it may be invoked via Unified EL.
- A Web Bean may access transactional resources. Dependencies between Web Beans
- are managed automatically by the Web Bean manager. Most Web Beans are
- <emphasis>stateful</emphasis> and
<emphasis>contextual</emphasis>. The lifecycle
- of a Web Bean is always managed by the Web Bean manager.</para>
+ <para>
+ However, like a stateless or singleton model, but
<emphasis>unlike</emphasis> stateful session beans, the
+ client does not control the lifecycle of the instance by explicitly creating and
destroying it. Instead, the
+ <emphasis>scope</emphasis> of the bean determines:
+ </para>
- <para>Let's back up a second. What does it really mean to be
"contextual"? Since
- Web Beans may be stateful, it matters <emphasis>which</emphasis> bean
instance I
- have. Unlike a stateless component model (for example, stateless session beans)
- or a singleton component model (such as servlets, or singleton beans), different
- clients of a Web Bean see the Web Bean in different states. The client-visible
- state depends upon which instance of the Web Bean the client has a reference
to.</para>
-
- <para>However, like a stateless or singleton model, but
<emphasis>unlike</emphasis>
- stateful session beans, the client does not control the lifecycle of the instance
- by explicitly creating and destroying it. Instead, the
<emphasis>scope</emphasis>
- of the Web Bean determines:</para>
-
- <itemizedlist>
- <listitem>
- <para>the lifecycle of each instance of the Web Bean and</para>
- </listitem>
- <listitem>
- <para>which clients share a reference to a particular instance of the Web
- Bean.</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>the lifecycle of each instance of the bean and</para>
+ </listitem>
+ <listitem>
+ <para>which clients share a reference to a particular instance of the
bean.</para>
+ </listitem>
+ </itemizedlist>
- <para>For a given thread in a Web Beans application, there may be an
- <emphasis>active context</emphasis> associated with the scope of the Web
Bean.
- This context may be unique to the thread (for example, if the Web Bean is request
- scoped), or it may be shared with certain other threads (for example, if the Web
- Bean is session scoped) or even all other threads (if it is application
scoped).</para>
+ <para>
+ For a given thread in a CDI application, there may be an <emphasis>active
context</emphasis> associated with
+ the scope of the bean. This context may be unique to the thread (for example, if
the bean is request scoped),
+ or it may be shared with certain other threads (for example, if the bean is
session scoped) or even all other
+ threads (if it is application scoped).
+ </para>
- <para>Clients (for example, other Web Beans) executing in the same context will
- see the same instance of the Web Bean. But clients in a different context will
- see a different instance.</para>
+ <para>
+ Clients (for example, other beans) executing in the same context will see the
same instance of the bean. But
+ clients in a different context may see a different instance (depending on the
relationship between the
+ contexts).
+ </para>
- <para>One great advantage of the contextual model is that it allows stateful
- Web Beans to be treated like services! The client need not concern itself with
- managing the lifecycle of the Web Bean it is using, <emphasis>nor does it even
- need to know what that lifecyle is.</emphasis> Web Beans interact by passing
- messages, and the Web Bean implementations define the lifecycle of their own state.
- The Web Beans are loosely coupled because:</para>
+ <para>
+ One great advantage of the contextual model is that it allows stateful beans to
be treated like services! The
+ client need not concern itself with managing the lifecycle of the bean it's
using, <emphasis>nor does it even
+ need to know what that lifecyle is.</emphasis> Beans interact by passing
messages, and the bean implementations
+ define the lifecycle of their own state. The beans are loosely coupled because:
+ </para>
- <itemizedlist>
- <listitem>
- <para>they interact via well-defined public APIs</para>
- </listitem>
- <listitem>
- <para>their lifecycles are completely decoupled</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>they interact via well-defined public APIs</para>
+ </listitem>
+ <listitem>
+ <para>their lifecycles are completely decoupled</para>
+ </listitem>
+ </itemizedlist>
- <para>We can replace one Web Bean with a different Web Bean that implements the
- same API and has a different lifecycle (a different scope) without affecting the
- other Web Bean implementation. In fact, Web Beans defines a sophisticated
- facility for overriding Web Bean implementations at deployment time, as we will
- see in <xref linkend="deploymenttypes"/>.</para>
+ <para>
+ We can replace one bean with another different bean that implements the same
interface and has a different lifecycle
+ (a different scope) without affecting the other bean implementation. In fact,
CDI defines a simple facility for
+ overriding bean implementations at deployment time, as we will see in <xref
linkend="alternatives"/> (FIXREF).
+ </para>
- <para>Note that not all clients of a Web Bean are Web Beans. Other objects
- such as Servlets or Message-Driven Beans — which are by nature not
injectable,
- contextual objects — may also obtain references to Web Beans by
injection.</para>
+ <para>
+ Note that not all clients of a bean are beans themselves. Other objects such as
Servlets or Message-Driven
+ Beans -- which are by nature not injectable, contextual objects -- may also
obtain references to beans by
+ injection.
+ </para>
- <para>Enough hand-waving. More formally, according to the spec:</para>
+ <para>Enough hand-waving. More formally, the anatomy of a bean, according to
the spec:</para>
- <blockquote>
+ <blockquote>
- <para>A Web Bean comprises:</para>
+ <para>A bean comprises of the following attributes:</para>
- <itemizedlist>
- <listitem><para>A (nonempty) set of API
types</para></listitem>
- <listitem><para>A (nonempty) set of binding annotation
types</para></listitem>
- <listitem><para>A scope</para></listitem>
- <listitem><para>A deployment type</para></listitem>
- <listitem><para>Optionally, a Web Bean
name</para></listitem>
- <listitem><para>A set of interceptor binding
types</para></listitem>
- <listitem><para>A Web Bean implementation</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>A (nonempty) set of bean
types</para></listitem>
+ <listitem><para>A (nonempty) set of
qualifiers</para></listitem>
+ <listitem><para>A scope</para></listitem>
+ <listitem><para>A deployment type</para></listitem>
+ <listitem><para>Optionally, a bean EL
name</para></listitem>
+ <listitem><para>A set of interceptor
bindings</para></listitem>
+ <listitem><para>A bean
implementation</para></listitem>
+ </itemizedlist>
- </blockquote>
+ </blockquote>
- <para>Let's see what some of these terms mean, to the Web Bean
developer.</para>
+ <para>Let's see what some of these terms mean, to the CDI
developer.</para>
-<section>
- <title>API types, binding types and dependency injection</title>
+ <section>
+ <title>Bean types, qualifiers and dependency injection</title>
- <para>Web Beans usually acquire references to other Web Beans via dependency
- injection. Any injected attribute specifies a "contract" that must be
- satisfied by the Web Bean to be injected. The contract is:</para>
+ <para>
+ Beans usually acquire references to other beans via dependency injection. Any
injected attribute specifies a
+ "contract" that must be satisfied by the bean to be injected. The
contract is:
+ </para>
- <itemizedlist>
- <listitem><para>an API type, together with</para></listitem>
- <listitem><para>a set of binding types.</para></listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem><para>a bean type, together
with</para></listitem>
+ <listitem><para>a set of
qualifiers.</para></listitem>
+ </itemizedlist>
- <para>An API is a user-defined class or interface. (If the Web Bean is an
- EJB session bean, the API type is the <literal>@Local</literal> interface
or
- bean-class local view). A binding type represents some client-visible semantic
- that is satisfied by some implementations of the API and not by others.</para>
+ <para>
+ A bean type is a user-defined class or interface; types that are
client-visible. If the bean is an EJB
+ session bean, the bean type is the <literal>@Local</literal>
interface or bean-class local view. A bean may
+ have multiple bean types. For example, the following bean has four bean
types:
+ </para>
- <para>Binding types are represented by user-defined annotations that are
- themselves annotated <literal>@BindingType</literal>. For example, the
following
- injection point has API type <literal>PaymentProcessor</literal> and
binding
- type <literal>@CreditCard</literal>:</para>
+ <programlisting role="JAVA"><![CDATA[public class BookShop
extends Business implements Shop<Book> {
+ ...
+}]]></programlisting>
-<programlisting role="JAVA"><![CDATA[@CreditCard PaymentProcessor
paymentProcessor]]></programlisting>
+ <para>
+ The bean types are <literal>BookShop</literal>,
<literal>Business</literal> and
+ <literal>Shop<Book></literal>, as well as the
implicit type <literal>java.lang.Object</literal>.
+ (Notice that a parameterized type is a legal bean type). Meanwhile, this
session bean has only the local
+ interfaces <literal>BookShop</literal>,
<literal>Auditable</literal> and
<literal>java.lang.Object</literal>
+ as bean types, since the bean class,
<literal>BookShopBean</literal> is not a client-visible type.
+ </para>
- <para>If no binding type is explicitly specified at an injection point, the
- default binding type <literal>@Current</literal> is assumed.</para>
+ <programlisting role="JAVA"><![CDATA[@Stateful
+public class BookShopBean extends Business implements BookShop, Auditable {
+ ...
+}]]></programlisting>
- <para>For each injection point, the Web Bean manager searches for a Web Bean
- which satisfies the contract (implements the API, and has all the binding
- types), and injects that Web Bean.</para>
+ <note>
+ <para>
+ Most bean types you can probably figure out. One gotcha is primitive
types. All primitive types are assumed
+ to be identical to their corresponding wrapper types in
<literal>java.lang</literal>.
+ </para>
+ </note>
- <para>The following Web Bean has the binding type
<literal>@CreditCard</literal>
- and implements the API type <literal>PaymentProcessor</literal>. It could
- therefore be injected to the example injection point:</para>
+ <para>
+ Bean types may be restricted to an explicit set by annotating the bean with
the <literal>@Typed</literal>
+ annotation and listing the bean types in the value of the annotation. For
instance, this bean has been
+ restricted to a single bean type, <literal>Shop</literal>:
+ </para>
-<programlisting role="JAVA"><![CDATA[@CreditCard
-public class CreditCardPaymentProcessor
- implements PaymentProcessor { ... }]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[(a)Typed(Shop.class)
+public class BookShop extends Business implements Shop<Book> {
+ ...
+}]]></programlisting>
- <para>If a Web Bean does not explicitly specify a set of binding types, it has
- exactly one binding type: the default binding type
<literal>(a)Current</literal>.</para>
+ <para>
+ The bean types alone often do not provide enough information for the bean
manager to know which bean to
+ inject. For instance, say you have two implementations of the
<literal>PaymentProcessor</literal> interface:
+ <literal>CreditCardPaymentProcessor</literal> and
<literal>DebitPaymentProcessor</literal>. Injecting into a
+ field of type <literal>PaymentProcessor</literal> introduces an
ambigious condition. In these cases, the
+ bean manager must rely on some client-visible semantic that is satisified by
one implementation of the bean
+ type, but not by others. That semantic is called a qualifier.
+ </para>
- <para>Web Beans defines a sophisticated but intuitive <emphasis>resolution
- algorithm</emphasis> that helps the container decide what to do if there is more
- than one Web Bean that satisfies a particular contract. We'll get into the
- details in <xref linkend="injection"/>.</para>
+ <para>
+ Qualifiers are represented by user-defined annotations that are themselves
annotated with
+ <literal>@Qualifer</literal>. These annotations extend the type
system in Java to let you further qualify
+ the type without having to fall back to string-based names as many dependency
injection frameworks use.
+ Here's an example of a qualifier annotation:
+ </para>
-</section>
+ <programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD,
PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+@Qualifier
+public @interface CreditCard {}]]></programlisting>
-<section>
- <title>Deployment types</title>
+ <para>
+ You may not be used to seeing the definition of an annotation. In fact, this
might be the first time you
+ have encountered one. With CDI, they will become very familiar artifact as
you will be creating them often.
+ Pay attention to the names of the built-in annotations in CDI and EJB.
+ </para>
+
+ <tip>
+ <para>
+ You'll notice that they are all adjectives. You are encouraged to
follow this convention when creating
+ your custom annotations, since they serve to describe the behaviors and
roles of the class.
+ </para>
+ </tip>
+
+ <para>
+ Now that we have defined a qualifier annotation, we can use it. The following
injection point has the bean
+ type <literal>PaymentProcessor</literal> and qualifier
<literal>@CreditCard</literal>:
+ </para>
- <para><emphasis>Deployment types</emphasis> let us classify our Web
Beans by
- deployment scenario. A deployment type is an annotation that represents a particular
- deployment scenario, for example <literal>@Mock</literal>,
<literal>@Staging</literal>
- or <literal>@AustralianTaxLaw</literal>. We apply the annotation to Web
Beans which
- should be deployed in that scenario. A deployment type allows a whole set of Web Beans
- to be conditionally deployed, with a just single line of configuration.</para>
+ <programlisting role="JAVA"><![CDATA[@Inject @CreditCard
PaymentProcessor paymentProcessor]]></programlisting>
- <para>Many Web Beans just use the default deployment type
<literal>@Production</literal>,
- in which case no deployment type need be explicitly specified. All three Web Bean
- in our example have the deployment type
<literal>(a)Production</literal>.</para>
+ <note>
+ <para>
+ If no qualifier is specified at an injection point, the default qualifier,
<literal>@Default</literal>, is
+ assumed.
+ </para>
+ </note>
- <para>In a testing environment, we might want to replace the
<literal>SentenceTranslator</literal>
- Web Bean with a "mock object":</para>
+ <para>
+ For each injection point, the bean manager searches for a bean which
satisfies the contract, meaning it
+ matches the bean time and all the qualifiers. It then injects that instance.
+ </para>
-<programlisting role="JAVA"><![CDATA[@Mock
-public class MockSentenceTranslator implements Translator {
- public String translate(String sentence) {
- return "Lorem ipsum dolor sit amet";
- }
-}]]></programlisting>
+ <para>
+ We've seen how to indicate that you want to inject qualified bean. But
how do you actually qualify the bean?
+ By using the annotation, of course! The following bean has the qualifier
<literal>@CreditCard</literal>
+ and implements the bean type <literal>PaymentProcessor</literal>.
Therefore, it satisfies our qualified
+ injection point:
+ </para>
+ <programlisting role="JAVA"><![CDATA[@CreditCard
+public class CreditCardPaymentProcessor
+ implements PaymentProcessor { ... }]]></programlisting>
- <para>We would enable the deployment type <literal>@Mock</literal> in
our testing
- environment, to indicate that <literal>MockSentenceTranslator</literal> and
any other
- Web Bean annotated <literal>@Mock</literal> should be used.</para>
+ <note>
+ <para>
+ If a bean does not explicitly specify a qualifier, it has exactly one
qualifier, the default qualifier,
+ <literal>@Default</literal>.
+ </para>
+ </note>
- <para>We'll talk more about this unique and powerful feature in
- <xref linkend="deploymenttypes"/>.</para>
+ <para>
+ CDI defines a sophisticated, yet intuitive <emphasis>resolution
algorithm</emphasis> that helps the
+ container decide what to do if there is more than one bean that satisfies a
particular contract. We'll get
+ into the details in <xref linkend="injection"/>.
+ </para>
-</section>
+ </section>
-<section>
- <title>Scope</title>
+ <section>
+ <title>Scope</title>
+ <!-- I wonder whether the explaination of contextual above would fit better
here -->
- <para>The <emphasis>scope</emphasis> defines the lifecycle and
visibility
- of instances of the Web Bean. The Web Beans context model is extensible,
- accommodating arbitrary scopes. However, certain important scopes are
- built-in to the specification, and provided by the Web Bean manager. A
- scope is represented by an annotation type.</para>
+ <para>
+ The <emphasis>scope</emphasis> of a bean defines the lifecycle
and visibility of instances created from it.
+ The CDI context model is extensible, accommodating arbitrary scopes. However,
certain important scopes are
+ built-in to the specification, and provided by the bean manager. Each scope
is represented by an annotation
+ type.
+ </para>
- <para>For example, any web application may have <emphasis>session
scoped</emphasis>
- Web Beans:</para>
+ <para>
+ For example, any web application may have <emphasis>session
scoped</emphasis> bean:
+ </para>
-<programlisting role="JAVA"><![CDATA[@SessionScoped
+ <programlisting role="JAVA"><![CDATA[@SessionScoped
public class ShoppingCart { ... }]]></programlisting>
- <para>An instance of a session scoped Web Bean is bound to a user session
+ <para>An instance of a session-scoped bean is bound to a user session
and is shared by all requests that execute in the context of that
session.</para>
- <para>By default, Web Beans belong to a special scope called the
- <emphasis>dependent pseudo-scope</emphasis>. Web Beans with this scope are
- pure dependent objects of the object into which they are injected, and their
- lifecycle is bound to the lifecycle of that object.</para>
+ <note>
+ <para>
+ Keep in mind that once a bean is bound to a context, it remains in that
context until the context is
+ destroyed. There is no way to explicitly remove a bean from a context. If
you don't the bean to live in
+ the session indefinitely, consider using another scope such as the request
or conversation scope instead.
+ </para>
+ </note>
- <para>We'll talk more about scopes in <xref
linkend="scopescontexts"/>.</para>
+ <para>
+ If a scope is not explicitly specified, then the bean belongs to a special
scope called the
+ <emphasis>dependent pseudo-scope</emphasis>. Beans with this
scope live to serve the bean into which they
+ are injected, which means their life cycle is bound to the life cycle of that
object.
+ </para>
-</section>
+ <para>We'll talk more about scopes in <xref
linkend="scopescontexts"/>.</para>
-<section>
- <title>Web Bean names and Unified EL</title>
+ </section>
- <para>A Web Bean may have a <emphasis>name</emphasis>, allowing it to
be
- used in Unified EL expressions. It's easy to specify the name of a Web
- Bean:</para>
+ <section>
+ <title>EL name</title>
-<programlisting role="JAVA"><![CDATA[@SessionScoped
@Named("cart")
+ <para>
+ If you want to reference a bean outside of Java, such as in JSF view, you
must assign the bean a
+ <emphasis>name</emphasis>. The name is used as the EL name of the
bean, allowing the bean to be used
+ in a Unified EL expression.
+ </para>
+
+ <para>
+ The name is specified using the <literal>@Named</literal>
annotation, as shown here:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@SessionScoped
@Named("cart")
public class ShoppingCart { ... }]]></programlisting>
- <para>Now we can easily use the Web Bean in any JSF or JSP page:</para>
+ <para>Now we can easily use the bean in any JSF or JSP page:</para>
-<programlisting role="HTML"><![CDATA[<h:dataTable
value="#{cart.lineItems}" var="item">
- ....
+ <programlisting role="XML"><![CDATA[<h:dataTable
value="#{cart.lineItems}" var="item">
+ ...
</h:dataTable>]]></programlisting>
- <para>It's even easier to just let the name be defaulted by the Web Bean
- manager:</para>
+ <note>
+ <para>
+ The <literal>@Named</literal> annotation is not what makes the
class a bean. Most classes in a bean
+ archive are already recognized as beans. The
<literal>@Named</literal> annotation just makes it
+ possible to reference the bean from the EL, most commonly from a JSF
view.
+ </para>
+ </note>
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Named
+ <para>
+ If you want, you can let CDI select a name for you by leaving off the
+ value of the <literal>@Named</literal> annotation:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@SessionScoped @Named
public class ShoppingCart { ... }]]></programlisting>
- <para>In this case, the name defaults to
<literal>shoppingCart</literal> — the
- unqualified class name, with the first character changed to lowercase.</para>
+ <para>
+ The name defaults to the unqualified class name, decapitalized; in this
case,
+ <literal>shoppingCart</literal>.
+ </para>
-</section>
+ </section>
-<section>
- <title>Interceptor binding types</title>
-
- <para>Web Beans supports the interceptor functionality defined by EJB 3,
- not only for EJB beans, but also for plain Java classes. In addition,
- Web Beans provides a new approach to binding interceptors to EJB beans
- and other Web Beans.</para>
-
- <para>It remains possible to directly specify the interceptor class via
- use of the <literal>@Interceptors</literal> annotation:</para>
-
-<programlisting role="JAVA"><![CDATA[@SessionScoped
-(a)Interceptors(TransactionInterceptor.class)
-public class ShoppingCart { ... }]]></programlisting>
+ <section>
+ <title>Alternatives</title>
- <para>However, it is more elegant, and better practice, to indirect the
- interceptor binding through an <emphasis>interceptor binding
- type</emphasis>:</para>
-
-<programlisting role="JAVA"><![CDATA[@SessionScoped @Transactional
+ <para>
+ There are cases when you want to replace one bean implementation with another
at deployment time. For
+ instance, you may want to use a mock implementation in a testing environment.
An
+ <emphasis>alternative</emphasis> may be declared by annotating
the bean class or producer method or field
+ with the <literal>@Alternative</literal> annotation.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Alternative
+public class MockPaymentProcessor extends PaymentProcessorImpl { ...
}]]></programlisting>
+
+ <para>
+ You then enable the alternative using the CDI deployment descriptor,
META-INF/beans.xml, in the classpath
+ entry in which you intent to use it. An alternative must be explicitly
selected in every bean deployment
+ archive in which the alternative should be available for injection, lookup
and EL resolution.
+ </para>
+
+ <para>
+ Details on how to enable alternative beans, and how you can use them to
specialize (override) beans and
+ producer methods is covered in <xref
linkend="specialization"/>. CDI is very flexible when it comes
+ alternatives that are selected at deployment time.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Interceptor binding types</title>
+
+ <para>
+ Since the introduction of the Managed Bean specification in Java EE 6,
interceptors are available on
+ JavaBeans in additionn to EJB session beans. That's right, you no longer
have to create an EJB just to
+ intercept method calls. Holler. So what does CDI have to offer? Well, a lot
actually. Let's cover some
+ background.
+ </para>
+
+ <para>
+ The way that interceptors are defined in Java EE 5 is counter-intuitive. You
are required to specify the
+ <emphasis>implementation</emphasis> of the interceptor directly
on the <emphasis>implementation</emphasis>
+ of the EJB, either in the <literal>@Interceptors</literal>
annotation or in the XML descriptor. You might as
+ well just put the interceptor code <emphasis>in</emphasis> the
implementation. Second, the order in which
+ the interceptors are applied is taken from the order in which they are
declared in the annotation or the XML
+ descriptor. Perhaps this isn't so bad if you're applying the
interceptors to a single bean. But, if you are
+ applying them repeatly, then there is a chance that you'll inadvertly
define a different order for different
+ beans. Now that is a problem.
+ </para>
+
+ <para>
+ CDI provides a new approach to binding interceptors to beans that introduces
a level of abstraction (and
+ thus control). You define a special kind of annotation called an
<emphasis>interceptor binding
+ type</emphasis> whose name describes the role of the interceptor, in
this case to add transaction support:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@InterceptorBinding
+@Inherited
+@Target( { TYPE, METHOD })
+@Retention(RUNTIME)
+public @interface Transactional {}]]></programlisting>
+
+ <para>
+ Then you apply the annotation to the class whose methods you wish to have
intercepted.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@SessionScoped
@Transactional
public class ShoppingCart { ... }]]></programlisting>
- <para>We'll discuss Web Beans interceptors and decorators in
- <xref linkend="interceptors"/> and <xref
linkend="decorators"/>.</para>
+ <para>
+ Where is the interceptor? You match the interceptor(s) to apply to the bean
by also annotating the
+ interceptor class. Never do the two implementations (bean and interceptor)
come in direct contact.
+ Activating and ordering of the interceptors is then controlled by the XML
descriptor, one of the few times
+ XML is warranted.
+ </para>
+
+ <para>
+ We'll discuss bean interceptors, and their cousins, decorators, in
<xref linkend="interceptors"/> and <xref
+ linkend="decorators"/>.
+ </para>
-</section>
+ </section>
-</section>
+ </section>
-<section>
- <title>What kinds of objects can be Web Beans?</title>
-
- <para>We've already seen that JavaBeans, EJBs and some other Java classes
can
- be Web Beans. But exactly what kinds of objects are Web Beans?</para>
-
- <section>
- <title>Simple Web Beans</title>
-
- <para>The Web Beans specification says that a concrete Java class is a
- <emphasis>simple</emphasis> Web Bean if:</para>
-
- <itemizedlist>
- <listitem>
- <para>it is not an EE container-managed component, like an EJB, a Servlet
- or a JPA entity,</para>
- </listitem>
- <listitem>
- <para>it is not a non-static static inner class,</para>
- </listitem>
- <listitem>
- <para>it is not a parameterized type, and</para>
- </listitem>
- <listitem>
- <para>it has a constructor with no parameters, or a constructor annotated
- <literal>(a)Initializer</literal>.</para>
- </listitem>
- </itemizedlist>
-
- <para>Thus, almost every JavaBean is a simple Web Bean.</para>
-
- <para>Every interface implemented directly or indirectly by a simple Web Bean
- is an API type of the simple Web Bean. The class and its superclasses are also
- API types.</para>
-
- </section>
-
- <section>
- <title>Enterprise Web Beans</title>
-
- <para>The specification says that all EJB 3-style session and singleton beans
- are <emphasis>enterprise</emphasis> Web Beans. Message driven beans are
not
- Web Beans — since they are not intended to be injected into other
- objects — but they can take advantage of most of the functionality of Web
- Beans, including dependency injection and interceptors.</para>
-
- <para>Every local interface of an enterprise Web Bean that does not have a
- wildcard type parameter or type variable, and every one of its superinterfaces,
- is an API type of the enterprise Web Bean. If the EJB bean has a bean class
- local view, the bean class, and every one of its superclasses, is also an API
- type.</para>
-
- <para>Stateful session beans should declare a remove method with no parameters
- or a remove method annotated <literal>@Destructor</literal>. The Web
Bean
- manager calls this method to destroy the stateful session bean instance at the
- end of its lifecycle. This method is called the
<emphasis>destructor</emphasis>
- method of the enterprise Web Bean.</para>
-
-<programlisting role="JAVA"><![CDATA[@Stateful @SessionScoped
-public class ShoppingCart {
+ <section>
+ <title>What kinds of classes can be beans?</title>
+
+ <para>
+ We've already seen that JavaBeans and EJBs can be (CDI) beans. Is that the
whole story? Let's start from what
+ we know, and go from there.
+ </para>
+
+ <section>
+ <title>Managed beans</title>
- ...
-
- @Remove
- public void destroy() {}
+ <para>
+ A managed bean is a bean that is implemented by almost any Java class. This
class is called the bean class
+ of the managed bean. The basic lifecycle and semantics of a managed bean is
defined by the Managed Beans
+ specification. If the class is not picked up as a managed bean by the
container, then CDI will allow it
+ to be a bean if:
+ </para>
-}]]></programlisting>
+ <itemizedlist>
+ <listitem>
+ <para>It is not a non-static inner class.</para>
+ </listitem>
+ <listitem>
+ <para>It is a concrete class, or is annotated
<literal>(a)Decorator</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>
+ It is not annotated with an EJB component-defining annotation or
declared as an EJB bean class in
+ ejb-jar.xml.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ It has an appropriate constructor -- either:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>the class has a constructor with no parameters,
or</para>
+ </listitem>
+ <listitem>
+ <para>the class declares a constructor annotated
<literal>(a)Inject</literal>.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
- <para>So when should we use an enterprise Web Bean instead of a simple Web
Bean?
- Well, whenever we need the advanced enterprise services offered by EJB, such
- as:</para>
-
-
- <itemizedlist>
- <listitem>
- <para>method-level transaction management and security,</para>
- </listitem>
- <listitem>
- <para>concurrency management,</para>
- </listitem>
- <listitem>
- <para>instance-level passivation for stateful session beans and
- instance-pooling for stateless session beans,</para>
- </listitem>
- <listitem>
- <para>remote and web service invocation, and</para>
- </listitem>
- <listitem>
- <para>timers and asynchronous methods,</para>
- </listitem>
- </itemizedlist>
-
- <para>we should use an enterprise Web Bean. When we don't need any of these
things,
- a simple Web Bean will serve just fine.</para>
-
- <para>Many Web Beans (including any session or application scoped Web Bean)
are
- available for concurrent access. Therefore, the concurrency management provided
- by EJB 3.1 is especially useful. Most session and application scoped Web Beans
- should be EJBs.</para>
-
- <para>Web Beans which hold references to heavy-weight resources, or hold a lot
- of internal state benefit from the advanced container-managed lifecycle defined
- by the EJB
<literal>@Stateless</literal>/<literal>@Stateful</literal>/<literal>@Singleton</literal>
- model, with its support for passivation and instance pooling.</para>
-
- <para>Finally, it's usually obvious when method-level transaction
management,
- method-level security, timers, remote methods or asynchronous methods are
needed.</para>
-
- <para>It's usually easy to start with simple Web Bean, and then turn it
into an
- EJB, just by adding an annotation: <literal>@Stateless</literal>,
- <literal>@Stateful</literal> or
<literal>(a)Singleton</literal>.</para>
+ <para>
+ <emphasis>Unlike</emphasis> the managed bean definition, no
special declaration is required to define a
+ managed bean. CDI takes advantage of the fact that the Managed Bean
specification allows companion
+ specifications to relax the requirement of having to add the
<literal>@ManagedBean</literal> annotation.
+ </para>
- </section>
-
- <section>
- <title>Producer methods</title>
+ <para>
+ Some managed beans are much more. Those are the session beans. While still
technically managed beans, they
+ have enough additional, enterprise features, that we consider them to be
their own kind.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Session beans</title>
- <para>A <emphasis>producer method</emphasis> is a method that is
called by the
- Web Bean manager to obtain an instance of the Web Bean when no instance exists
- in the current context. A producer method lets the application take full control
- of the instantiation process, instead of leaving instantiation to the Web Bean
- manager. For example:</para>
+ <para>
+ EJB 3 session beans belong to the EJB specification. That is, the basic life
cycle and semantics. Beyond
+ that, they get to participate in CDI just like any other bean. There are some
restrictions about which
+ scopes can be assigned to a session bean, but other than that, they are
interchangable with regular managed
+ beans. That means you can inject one session bean into another, a managed
bean into a session bean, a
+ session bean into a managed bean, have a managed bean observe an event raised
by a session bean, and so on.
+ </para>
-<programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Generator {
+ <note>
+ <para>
+ Message-driven and entity beans are by nature non-contextual objects and
may not be injected into other
+ objects. Message-driven beans can take advantage of some CDI
functionality, such as dependency injection
+ and interceptors. In fact, CDI will perform injection into any
message-driven or session bean, even those
+ which are not contextual instances.
+ </para>
+ </note>
- private Random random = new Random( System.currentTimeMillis() );
-
- @Produces @Random int next() {
- return random.nextInt(100);
- }
+ <para>
+ The unrestricted set of bean types for a session bean contains all local
interfaces of the bean and their
+ superinterfaces. If the session bean has a bean class local view, the
unrestricted set of bean types
+ contains the bean class and all superclasses. In addition,
<literal>java.lang.Object</literal> is a bean
+ type of every session bean. But, remote interfaces are
<emphasis>not</emphasis> included in the set of bean
+ types.
+ </para>
+ <para>
+ Stateful session beans can define a no arguments remove method, annotated
<literal>@Remove</literal>, that
+ is used by the application to indicate the instance should be destroyed.
However, in a CDI environment, this
+ method can only be executed by the application if the bean is
dependent-scoped. Otherwise, it's illegal for
+ the application to invoke this method.
+ </para>
+
+ <para>
+ So, when should we use a session instead of a basic managed bean? Whenever we
need the advanced enterprise
+ services offered by EJB, such as:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>method-level transaction management and security,</para>
+ </listitem>
+ <listitem>
+ <para>concurrency management,</para>
+ </listitem>
+ <listitem>
+ <para>instance-level passivation for stateful session beans and
+ instance-pooling for stateless session beans,</para>
+ </listitem>
+ <listitem>
+ <para>remote and web service invocation, and</para>
+ </listitem>
+ <listitem>
+ <para>timers and asynchronous methods,</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>When we don't need any of these things, a basic managed bean
will serve just fine.</para>
+
+ <para>
+ Many beans (including any session or application scoped bean) are available
for concurrent access.
+ Therefore, the concurrency management provided by EJB 3.1 is especially
useful. Most session and application
+ scoped beans should be EJBs.
+ </para>
+
+ <para>
+ Beans which hold references to heavy-weight resources, or hold a lot of
internal state benefit from the
+ advanced container-managed lifecycle defined by the EJB
+
<literal>@Stateless</literal>/<literal>@Stateful</literal>/<literal>@Singleton</literal>
model, with its
+ support for passivation and instance pooling.
+ </para>
+
+ <para>
+ Finally, it's usually obvious when method-level transaction management,
method-level security, timers,
+ remote methods or asynchronous methods are needed.
+ </para>
+
+ <para>
+ The point is, you use a session bean when you need the services it provides,
not just because you want to
+ use dependency injection, life cycle management, or interceptors. The Java EE
programming model makes a
+ whole lot more sense now; you won't need to go off and invent your own
bean container to make programming
+ in Java EE palatable.
+ </para>
+
+ <para>
+ In fact, it's easy to start with simple managed bean, and later turn it
into an EJB just by adding one of
+ the following annotations: <literal>@Stateless</literal>,
<literal>@Stateful</literal> or
+ <literal>@Singleton</literal>.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Producer methods</title>
+
+ <para>
+ Surely not everything you want to inject can be a bean class. What if you
need to inject the implementation
+ of an API that varies at runtime? And how would you inject objects that are
created by another mechanism,
+ such as a JPA result? Fortunately, the CDI specification recognized these and
other cases and introduced the
+ concept of a producer method.
+ </para>
+
+ <para>
+ A <emphasis>producer method</emphasis> is a method on a bean that
is used as a bean source, meaning the
+ method itself describes the bean and the bean manager invokes the method to
obtain an instance of the bean
+ when no instance exists in its specified context. A producer method lets the
application take full control
+ of the instantiation process, specifically when:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ the objects to be injected are not required to be instances of beans,
or
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the concrete type of the objects to be injected may vary at runtime,
or
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the objects require some custom initialization that is not performed by
the bean constructor.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ For example:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class RandomNumberGenerator {
+
+ private Random random = new Random(System.currentTimeMillis());
+
+ @Produces @Named @Random int getRandomNumber() {
+ return random.nextInt(100);
+ }
+
}]]></programlisting>
- <para>The result of a producer method is injected just like any other Web
Bean.</para>
+ <para>
+ Obviously, you cannot define a bean that is itself a random number. A
producer method allows you do define
+ its result as a bean, in this case an <literal>Integer</literal>
with qualifier <literal>@Random</literal>,
+ scope <literal>@Dependent</literal> (implied) and name
<literal>randomNumber</literal> (derived from bean
+ property convention; otherwise it would be the same as the method name). It
can be injected just like any
+ other bean:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject @Random int
randomNumber;]]></programlisting>
- <programlisting role="JAVA"><![CDATA[@Random int
randomNumber]]></programlisting>
-
- <para>The method return type and all interfaces it extends/implements directly
or indirectly
- are API types of the producer method. If the return type is a class, all superclasses
are
- also API types.</para>
-
- <para>Some producer methods return objects that require explicit
destruction:</para>
-
-<programlisting role="JAVA"><![CDATA[@Produces @RequestScoped
Connection connect(User user) {
- return createConnection( user.getId(), user.getPassword() );
+ <para>
+ or used in a Unified EL expression:
+ </para>
+
+ <programlisting><![CDATA[Your raffle number is
#{randomNumber}.]]></programlisting>
+
+ <para>
+ A producer method must be a non-abstract method of a managed bean class or
session bean class. A producer
+ method may be either static or non-static. If the bean is a session bean, the
producer method must be either
+ a business method of the EJB or a static method of the bean class.
+ </para>
+
+ <para>
+ The bean types of a producer method depend upon the method return type:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ If the return type is an interface, the unrestricted set of bean types
contains the return type, all
+ interfaces it extends directly or indirectly and
<literal>java.lang.Object</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a return type is primitive or is a Java array type, the unrestricted
set of bean types contains
+ exactly two types: the method return type and
<literal>java.lang.Object</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the return type is a class, the unrestricted set of bean types
contains the return type, every
+ superclass and all interfaces it implements directly or indirectly.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Some producer methods return objects that require explicit destruction:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Produces @RequestScoped
Connection connect(User user) {
+ return createConnection(user.getId(), user.getPassword());
}]]></programlisting>
- <para>These producer methods may define matching <emphasis>disposal
methods</emphasis>:</para>
-
-<programlisting role="JAVA"><![CDATA[void close(@Disposes Connection
connection) {
- connection.close();
+ <para>
+ If the producer method has method arguments, as in this example, the
container will look for matching beans
+ and pass them into the method automatically -- another form of dependency
injection.
+ </para>
+
+ <para>Producer methods may also define matching <emphasis>disposal
methods</emphasis>:</para>
+
+ <programlisting role="JAVA"><![CDATA[void close(@Disposes
Connection connection) {
+ connection.close();
}]]></programlisting>
+
+ <para>
+ The disposal method is called automatically when the context ends (in this
case, the end of the request).
+ The disposal method requires at least one parameter, the bean produced by the
producer method. Any
+ additional parameters will be satisfied by the container.
+ </para>
+
+ <para>We'll talk much more about producer and disposal methods in
<xref linkend="producermethods"/>.</para>
+
+ </section>
- <para>This disposal method is called automatically by the Web Bean manager at
- the end of the request.</para>
+ <section>
+ <title>Producer fields</title>
- <para>We'll talk much more about producer methods in <xref
linkend="producermethods"/>.</para>
+ <para>
+ A <emphasis>producer field</emphasis> is a simpler alternative to
a producer method and can also marry
+ dependency injection with bean definition. A producer field may be declared
by annotating a field of a
+ managed bean class or session bean class with the
<literal>@Produces</literal> annotation previously used on
+ producer methods.
+ </para>
- </section>
+ <programlisting role="JAVA"><![CDATA[public class Shop {
+ @Produces PaymentProcessor paymentProcessor = ....;
+ @Produces List<Product> products = ....;
+}]]></programlisting>
- <section>
- <title>JMS endpoints</title>
-
- <para>Finally, a JMS queue or topic can be a Web Bean. Web Beans relieves the
- developer from the tedium of managing the lifecycles of all the various JMS
- objects required to send messages to queues and topics. We'll discuss JMS
- endpoints in <xref linkend="jms"/>.</para>
-
- </section>
+ <para>
+ A producer field may also specify scope, name, stereotypes and/or qualifiers.
It's a good way to expose
+ state from a bean as a top-level bean.
+ </para>
-</section>
+ <programlisting role="JAVA"><![CDATA[public class Shop {
+ @Produces @Wishlist @Named("wishlist") List<Product> products = ....;
+}]]></programlisting>
-</chapter>
\ No newline at end of file
+ <para>
+ The result can be injected or used in a Unified EL expression.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject @Wishlist
List<Product> wishlist;]]></programlisting>
+ <programlisting role="XML"><![CDATA[<h:dataTable
var="_product"
value="#{wishlist}">...</h:dataTable>]]></programlisting>
+
+ <para>
+ The rules for determining the bean types of a producer field parallel the
rules for producer method.
+ </para>
+
+ <para>
+ Aside from convenience, producer fields serve a specific purpose as an
adapter for Java EE resources
+ injections.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Java EE resources</title>
+
+ <para>
+ Java EE 5 already introduced some support for dependency injection, in the
form of resource injections. A
+ resources is either a component defined in JNDI such as a data source or a
container-provided component such
+ as a persistence unit, persistence context, EJB or web service.
+ </para>
+
+ <para>
+ Naturally, there remained some mismatch with the new style of dependency
injection in CDI. Most notably,
+ resource injections rely on string-based names to qualify ambigious types,
and there is no real consistency
+ as to how a resource obtains its name (sometimes JNDI, other times from an
XML descriptor or even a default
+ name). Producer fields turned out to be an elegant adapter to rein them in
and get them to participate in
+ the CDI system just like any other injectable bean.
+ </para>
+
+ <para>
+ Producer fields have a duality in that they can both accept a standard Java
EE resource injection and
+ produce a bean that can be injected into another bean in a typesafe way. Here
are some examples of these
+ injection points. Notice that a qualifier annotation can be assigned at the
injection point to adapt the
+ string-based name required by the injection point into a typesafe qualifier
for injection elsewhere.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Produces
@WebServiceRef(lookup="java:app/service/PaymentService")
+PaymentService paymentService;]]></programlisting>
+
+ <programlisting role="JAVA"><![CDATA[@Produces
@PersistenceContext(unitName="CustomerDatabase")
+@CustomerDatabase EntityManager
customerDatabasePersistenceContext;]]></programlisting>
+
+ <para>
+ These resources can then be injected in the usual way.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Inject PaymentService
paymentService;]]></programlisting>
+ <programlisting role="JAVA"><![CDATA[@Inject
@CustomerDatabase EntityManager
customerDatabaseEntityManager;]]></programlisting>
+
+ <para>
+ The bean type and qualifiers of the resource are determined by the producer
field declaration.
+ </para>
+
+ <para>
+ While you may have to introduce a couple extra managed beans to serve as
typesafe adapters, it's well worth
+ the effort so that you can minimize the number of places in your code you
have to repeat the old-style
+ dependency injection and string-based qualifiers.
+ </para>
+
+ </section>
+
+ <section>
+ <title>Built-in beans</title>
+
+ <para>
+ Java EE gives you some other goodies in the form of built-in beans. A Java EE
(or embeddable EJB) container
+ provide the following built-in beans, all of which have qualifier
<literal>@Default</literal>:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ a bean with bean type
<literal>javax.transaction.UserTransaction</literal>, allowing injection of a
+ reference to the JTA <literal>UserTransaction</literal>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a bean with bean type
<literal>javax.security.Principal</literal>, allowing injection of a
+ <literal>Principal</literal> representing the current
caller identity.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a bean with bean type
<literal>javax.validation.ValidationFactory</literal>, allowing injection of
the
+ default <ulink
src="http://jcp.org/en/jsr/detail?id=303">Bean Validation</ulink>
+ <literal>ValidationFactory</literal>, and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a bean with bean type
<literal>javax.validation.Validator</literal>, allowing injection of a
Validator
+ for the default Bean Validation
<literal>ValidationFactory</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Aren't you excited to start using this stuff? Wait no longer. In the next
two chapters, we'll look at some
+ examples.
+ </para>
+
+ </section>
+
+ </section>
+
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</chapter>
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/master.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,33 +1,33 @@
<?xml version='1.0' encoding="iso-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
<book lang="en">
- <xi:include href="Book_Info.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <preface>
+ <xi:include href="Book_Info.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <preface>
<title>Note</title>
<para>
- JSR-299 has recently changed its name from "Web Beans" to "Java
- Contexts and Dependency Injection". The reference guide still refers
- to JSR-299 as "Web Beans" and the JSR-299 Reference Implementation as
- the "Web Beans RI". Other documentation, blogs, forum posts etc. may
- use the new nomenclature, including the new name for the JSR-299
- Reference Implementation - "Web Beans".
+ Shortly before the final draft of JSR-299 was submitted, the specification
changed its name from "Web Beans" to
+ "Java Contexts and Dependency Injection for the Java EE platform",
abbreviated CDI. For a brief period after
+ the renaming, the reference implementation adopted the name "Web
Beans". However, this ended up causing more
+ confusion than it solved and Red Hat decided to change the name of the reference
implementation to "Weld". You
+ may still find other documentation, blogs, forum posts, etc. that use the old
nomenclature. Please update any
+ references you can. The naming game is over.
</para>
-
+
<para>
- You'll also find that some of the more recent functionality to be
- specified is missing (such as producer fields, realization,
- asynchronous events, XML mapping of EE resources).
+ You'll also find that some of the functionality that once existed in the
specification is now missing, such as
+ defining beans in XML. These features will be available as portable extensions
for CDI in the Weld project, and
+ perhaps other implementations.
</para>
- </preface>
-
- <toc/>
-
- <part>
- <title>Using contextual objects</title>
+ </preface>
+
+ <toc/>
+
+ <part>
+ <title>Contextual components, loose-coupling and strong typing</title>
<xi:include href="part1.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="intro.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
@@ -36,20 +36,20 @@
<xi:include href="injection.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="scopescontexts.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="producermethods.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
-
- <part>
+
+ </part>
+
+ <part>
<title>Developing loosely-coupled code</title>
<xi:include href="part2.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="interceptors.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="decorators.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="events.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
-
- <part>
+
+ </part>
+
+ <part>
<title>Making the most of strong typing</title>
<xi:include href="part3.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
@@ -58,33 +58,34 @@
<xi:include href="specialization.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="xml.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
- </part>
-
- <part>
- <title>Web Beans and the Java EE ecosystem</title>
+ </part>
+
+ <part>
+ <title>CDI and the Java EE ecosystem</title>
<xi:include href="part4.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="ee.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="extend.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ </part>
+
+ <xi:include href="next.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <part>
+ <title>Weld reference</title>
- </part>
-
- <xi:include href="next.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <part>
- <title>Web Beans Reference</title>
-
<xi:include href="part5.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="environments.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="extensions.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="viewlayers.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- </part>
+
+ </part>
+
+ <xi:include href="ri-spi.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
- <xi:include href="ri-spi.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
</book>
-
Modified: doc/trunk/reference/en-US/part1.xml
===================================================================
--- doc/trunk/reference/en-US/part1.xml 2009-10-27 18:16:18 UTC (rev 4351)
+++ doc/trunk/reference/en-US/part1.xml 2009-10-27 18:36:17 UTC (rev 4352)
@@ -1,129 +1,176 @@
-<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+ "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+<partintro>
-<partintro>
+ <!-- This part could probably be split into a chapter of it's own, perhaps
"Overview" with subsection for Concepts
+ and History -->
+
+<!-- this specification defines an SPI that allows alternative,
non-platform technologies to integrate
+with the con-
+tainer, for example, alternative web presentation technologies.
+-->
+
+ <!-- NOTE synchronize this intro with the intro on
http://seamframework.org/Weld
-->
+ <para>
+ The <ulink
src="http://jcp.org/en/jsr/detail?id=299">JSR-299</ulink> specification
(CDI) defines a set of services
+ for the Java EE environment that make applications much easier to develop. CDI
layers an enhanced lifecycle and
+ interaction model over existing Java component types, including Managed Beans
(JavaBeans) and Enterprise JavaBeans
+ (EJB session beans). As a complement to the traditional Java EE programming model,
the services provide:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ an improved lifecycle for stateful components, bound to well-defined
<emphasis>contexts</emphasis>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a typesafe approach to <emphasis>dependency
injection</emphasis>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ component interaction via an <emphasis>event notification
facility</emphasis>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a better approach to binding <emphasis>interceptors</emphasis> to
components, along with a new kind of
+ interceptor, called a <emphasis>decorator</emphasis>, that is
more appropriate for use in solving business problems, and
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ an <emphasis>SPI</emphasis> for developing portable extensions
for the Java EE platform.
+ </para>
+ </listitem>
+ </itemizedlist>
- <para>The Web Beans (JSR-299) specification defines a set of services for
- the Java EE environment that makes applications much easier to develop.
- Web Beans layers an enhanced lifecycle and interaction model over existing
- Java component types including JavaBeans and Enterprise Java Beans. As a
- complement to the traditional Java EE programming model, the Web Beans
- services provide:</para>
+ <para>
+ A component that receives CDI services is referred to, generally, as a bean. The
CDI services are a core aspect of
+ the Java EE platform and apply to the following types of components that exist in
the platform:
+ </para>
- <itemizedlist>
- <listitem>
- <para>an improved lifecycle for stateful components, bound to well-defined
- <emphasis>contexts</emphasis>,</para>
- </listitem>
- <listitem>
- <para>a typesafe approach to <emphasis>dependency
injection</emphasis>,</para>
- </listitem>
- <listitem>
- <para>interaction via an <emphasis>event notification</emphasis>
facility,
- and</para>
- </listitem>
- <listitem>
- <para>a better approach to binding
<emphasis>interceptors</emphasis> to
- components, along with a new kind of interceptor, called a
- <emphasis>decorator</emphasis>, that is more appropriate for use in
- solving business problems.</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>all Managed Beans (JavaBeans), including JSF managed
beans,</para>
+ </listitem>
+ <listitem>
+ <para>all Enterprise JavaBeans (EJBs), and</para>
+ </listitem>
+ <listitem>
+ <para>all Servlets.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ CDI is especially useful in the context of web applications, but is applicable to a
wide variety of applications.
+ It may even be used in the Java SE context, in conjunction with an embeddable EJB
Lite container, as defined in
+ the EJB 3.1 specification, or through an extension (see <xref
linkend="weld-se"/>).
+ </para>
- <para>Dependency injection, together with contextual lifecycle management,
- saves the user of an unfamiliar API from having to ask and answer the following
- questions:</para>
+ <para>
+ The concerns handled by CDI save the user who is unfamiliar with an API from having
to answer the following
+ questions:
+ </para>
- <itemizedlist>
- <listitem>
- <para>what is the lifecycle of this object?</para>
- </listitem>
- <listitem>
- <para>how many simultaneous clients can it have?</para>
- </listitem>
- <listitem>
- <para>is it multithreaded?</para>
- </listitem>
- <listitem>
- <para>where can I get one from?</para>
- </listitem>
- <listitem>
- <para>do I need to explicitly destroy it?</para>
- </listitem>
- <listitem>
- <para>where should I keep my reference to it when I'm not
- using it directly?</para>
- </listitem>
- <listitem>
- <para>how can I add an indirection layer, so that the implementation
- of this object can vary at deployment time?</para>
- </listitem>
- <listitem>
- <para>how should I go about sharing this object between other
objects?</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>What is the lifecycle of this object?</para>
+ </listitem>
+ <listitem>
+ <para>How many simultaneous clients can it have?</para>
+ </listitem>
+ <listitem>
+ <para>Is it multithreaded?</para>
+ </listitem>
+ <listitem>
+ <para>How do I retrieve it?</para>
+ </listitem>
+ <listitem>
+ <para>Do I need to explicitly destroy it?</para>
+ </listitem>
+ <listitem>
+ <para>
+ Where should I keep the reference to it when I'm not currently using it?
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ How can I define alternatives, so that the implementation of this object can
vary at deployment time?
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ How should I go about sharing this object between other objects?
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The main theme of CDI, which is instrumental in removing these complexities, is
<emphasis>loose-couping with
+ strong typing</emphasis>. Let's study what that phrase means.
+ </para>
- <para>A Web Bean specifies only the type and semantics of other Web Beans
- it depends upon. It need not be aware of the actual lifecycle, concrete
- implementation, threading model or other clients of any Web Bean it depends
- upon. Even better, the concrete implementation, lifecycle and threading model
- of a Web Bean it depends upon may vary according to the deployment scenario,
- without affecting any client.</para>
+ <para>
+ A bean specifies only the type and semantics of other beans it depends upon. It
need not be aware of the actual
+ lifecycle, concrete implementation, threading model or other clients of any bean it
depends upon. Even better, the
+ concrete implementation, lifecycle and threading model of a bean it depends upon
may vary according to the
+ deployment scenario, without affecting any client. This loose-coupling is what
makes this architecture so simple,
+ yet powerful.
+ </para>
- <para>Events, interceptors and decorators enhance the
<emphasis>loose-coupling</emphasis>
- that is inherent in this model:</para>
+ <para>
+ Events, interceptors and decorators enhance the
<emphasis>loose-coupling</emphasis> inherent in this model:
+ </para>
- <itemizedlist>
- <listitem>
- <para><emphasis>event notifications</emphasis> decouple event
producers
- from event consumers,</para>
- </listitem>
- <listitem>
- <para><emphasis>interceptors</emphasis> decouple technical
concerns from
- business logic, and</para>
- </listitem>
- <listitem>
- <para><emphasis>decorators</emphasis> allow business concerns to
be
- compartmentalized.</para>
- </listitem>
- </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>event notifications</emphasis> decouple event producers
from event consumers,</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>interceptors</emphasis> decouple technical concerns
from business logic, and</para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>decorators</emphasis> allow business concerns to be
compartmentalized.</para>
+ </listitem>
+ </itemizedlist>
- <para>Most importantly, Web Beans provides all these facilities in a
- <emphasis>typesafe</emphasis> way. Web Beans never uses string-based
- identifiers to determine how collaborating objects fit together. And
- XML, though it remains an option, is rarely used. Instead, Web Beans
- uses the typing information that is already available in the Java
- object model, together with a new pattern, called
- <emphasis>binding annotations</emphasis>, to wire together Web Beans,
- their dependencies, their interceptors and decorators and their event
- consumers.</para>
+ <para>
+ What's even more powerful (and comforting) is that CDI provides all these
facilities in a
+ <emphasis>typesafe</emphasis> way. CDI never relies on string-based
identifiers to determine how collaborating
+ objects fit together. (XML is rarely used, reserved only to activate alternatives
and define ordering at
+ deployment time). Instead, CDI uses the typing information that is already
available in the Java object model,
+ then extends it with a new typing pattern, called <emphasis>qualifier
annotations</emphasis>, to wire together
+ beans, their dependencies, their interceptors and decorators and their event
consumers.
+ </para>
- <para>The Web Beans services are general and apply to the following types of
- components that exist in the Java EE environment:</para>
+ <para>
+ CDI even provides the necessary integration points, through a comprehensive SPI, so
that other kinds of components
+ defined by future Java EE specifications or by non-standard frameworks may be
cleanly integrated with CDI, take
+ advantage of the CDI services, and interact with any other kind of platform
component.
+ </para>
- <itemizedlist>
- <listitem>
- <para>all JavaBeans,</para>
- </listitem>
- <listitem>
- <para>all EJBs, and</para>
- </listitem>
- <listitem>
- <para>all Servlets.</para>
- </listitem>
- </itemizedlist>
+ <para>
+ CDI was influenced by a number of existing Java frameworks, including Seam, Guice
and Spring. However, CDI has its
+ own, very distinct, character: more typesafe than Seam, more stateful and less
XML-centric than Spring, more web and
+ enterprise-application capable than Guice. But it couldn't have been any of
these without inspiration from the
+ frameworks mentioned and <emphasis>lots</emphasis> of collaboration and
hard work by the JSR-299 Expert Group
+ (EG).
+ </para>
- <para>Web Beans even provides the necessary integration points so that other
- kinds of components defined by future Java EE specifications or by non-standard
- frameworks may be cleanly integrated with Web Beans, take advantage of the Web
- Beans services, and interact with any other kind of Web Bean.</para>
+ <para>
+ Finally, JSR-299 is a <ulink src="http://jcp.org">Java Community
Process</ulink> (JCP) standard that integrates
+ cleanly with the Java EE platform, and with any Java SE environment where
embeddable EJB Lite is available. In
+ fact, Java EE 6 requires that all compliant application servers provide support for
JSR-299 (even in the web
+ profile).
+ </para>
- <para>Web Beans was influenced by a number of existing Java frameworks,
- including Seam, Guice and Spring. However, Web Beans has its own very distinct
- character: more typesafe than Seam, more stateful and less XML-centric than
- Spring, more web and enterprise-application capable than Guice.</para>
-
- <para>Most importantly, Web Beans is a JCP standard that integrates
- cleanly with Java EE, and with any Java SE environment where embeddable
- EJB Lite is available.</para>
-
-</partintro>
\ No newline at end of file
+<!--
+vim:et:ts=3:sw=3:tw=120
+-->
+</partintro>