[webbeans-commits] Webbeans SVN: r2518 - doc/trunk/reference/en-US.
by webbeans-commits@lists.jboss.org
Author: cpopetz
Date: 2009-04-19 16:34:17 -0400 (Sun, 19 Apr 2009)
New Revision: 2518
Modified:
doc/trunk/reference/en-US/gettingstarted.xml
Log:
add -Pjetty docs
Modified: doc/trunk/reference/en-US/gettingstarted.xml
===================================================================
--- doc/trunk/reference/en-US/gettingstarted.xml 2009-04-19 20:30:54 UTC (rev 2517)
+++ doc/trunk/reference/en-US/gettingstarted.xml 2009-04-19 20:34:17 UTC (rev 2518)
@@ -715,13 +715,14 @@
</para>
<programlisting><![CDATA[cd examples/wicket/numberguess
-mvn eclipse:eclipse]]></programlisting>
+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. This will create a project in your workspace called
- <literal>webbeans-wicket-numberguess</literal>
+ 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>
</para>
<mediaobject>
@@ -1522,4 +1523,4 @@
examples and translating this reference guide.
</para>
-</chapter>
\ No newline at end of file
+</chapter>
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2517 - in examples/trunk/wicket: conversations/src/main/java/org/jboss/webbeans/examples/conversations and 5 other directories.
by webbeans-commits@lists.jboss.org
Author: cpopetz
Date: 2009-04-19 16:30:54 -0400 (Sun, 19 Apr 2009)
New Revision: 2517
Added:
examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/jetty-additions-to-web.xml
examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/jetty-additions-to-web.xml
Modified:
examples/trunk/wicket/conversations/pom.xml
examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.html
examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.java
examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/web.xml
examples/trunk/wicket/conversations/src/test/java/org/jboss/webbeans/examples/wicket/Start.java
examples/trunk/wicket/numberguess/pom.xml
examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/web.xml
examples/trunk/wicket/numberguess/src/test/java/org/jboss/webbeans/examples/wicket/Start.java
Log:
Fix examples for jboss5.
Modified: examples/trunk/wicket/conversations/pom.xml
===================================================================
--- examples/trunk/wicket/conversations/pom.xml 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/conversations/pom.xml 2009-04-19 20:30:54 UTC (rev 2517)
@@ -34,8 +34,9 @@
</dependency>
<dependency>
- <groupId>org.jboss.webbeans.servlet</groupId>
- <artifactId>webbeans-servlet</artifactId>
+ <groupId>org.jboss.webbeans</groupId>
+ <artifactId>webbeans-api</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
@@ -137,4 +138,18 @@
<jetty.version>6.1.16</jetty.version>
</properties>
+ <profiles>
+ <profile>
+ <id>jetty</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.webbeans.servlet</groupId>
+ <artifactId>webbeans-servlet</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
+
</project>
Modified: examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.html
===================================================================
--- examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.html 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.html 2009-04-19 20:30:54 UTC (rev 2517)
@@ -18,7 +18,7 @@
<input type="submit" wicket:id="noop" value="noop"/><p/>
<input type="submit" wicket:id="end" value="end"/><p/>
<input type="submit" wicket:id="longop" value="longop"/><p/>
- <a href="/">Abandon</a><p/>
+ <a wicket:id="abandon" href="/">Abandon</a><p/>
</form>
<p/>
<span wicket:id="feedback"/>
Modified: examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.java
===================================================================
--- examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.java 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/conversations/src/main/java/org/jboss/webbeans/examples/conversations/HomePage.java 2009-04-19 20:30:54 UTC (rev 2517)
@@ -12,6 +12,7 @@
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.link.ExternalLink;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
@@ -136,6 +137,11 @@
}
}
});
+
+ //Fake out conversation propagation by constructing a string url to ourselves, which
+ //won't have the propagated cid
+ form.add(new ExternalLink("abandon",
+ urlFor(HomePage.class,new PageParameters()).toString()));
}
}
Added: examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/jetty-additions-to-web.xml
===================================================================
--- examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/jetty-additions-to-web.xml (rev 0)
+++ examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/jetty-additions-to-web.xml 2009-04-19 20:30:54 UTC (rev 2517)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+<!-- Jboss AS has a deployer that bootstraps webbeans, but in jetty we need this listener -->
+ <listener>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+ </listener>
+
+</web-app>
Property changes on: examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/jetty-additions-to-web.xml
___________________________________________________________________
Name: svn:executable
+ *
Modified: examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/web.xml
===================================================================
--- examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/web.xml 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/conversations/src/main/webapp/WEB-INF/web.xml 2009-04-19 20:30:54 UTC (rev 2517)
@@ -20,9 +20,4 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
- <listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
- </listener>
-
-
</web-app>
Modified: examples/trunk/wicket/conversations/src/test/java/org/jboss/webbeans/examples/wicket/Start.java
===================================================================
--- examples/trunk/wicket/conversations/src/test/java/org/jboss/webbeans/examples/wicket/Start.java 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/conversations/src/test/java/org/jboss/webbeans/examples/wicket/Start.java 2009-04-19 20:30:54 UTC (rev 2517)
@@ -17,6 +17,8 @@
bb.setServer(server);
bb.setContextPath("/");
bb.setWar("src/main/webapp");
+ bb.setOverrideDescriptor("src/main/webapp/WEB-INF/jetty-additions-to-web.xml");
+
server.addHandler(bb);
try {
Modified: examples/trunk/wicket/numberguess/pom.xml
===================================================================
--- examples/trunk/wicket/numberguess/pom.xml 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/numberguess/pom.xml 2009-04-19 20:30:54 UTC (rev 2517)
@@ -33,12 +33,6 @@
<scope>provided</scope>
</dependency>
- <dependency>
- <groupId>org.jboss.webbeans.servlet</groupId>
- <artifactId>webbeans-servlet</artifactId>
- <scope>runtime</scope>
- </dependency>
-
<dependency>
<groupId>org.jboss.webbeans</groupId>
<artifactId>webbeans-wicket</artifactId>
@@ -138,4 +132,18 @@
<jetty.version>6.1.16</jetty.version>
</properties>
+ <profiles>
+ <profile>
+ <id>jetty</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.webbeans.servlet</groupId>
+ <artifactId>webbeans-servlet</artifactId>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
+
</project>
Added: examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/jetty-additions-to-web.xml
===================================================================
--- examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/jetty-additions-to-web.xml (rev 0)
+++ examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/jetty-additions-to-web.xml 2009-04-19 20:30:54 UTC (rev 2517)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
+ version="2.4">
+
+<!-- Jboss AS has a deployer that bootstraps webbeans, but in jetty we need this listener -->
+ <listener>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+ </listener>
+
+</web-app>
Property changes on: examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/jetty-additions-to-web.xml
___________________________________________________________________
Name: svn:executable
+ *
Modified: examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/web.xml
===================================================================
--- examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/web.xml 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/numberguess/src/main/webapp/WEB-INF/web.xml 2009-04-19 20:30:54 UTC (rev 2517)
@@ -20,9 +20,4 @@
<url-pattern>/*</url-pattern>
</filter-mapping>
- <listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
- </listener>
-
-
</web-app>
Modified: examples/trunk/wicket/numberguess/src/test/java/org/jboss/webbeans/examples/wicket/Start.java
===================================================================
--- examples/trunk/wicket/numberguess/src/test/java/org/jboss/webbeans/examples/wicket/Start.java 2009-04-19 20:24:44 UTC (rev 2516)
+++ examples/trunk/wicket/numberguess/src/test/java/org/jboss/webbeans/examples/wicket/Start.java 2009-04-19 20:30:54 UTC (rev 2517)
@@ -17,6 +17,7 @@
bb.setServer(server);
bb.setContextPath("/");
bb.setWar("src/main/webapp");
+ bb.setOverrideDescriptor("src/main/webapp/WEB-INF/jetty-additions-to-web.xml");
server.addHandler(bb);
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2516 - doc/trunk/reference/en-US.
by webbeans-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2009-04-19 16:24:44 -0400 (Sun, 19 Apr 2009)
New Revision: 2516
Added:
doc/trunk/reference/en-US/gettingstarted.xml
Removed:
doc/trunk/reference/en-US/ri.xml
Modified:
doc/trunk/reference/en-US/environments.xml
doc/trunk/reference/en-US/master.xml
Log:
Move getting started withJava SE
Modified: doc/trunk/reference/en-US/environments.xml
===================================================================
--- doc/trunk/reference/en-US/environments.xml 2009-04-19 19:57:30 UTC (rev 2515)
+++ doc/trunk/reference/en-US/environments.xml 2009-04-19 20:24:44 UTC (rev 2516)
@@ -279,396 +279,6 @@
</section>
- <section>
- <title>Swing Example: Number Guess</title>
-
- <para>Here's an example of a Swing application, Number Guess, similar to the example in
- chapter 3.4. In the Number Guess 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. This example can be found in the
- <literal>examples/se/numberguess</literal> folder of the Web Beans distribution.
- </para>
-
- <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.
- </para>
-
- <para>The game's main logic is located in <literal>Game.java</literal>. Here is the code for
- that class, excluding that which is identical to the JSF version: </para>
-
- <programlistingco>
- <areaspec>
- <area id="scope" coords="1" />
- <area id="name" coords="1" />
- <area id="messages" coords="26" />
- <area id="validation" coords="39" />
- <area id="reset" coords="68" />
- </areaspec>
- <programlisting role="JAVA"><![CDATA[@ApplicationScoped
-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;
-
- ...
-
- public boolean isValidNumberRange()
- {
- return validNumberRange;
- }
-
- public boolean isGameWon()
- {
- return guess == number;
- }
-
- public boolean isGameLost()
- {
- return guess != number && remainingGuesses <= 0;
- }
-
- public boolean check()
- {
- boolean result = false;
-
- if ( checkNewNumberRangeIsValid() )
- {
- if ( guess > number )
- {
- biggest = guess - 1;
- }
-
- if ( guess < number )
- {
- smallest = guess + 1;
- }
-
- if ( guess == number )
- {
- result = true;
- }
-
- remainingGuesses--;
- }
-
- return result;
- }
-
- private boolean checkNewNumberRangeIsValid()
- {
- return validNumberRange = ( ( guess >= smallest ) && ( guess <= biggest ) );
- }
-
- @PostConstruct
- public void reset()
- {
- this.smallest = 0;
- ...
- this.number = rndGenerator.next();
- }
-}]]></programlisting>
- <calloutlist>
- <callout arearefs="scope">
- <para>
- The bean is application scoped instead of session scoped, since an instance of the
- application represents a single 'session'.
- </para>
- </callout>
- <callout arearefs="name">
- <para>
- The bean is not named, since it doesn't need to be accessed via EL
- </para>
- </callout>
- <callout arearefs="messages">
- <para>There is no JSF <literal>FacesContext</literal> to add messages to. Instead the <literal>Game</literal> class provides
- additional information about the state of the current game including:
- </para>
-
-
- <itemizedlist>
- <listitem>
- <para>If the game has been won or lost</para>
- </listitem>
- <listitem>
- <para>If the most recent guess was invalid</para>
- </listitem>
- </itemizedlist>
-
- <para>This allows the Swing UI to query the state of the game, which it does
- indirectly via a class called <literal>MessageGenerator,</literal> in order to determine the appropriate
- messages to display to the user during the game.
- </para>
- </callout>
- <callout arearefs="validation">
- <para>
- Validation of user input is performed during the <literal>check()</literal> method, since there is
- no dedicated validation phase
- </para>
- </callout>
- <callout arearefs="reset">
- <para>
- The <literal>reset()</literal> method makes a call to the injected <literal>rndGenerator</literal> in order to get the
- random number at the start of each game. It cannot use
- <literal>manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){})</literal>
- as the JSF example does because there will not be any active contexts like
- there is during a JSF request.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>The <literal>MessageGenerator</literal> class depends on the current instance of <literal>Game</literal>, and queries
- its state in order to determine the appropriate messages to provide as the
- prompt for the user's next guess and the response to the previous guess.
- The code for <literal>MessageGenerator</literal> is as follows:
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="game" coords="3" />
- <area id="challenge" coords="5" />
- <area id="result" coords="16" />
- </areaspec>
- <programlisting role="JAVA"><![CDATA[public class MessageGenerator
-{
- @Current Game game;
-
- public String getChallengeMessage()
- {
- StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a number between " );
- challengeMsg.append( game.getSmallest() );
- challengeMsg.append( " and " );
- challengeMsg.append( game.getBiggest() );
- challengeMsg.append( ". Can you guess what it is?" );
-
- return challengeMsg.toString();
- }
-
- public String getResultMessage()
- {
- if ( game.isGameWon() )
- {
- return "You guess it! The number was " + game.getNumber();
- } else if ( game.isGameLost() )
- {
- return "You are fail! The number was " + game.getNumber();
- } else if ( ! game.isValidNumberRange() )
- {
- return "Invalid number range!";
- } else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
- {
- return "What is your first guess?";
- } else
- {
- String direction = null;
-
- if ( game.getGuess() < game.getNumber() )
- {
- direction = "Higher";
- } else
- {
- direction = "Lower";
- }
-
- return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
- }
- }
-}]]></programlisting>
- <calloutlist>
- <callout arearefs="game">
- <para>
- The instance of <literal>Game</literal> for the application is injected here.
- </para>
- </callout>
- <callout arearefs="challenge">
- <para>
- The <literal>Game</literal>'s state is interrogated to determine the appropriate
- challenge message.
- </para>
- </callout>
- <callout arearefs="result">
- <para>
- And again to determine whether to congratulate, console or
- encourage the user to continue.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>Finally we come to the <literal>NumberGuessFrame</literal> class which provides the Swing
- front end to our guessing game. </para>
-
- <programlistingco>
- <areaspec>
- <area id="gameIn" coords="3" />
- <area id="messagesIn" coords="4" />
- <area id="start" coords="6" />
- <area id="init" coords="18" />
- <area id="guess" coords="34" />
- <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;
-
- public void start( @Observes @Deployed Manager manager )
- {
- java.awt.EventQueue.invokeLater( new Runnable()
- {
- public void run()
- {
- initComponents();
- setVisible( true );
- }
- } );
- }
-
- private void initComponents() {
-
- buttonPanel = new javax.swing.JPanel();
- mainMsgPanel = new javax.swing.JPanel();
- mainLabel = new javax.swing.JLabel();
- messageLabel = new javax.swing.JLabel();
- guessText = new javax.swing.JTextField();
- ...
- mainLabel.setText(msgGenerator.getChallengeMessage());
- mainMsgPanel.add(mainLabel);
-
- messageLabel.setText(msgGenerator.getResultMessage());
- mainMsgPanel.add(messageLabel);
- ...
- }
-
- private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
- {
- int guess = Integer.parseInt(guessText.getText());
-
- game.setGuess( guess );
- game.check();
- refreshUI();
-
- }
-
- private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
- {
- game.reset();
- refreshUI();
- }
-
- private void refreshUI()
- {
- mainLabel.setText( msgGenerator.getChallengeMessage() );
- messageLabel.setText( msgGenerator.getResultMessage() );
- guessText.setText( "" );
- guessesLeftBar.setValue( game.getRemainingGuesses() );
- guessText.requestFocus();
- }
-
- // swing components
- private javax.swing.JPanel borderPanel;
- ...
- private javax.swing.JButton replayBtn;
-
-}]]></programlisting>
- <calloutlist>
- <callout arearefs="gameIn">
- <para>
- The injected instance of the game (logic and state).
- </para>
- </callout>
- <callout arearefs="messagesIn">
- <para>
- The injected message generator for UI messages.
- </para>
- </callout>
- <callout arearefs="start">
- <para>
- This application is started in the usual Web Beans SE way, by observing the
- <literal>@Deployed Manager</literal> event.
- </para>
- </callout>
- <callout arearefs="init">
- <para>
- This method initialises all of the Swing components. Note the use
- of the <literal>msgGenerator</literal>.
- </para>
- </callout>
- <callout arearefs="guess">
- <para>
- <literal>guessButtonActionPerformed</literal> is called when the 'Guess' button is clicked, and
- it does the following:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>Gets the guess entered by the user and sets it as the current guess in the <literal>Game</literal></para>
- </listitem>
- <listitem>
- <para>Calls <literal>game.check()</literal> to validate and perform one 'turn' of the game</para>
- </listitem>
- <listitem>
- <para> Calls <literal>refreshUI</literal>. If there were validation errors with the input, this
- will have been captured during <literal>game.check()</literal> and as such will be reflected
- in the messeges returned by <literal>MessageGenerator</literal> and subsequently presented
- to the user. If there are no validation errors then the user will be told
- to guess again (higher or lower) or that the game has ended either in a
- win (correct guess) or a loss (ran out of guesses).
- </para>
- </listitem>
- </itemizedlist>
- </callout>
- <callout arearefs="replay">
- <para>
- <literal>replayBtnActionPerformed</literal> simply calls <literal>game.reset()</literal> to start a new game
- and refreshes the messages in the UI.
- </para>
- </callout>
- <callout arearefs="refresh">
- <para>
- <literal>refreshUI</literal> uses the <literal>MessageGenerator</literal> to update the messages to the user based
- on the current state of the Game.
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <para>
- To run this example simply
- <itemizedlist>
- <listitem>
- <para>Open a command line/terminal window in the
- <literal>examples/se/numberguess</literal> directory</para>
- </listitem>
- <listitem>
- <para>Ensure that Maven 2 is installed and in your PATH</para>
- </listitem>
- <listitem>
- <para>Ensure that the <literal>JAVA_HOME</literal> environment variable is pointing to your JDK installation</para>
- </listitem>
- <listitem>
- <para>execute the following command</para>
- </listitem>
- </itemizedlist>
- </para>
-
- <programlisting>mvn -Drun</programlisting>
-
- </section>
-
</section>
</chapter>
\ No newline at end of file
Copied: doc/trunk/reference/en-US/gettingstarted.xml (from rev 2515, doc/trunk/reference/en-US/ri.xml)
===================================================================
--- doc/trunk/reference/en-US/gettingstarted.xml (rev 0)
+++ doc/trunk/reference/en-US/gettingstarted.xml 2009-04-19 20:24:44 UTC (rev 2516)
@@ -0,0 +1,1525 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+
+<chapter id="ri">
+ <title>Getting started with Web Beans, the Reference Implementation of JSR-299</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>
+
+ <para>
+ Web Beans comes with a two deployable example applications:
+ <literal>webbeans-numberguess</literal>, a war example, containing only
+ simple beans, and <literal>webbeans-translator</literal> an ear example,
+ containing enterprise beans. There are also two variations on the
+ numberguess example, the tomcat example (suitable for deployment to
+ Tomcat) and the jsf2 example, which you can use if you are running JSF2.
+ To run the examples you'll need the following:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the latest release of Web Beans,</para>
+ </listitem>
+ <listitem>
+ <para>JBoss AS 5.0.1.GA, or</para>
+ </listitem>
+ <listitem>
+ <para>Apache Tomcat 6.0.x, and</para>
+ </listitem>
+ <listitem>
+ <para>Ant 1.7.0.</para>
+ </listitem>
+ </itemizedlist>
+
+ <section>
+ <title>Using JBoss AS 5</title>
+
+ <para>
+ You'll need to download JBoss AS 5.0.1.GA from
+ <ulink url="http://www.jboss.org/jbossas/downloads/">jboss.org</ulink>,
+ and unzip it. For example:
+ </para>
+
+ <programlisting><![CDATA[$ cd /Applications
+$ unzip ~/jboss-5.0.1.GA.zip]]></programlisting>
+
+ <para>
+ Next, download Web Beans from
+ <ulink url="http://seamframework.org/Download">seamframework.org</ulink>,
+ and unzip it. For example
+ </para>
+
+ <programlisting><![CDATA[$ cd ~/
+$ unzip ~/webbeans-$VERSION.zip]]></programlisting>
+
+
+ <para>
+ Next, we need to tell Web Beans where JBoss is located. Edit
+ <literal>jboss-as/build.properties</literal> and set the
+ <literal>jboss.home</literal> property. For example:
+ </para>
+
+ <programlisting>jboss.home=/Applications/jboss-5.0.1.GA</programlisting>
+
+ <para>
+ To install Web Beans, you'll need Ant 1.7.0 installed, and the
+ <literal>ANT_HOME</literal> environment variable set. For example:
+ </para>
+
+ <programlisting>$ unzip apache-ant-1.7.0.zip
+$ export ANT_HOME=~/apache-ant-1.7.0</programlisting>
+
+ <para>
+ Then, you can install the update. The update script will use Maven to
+ download Web Beans automatically.
+ </para>
+
+ <programlisting>$ cd webbeans-$VERSION/jboss-as
+$ ant update</programlisting>
+
+ <para>
+ Now, you're ready to deploy your first example!
+ </para>
+
+ <tip>
+ <para>
+ The build scripts for the examples offer a number of targets for
+ JBoss AS, these are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>ant restart</literal> - deploy the example in exploded
+ format
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <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
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant undeploy</literal> - remove the example from the server
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant clean</literal> - clean the example
+ </para>
+ </listitem>
+ </itemizedlist>
+ </tip>
+
+ <para>
+ To deploy the numberguess example:
+ </para>
+
+ <programlisting>$ cd examples/numberguess
+ant deploy</programlisting>
+
+ <para>
+ Start JBoss AS:
+ </para>
+
+ <programlisting>$ /Application/jboss-5.0.0.GA/bin/run.sh</programlisting>
+
+ <tip>
+ <para>
+ If you use Windows, use the <literal>run.bat</literal>script.
+ </para>
+ </tip>
+
+ <para>
+ Wait for the application to deploy, and enjoy hours of fun at
+ <ulink url="http://localhost:8080/webbeans-numberguess" />!
+ </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:
+ </para>
+
+ <programlisting>$ cd examples/translator
+ant deploy</programlisting>
+
+ <para>
+ Wait for the application to deploy, and visit
+ <ulink url="http://localhost:8080/webbeans-translator" />!
+ </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.org</ulink>,
+ and unzip it. For example:
+ </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</ulink>,
+ and unzip it. For example
+ </para>
+
+ <programlisting><![CDATA[$ cd ~/
+$ unzip ~/webbeans-$VERSION.zip]]></programlisting>
+
+ <para>
+ Next, we need to tell Web Beans where Tomcat is located. Edit
+ <literal>jboss-as/build.properties</literal> and set the
+ <literal>tomcat.home</literal> property. For example:
+ </para>
+
+ <programlisting>tomcat.home=/Applications/apache-tomcat-6.0.18</programlisting>
+
+ <tip>
+ <para>
+ The build scripts for the examples offer a number of targets for
+ Tomcat, these are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>ant tomcat.restart</literal> - deploy the example in exploded
+ format
+ </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
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.undeploy</literal> - remove the example from the server
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ant tomcat.clean</literal> - clean the example
+ </para>
+ </listitem>
+ </itemizedlist>
+ </tip>
+
+ <para>
+ To deploy the numberguess example for tomcat:
+ </para>
+
+ <programlisting>$ cd examples/tomcat
+ant tomcat.deploy</programlisting>
+
+ <para>
+ Start Tomcat:
+ </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>
+ Wait for the application to deploy, and enjoy hours of fun at
+ <ulink url="http://localhost:8080/webbeans-numberguess" />!
+ </para>
+
+ </section>
+
+ <section>
+ <title>Using GlassFish</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.
+ </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.
+ </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:
+ </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>
+
+</faces-config>]]></programlisting>
+
+ <para>
+ There is an empty <literal>web-beans.xml</literal> file, which marks
+ this application as a Web Beans application.
+ </para>
+
+ <para>
+ Finally there is <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" />
+ </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">
+
+ <display-name>Web Beans Numbergues example</display-name>
+
+ <!-- JSF -->
+
+ <servlet>
+ <servlet-name>Faces Servlet</servlet-name>
+ <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Faces Servlet</servlet-name>
+ <url-pattern>*.jsf</url-pattern>
+ </servlet-mapping>
+
+ <context-param>
+ <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
+ <param-value>.xhtml</param-value>
+ </context-param>
+
+ <session-config>
+ <session-timeout>10</session-timeout>
+ </session-config>
+
+</web-app>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="faces.servlet">
+ <para>
+ Enable and load the JSF servlet
+ </para>
+ </callout>
+ <callout arearefs="faces.servlet.mapping">
+ <para>
+ Configure requests to <literal>.jsf</literal> pages 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
+ extension of <literal>.xhtml</literal>
+ </para>
+ </callout>
+ <callout arearefs="session.timeout">
+ <para>
+ Configure a session timeout of 10 minutes
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <note>
+ <para>
+ Whilst this demo is a JSF demo, you can use Web Beans with any
+ Servlet based web framework.
+ </para>
+ </note>
+
+ <para>
+ Let's take a look at the Facelet view:
+ </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" />
+ </areaspec>
+ <programlisting><![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">
+
+ <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>
+</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.
+ </para>
+ </callout>
+ <callout arearefs="messages2">
+ <para>
+ There are a number of messages which can be sent to the user,
+ "Higher!", "Lower!" and "Correct!"
+ </para>
+ </callout>
+ <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.
+ </para>
+ </callout>
+ <callout arearefs="guess">
+ <para>
+ This input field is bound to a Web Bean, using the value
+ expression.
+ </para>
+ </callout>
+ <callout arearefs="validator">
+ <para>
+ A range validator 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.
+ </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.
+ </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:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+@BindingType
+public @interface Random {}]]></programlisting>
+
+ <para>
+ There is also the <literal>@MaxNumber</literal> binding type, used for
+ injecting the maximum number that can be injected:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
+@Retention(RUNTIME)
+@Documented
+@BindingType
+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:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+public class Generator {
+
+ private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
+
+ private int maxNumber = 100;
+
+ java.util.Random getRandom()
+ {
+ return random;
+ }
+
+ @Produces @Random int next() {
+ return getRandom().nextInt(maxNumber);
+ }
+
+ @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.
+ </para>
+
+ <para>
+ The final Web Bean in the application is the session scoped
+ <literal>Game</literal>.
+ </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>.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[package org.jboss.webbeans.examples.numberguess;
+
+
+import javax.annotation.PostConstruct;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.webbeans.AnnotationLiteral;
+import javax.webbeans.Current;
+import javax.webbeans.Initializer;
+import javax.webbeans.Named;
+import javax.webbeans.SessionScoped;
+import javax.webbeans.manager.Manager;
+
+@Named
+@SessionScoped
+public class Game
+{
+ private int number;
+
+ private int guess;
+ private int smallest;
+ private int biggest;
+ private int remainingGuesses;
+
+ @Current Manager manager;
+
+ public Game()
+ {
+ }
+
+ @Initializer
+ Game(@MaxNumber int maxNumber)
+ {
+ this.biggest = maxNumber;
+ }
+
+ 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;
+ }
+
+ public String check()
+ {
+ if (guess>number)
+ {
+ biggest = guess - 1;
+ }
+ if (guess<number)
+ {
+ smallest = guess + 1;
+ }
+ if (guess == number)
+ {
+ FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
+ }
+ remainingGuesses--;
+ return null;
+ }
+
+ @PostConstruct
+ public void reset()
+ {
+ this.smallest = 0;
+ this.guess = 0;
+ this.remainingGuesses = 10;
+ this.number = manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){});
+ }
+
+}]]></programlisting>
+
+ <section>
+ <title>The numberguess example in Tomcat</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>.
+ </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.
+ </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>:
+ </para>
+
+ <programlisting><![CDATA[<listener>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+</listener>]]></programlisting>
+
+ </section>
+
+ <section id="numberguessWicket">
+ <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.
+ </para>
+
+ <note>
+ <para>
+ You may want to review the Wicket documentation at
+ <ulink url="http://wicket.apache.org/">http://wicket.apache.org/</ulink>.
+ </para>
+ </note>
+
+ <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.
+ </para>
+
+ <para>
+ These examples make use of the Eclipse IDE; instructions are also
+ given to deploy the application from the command line.
+ </para>
+
+ <section>
+ <title>Creating the Eclipse project</title>
+
+ <para>
+ To generate an Eclipse project from the example:
+ </para>
+
+ <programlisting><![CDATA[cd examples/wicket/numberguess
+mvn 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. This will create a project in your workspace called
+ <literal>webbeans-wicket-numberguess</literal>
+ </para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/wicket-numberguess-project.png" format="PNG"/>
+ </imageobject>
+ </mediaobject>
+ </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>.
+ </para>
+ </section>
+
+ <section>
+ <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>.
+ </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).
+ </para>
+
+ <para>
+ The code in the wicket numberguess example is very similar to the
+ JSF-based numberguess example. The business layer is identical!
+ </para>
+
+ <para>
+ Differences are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Each wicket application must have a
+ <literal>WebApplication</literal> subclass, In our case,
+ our application class is
+ <literal>SampleApplication</literal>:
+ </para>
+ <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication {
+ @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>
+ </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:
+ </para>
+
+ <programlisting><![CDATA[ @Current Game game;]]></programlisting>
+
+ <para>
+ 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") {
+ protected void onSubmit(AjaxRequestTarget target, Form form) {
+ if (game.check()) {]]></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
+ <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.
+ </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.
+ </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:
+ </para>
+ <programlisting><![CDATA[<filter>
+ <filter-name>wicket.numberguess-example</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>
+ </init-param>
+</filter>
+
+<filter-mapping>
+ <filter-name>wicket.numberguess-example</filter-name>
+ <url-pattern>/*</url-pattern>
+</filter-mapping>
+
+<listener>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+</listener>]]></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.
+ </para>
+ </listitem>
+
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section>
+ <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.
+ </para>
+
+
+ <para>
+ To run this example:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Open a command line/terminal window in the
+ <literal>examples/se/numberguess</literal> directory
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Ensure that Maven 2 is installed and in your PATH
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Ensure that the <literal>JAVA_HOME</literal> environment
+ variable is pointing to your JDK installation
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ execute the following command
+ </para>
+ <programlisting>mvn -Drun</programlisting>
+ </listitem>
+ </itemizedlist>
+
+
+
+ <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.
+ </para>
+
+ <para>
+ The game's main logic is located in <literal>Game.java</literal>.
+ Here is the code for that class, highlighting the changes made
+ from the web application version:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="scope" coords="1" />
+ <area id="name" coords="1" />
+ <area id="messages1" coords="26" />
+ <area id="validation" coords="39" />
+ <area id="reset" coords="68" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+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;
+
+ ...
+
+ public boolean isValidNumberRange()
+ {
+ return validNumberRange;
+ }
+
+ public boolean isGameWon()
+ {
+ return guess == number;
+ }
+
+ public boolean isGameLost()
+ {
+ return guess != number && remainingGuesses <= 0;
+ }
+
+ public boolean check()
+ {
+ boolean result = false;
+
+ if ( checkNewNumberRangeIsValid() )
+ {
+ if ( guess > number )
+ {
+ biggest = guess - 1;
+ }
+
+ if ( guess < number )
+ {
+ smallest = guess + 1;
+ }
+
+ if ( guess == number )
+ {
+ result = true;
+ }
+
+ remainingGuesses--;
+ }
+
+ return result;
+ }
+
+ private boolean checkNewNumberRangeIsValid()
+ {
+ return validNumberRange = ( ( guess >= smallest ) && ( guess <= biggest ) );
+ }
+
+ @PostConstruct
+ public void reset()
+ {
+ this.smallest = 0;
+ ...
+ this.number = rndGenerator.next();
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="scope">
+ <para>
+ The bean is application scoped instead of session scoped,
+ since an instance of the application represents a single 'session'.
+ </para>
+ </callout>
+ <callout arearefs="name">
+ <para>
+ The bean is not named, since it doesn't need to be accessed
+ via EL
+ </para>
+ </callout>
+ <callout arearefs="messages1">
+ <para>
+ There is no JSF <literal>FacesContext</literal> to add
+ messages to. Instead the <literal>Game</literal> class
+ provides additional information about the state of the
+ current game including:
+ </para>
+
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ If the game has been won or lost
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the most recent guess was invalid
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ This allows the Swing UI to query the state of the game,
+ which it does indirectly via a class called
+ <literal>MessageGenerator,</literal> in order to determine
+ the appropriate messages to display to the user during the
+ game.
+ </para>
+ </callout>
+ <callout arearefs="validation">
+ <para>
+ Validation of user input is performed during the
+ <literal>check()</literal> method, since there is no
+ dedicated validation phase
+ </para>
+ </callout>
+ <callout arearefs="reset">
+ <para>
+ The <literal>reset()</literal> method makes a call to the
+ injected <literal>rndGenerator</literal> in order to get
+ the random number at the start of each game. It cannot use
+ <literal>manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){})</literal>
+ as the JSF example does because there will not be any active contexts like
+ there is during a JSF request.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ The <literal>MessageGenerator</literal> class depends on the
+ current instance of <literal>Game</literal>, and queries its
+ state in order to determine the appropriate messages to provide
+ as the prompt for the user's next guess and the response to the
+ previous guess. The code for <literal>MessageGenerator</literal>
+ is as follows:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="game" coords="3" />
+ <area id="challenge" coords="5" />
+ <area id="result" coords="16" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[public class MessageGenerator
+{
+ @Current Game game;
+
+ public String getChallengeMessage()
+ {
+ StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a number between " );
+ challengeMsg.append( game.getSmallest() );
+ challengeMsg.append( " and " );
+ challengeMsg.append( game.getBiggest() );
+ challengeMsg.append( ". Can you guess what it is?" );
+
+ return challengeMsg.toString();
+ }
+
+ public String getResultMessage()
+ {
+ if ( game.isGameWon() )
+ {
+ return "You guess it! The number was " + game.getNumber();
+ } else if ( game.isGameLost() )
+ {
+ return "You are fail! The number was " + game.getNumber();
+ } else if ( ! game.isValidNumberRange() )
+ {
+ return "Invalid number range!";
+ } else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
+ {
+ return "What is your first guess?";
+ } else
+ {
+ String direction = null;
+
+ if ( game.getGuess() < game.getNumber() )
+ {
+ direction = "Higher";
+ } else
+ {
+ direction = "Lower";
+ }
+
+ return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
+ }
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="game">
+ <para>
+ The instance of <literal>Game</literal> for the application
+ is injected here.
+ </para>
+ </callout>
+ <callout arearefs="challenge">
+ <para>
+ The <literal>Game</literal>'s state is interrogated to
+ determine the appropriate challenge message.
+ </para>
+ </callout>
+ <callout arearefs="result">
+ <para>
+ And again to determine whether to congratulate, console or
+ encourage the user to continue.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Finally we come to the <literal>NumberGuessFrame</literal> class
+ which provides the Swing front end to our guessing game.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="gameIn" coords="3" />
+ <area id="messagesIn" coords="4" />
+ <area id="start" coords="6" />
+ <area id="init" coords="18" />
+ <area id="guess1" coords="34" />
+ <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;
+
+ public void start( @Observes @Deployed Manager manager )
+ {
+ java.awt.EventQueue.invokeLater( new Runnable()
+ {
+ public void run()
+ {
+ initComponents();
+ setVisible( true );
+ }
+ } );
+ }
+
+ private void initComponents() {
+
+ buttonPanel = new javax.swing.JPanel();
+ mainMsgPanel = new javax.swing.JPanel();
+ mainLabel = new javax.swing.JLabel();
+ messageLabel = new javax.swing.JLabel();
+ guessText = new javax.swing.JTextField();
+ ...
+ mainLabel.setText(msgGenerator.getChallengeMessage());
+ mainMsgPanel.add(mainLabel);
+
+ messageLabel.setText(msgGenerator.getResultMessage());
+ mainMsgPanel.add(messageLabel);
+ ...
+ }
+
+ private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ int guess = Integer.parseInt(guessText.getText());
+
+ game.setGuess( guess );
+ game.check();
+ refreshUI();
+
+ }
+
+ private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ game.reset();
+ refreshUI();
+ }
+
+ private void refreshUI()
+ {
+ mainLabel.setText( msgGenerator.getChallengeMessage() );
+ messageLabel.setText( msgGenerator.getResultMessage() );
+ guessText.setText( "" );
+ guessesLeftBar.setValue( game.getRemainingGuesses() );
+ guessText.requestFocus();
+ }
+
+ // swing components
+ private javax.swing.JPanel borderPanel;
+ ...
+ private javax.swing.JButton replayBtn;
+
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="gameIn">
+ <para>
+ The injected instance of the game (logic and state).
+ </para>
+ </callout>
+ <callout arearefs="messagesIn">
+ <para>
+ The injected message generator for UI messages.
+ </para>
+ </callout>
+ <callout arearefs="start">
+ <para>
+ This application is started in the usual Web Beans SE way,
+ by observing the <literal>@Deployed Manager</literal> event.
+ </para>
+ </callout>
+ <callout arearefs="init">
+ <para>
+ This method initialises all of the Swing components. Note
+ the use of the <literal>msgGenerator</literal>.
+ </para>
+ </callout>
+ <callout arearefs="guess1">
+ <para>
+ <literal>guessButtonActionPerformed</literal> is called
+ when the 'Guess' button is clicked, and it does the
+ following:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Gets the guess entered by the user and sets it as the
+ current guess in the <literal>Game</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Calls <literal>game.check()</literal> to validate and
+ perform one 'turn' of the game
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Calls <literal>refreshUI</literal>. If there were
+ validation errors with the input, this will have been
+ captured during <literal>game.check()</literal> and
+ as such will be reflected in the messeges returned by
+ <literal>MessageGenerator</literal> and subsequently
+ presented to the user. If there are no validation
+ errors then the user will be told to guess again
+ (higher or lower) or that the game has ended either
+ in a win (correct guess) or a loss (ran out of
+ guesses).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </callout>
+ <callout arearefs="replay">
+ <para>
+ <literal>replayBtnActionPerformed</literal> simply calls
+ <literal>game.reset()</literal> to start a new game and
+ refreshes the messages in the UI.
+ </para>
+ </callout>
+ <callout arearefs="refresh">
+ <para>
+ <literal>refreshUI</literal> uses the
+ <literal>MessageGenerator</literal> to update the messages
+ to the user based on the current state of the Game.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </section>
+ </section>
+
+ <section>
+ <title>The translator example</title>
+
+ <para>
+ The translator example will take any sentences you enter, and translate
+ them to Latin.
+ </para>
+
+ <para>
+ 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!
+ </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:
+ </para>
+
+ <programlisting role="XML"><![CDATA[<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-ear-plugin</artifactId>
+ <configuration>
+ <modules>
+ <webModule>
+ <groupId>org.jboss.webbeans.examples.translator</groupId>
+ <artifactId>webbeans-translator-war</artifactId>
+ <contextRoot>/webbeans-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>).
+ </para>
+
+ <tip>
+ <para>
+ If you aren'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>
+
+ <module>
+ <web>
+ <web-uri>webbeans-translator.war</web-uri>
+ <context-root>/webbeans-translator</context-root>
+ </web>
+ </module>
+ <module>
+ <ejb>webbeans-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>.
+ </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):
+ </para>
+
+ <programlisting role="XML"><![CDATA[<h:form id="NumberGuessMain">
+
+ <table>
+ <tr align="center" style="font-weight: bold" >
+ <td>
+ Your text
+ </td>
+ <td>
+ Translation
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
+ </td>
+ <td>
+ <h:outputText value="#{translator.translatedText}" />
+ </td>
+ </tr>
+ </table>
+ <div>
+ <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
+ </div>
+
+</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.
+ </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.
+ </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.
+ </para>
+
+ <para>
+ Both <literal>SentenceParser</literal> and
+ <literal>TextTranslator</literal> are dependent beans, and
+ <literal>TextTranslator</literal> uses constructor initialization:
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[public class TextTranslator {
+ private SentenceParser sentenceParser;
+ private Translator sentenceTranslator;
+
+ @Initializer
+ TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator)
+ {
+ this.sentenceParser = sentenceParser;
+ this.sentenceTranslator = sentenceTranslator;]]></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!
+ </para>
+
+ <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.
+ </para>
+
+ <programlisting role="JAVA"><![CDATA[@Stateful
+@RequestScoped
+@Named("translator")
+public class TranslatorControllerBean implements TranslatorController
+{
+
+ @Current TextTranslator translator;]]></programlisting>
+
+ <para>
+ The bean also has getters and setters for all the fields on the page.
+ </para>
+
+ <para>
+ As this is a stateful session bean, we have to have a remove method:
+ </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://www.seamframework.org/WebBeans/Development</ulink>.
+ </para>
+
+ <para>
+ We need help in all areas - bug fixing, writing new features, writing
+ examples and translating this reference guide.
+ </para>
+
+</chapter>
\ No newline at end of file
Property changes on: doc/trunk/reference/en-US/gettingstarted.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:mergeinfo
+
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-04-19 19:57:30 UTC (rev 2515)
+++ doc/trunk/reference/en-US/master.xml 2009-04-19 20:24:44 UTC (rev 2516)
@@ -32,7 +32,7 @@
<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" />
<xi:include href="example.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
- <xi:include href="ri.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="gettingstarted.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<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" />
Deleted: doc/trunk/reference/en-US/ri.xml
===================================================================
--- doc/trunk/reference/en-US/ri.xml 2009-04-19 19:57:30 UTC (rev 2515)
+++ doc/trunk/reference/en-US/ri.xml 2009-04-19 20:24:44 UTC (rev 2516)
@@ -1,1087 +0,0 @@
-<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
-
-<chapter id="ri">
- <title>Getting started with Web Beans, the Reference Implementation of JSR-299</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>
-
- <para>
- Web Beans comes with a two deployable example applications:
- <literal>webbeans-numberguess</literal>, a war example, containing only
- simple beans, and <literal>webbeans-translator</literal> an ear example,
- containing enterprise beans. There are also two variations on the
- numberguess example, the tomcat example (suitable for deployment to
- Tomcat) and the jsf2 example, which you can use if you are running JSF2.
- To run the examples you'll need the following:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>the latest release of Web Beans,</para>
- </listitem>
- <listitem>
- <para>JBoss AS 5.0.1.GA, or</para>
- </listitem>
- <listitem>
- <para>Apache Tomcat 6.0.x, and</para>
- </listitem>
- <listitem>
- <para>Ant 1.7.0.</para>
- </listitem>
- </itemizedlist>
-
- <section>
- <title>Using JBoss AS 5</title>
-
- <para>
- You'll need to download JBoss AS 5.0.1.GA from
- <ulink url="http://www.jboss.org/jbossas/downloads/">jboss.org</ulink>,
- and unzip it. For example:
- </para>
-
- <programlisting><![CDATA[$ cd /Applications
-$ unzip ~/jboss-5.0.1.GA.zip]]></programlisting>
-
- <para>
- Next, download Web Beans from
- <ulink url="http://seamframework.org/Download">seamframework.org</ulink>,
- and unzip it. For example
- </para>
-
- <programlisting><![CDATA[$ cd ~/
-$ unzip ~/webbeans-$VERSION.zip]]></programlisting>
-
-
- <para>
- Next, we need to tell Web Beans where JBoss is located. Edit
- <literal>jboss-as/build.properties</literal> and set the
- <literal>jboss.home</literal> property. For example:
- </para>
-
- <programlisting>jboss.home=/Applications/jboss-5.0.1.GA</programlisting>
-
- <para>
- To install Web Beans, you'll need Ant 1.7.0 installed, and the
- <literal>ANT_HOME</literal> environment variable set. For example:
- </para>
-
- <programlisting>$ unzip apache-ant-1.7.0.zip
-$ export ANT_HOME=~/apache-ant-1.7.0</programlisting>
-
- <para>
- Then, you can install the update. The update script will use Maven to
- download Web Beans automatically.
- </para>
-
- <programlisting>$ cd webbeans-$VERSION/jboss-as
-$ ant update</programlisting>
-
- <para>
- Now, you're ready to deploy your first example!
- </para>
-
- <tip>
- <para>
- The build scripts for the examples offer a number of targets for
- JBoss AS, these are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>ant restart</literal> - deploy the example in exploded
- format
- </para>
- </listitem>
- <listitem>
- <para>
- <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
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ant undeploy</literal> - remove the example from the server
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ant clean</literal> - clean the example
- </para>
- </listitem>
- </itemizedlist>
- </tip>
-
- <para>
- To deploy the numberguess example:
- </para>
-
- <programlisting>$ cd examples/numberguess
-ant deploy</programlisting>
-
- <para>
- Start JBoss AS:
- </para>
-
- <programlisting>$ /Application/jboss-5.0.0.GA/bin/run.sh</programlisting>
-
- <tip>
- <para>
- If you use Windows, use the <literal>run.bat</literal>script.
- </para>
- </tip>
-
- <para>
- Wait for the application to deploy, and enjoy hours of fun at
- <ulink url="http://localhost:8080/webbeans-numberguess" />!
- </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:
- </para>
-
- <programlisting>$ cd examples/translator
-ant deploy</programlisting>
-
- <para>
- Wait for the application to deploy, and visit
- <ulink url="http://localhost:8080/webbeans-translator" />!
- </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.org</ulink>,
- and unzip it. For example:
- </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</ulink>,
- and unzip it. For example
- </para>
-
- <programlisting><![CDATA[$ cd ~/
-$ unzip ~/webbeans-$VERSION.zip]]></programlisting>
-
- <para>
- Next, we need to tell Web Beans where Tomcat is located. Edit
- <literal>jboss-as/build.properties</literal> and set the
- <literal>tomcat.home</literal> property. For example:
- </para>
-
- <programlisting>tomcat.home=/Applications/apache-tomcat-6.0.18</programlisting>
-
- <tip>
- <para>
- The build scripts for the examples offer a number of targets for
- Tomcat, these are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- <literal>ant tomcat.restart</literal> - deploy the example in exploded
- format
- </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
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ant tomcat.undeploy</literal> - remove the example from the server
- </para>
- </listitem>
- <listitem>
- <para>
- <literal>ant tomcat.clean</literal> - clean the example
- </para>
- </listitem>
- </itemizedlist>
- </tip>
-
- <para>
- To deploy the numberguess example for tomcat:
- </para>
-
- <programlisting>$ cd examples/tomcat
-ant tomcat.deploy</programlisting>
-
- <para>
- Start Tomcat:
- </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>
- Wait for the application to deploy, and enjoy hours of fun at
- <ulink url="http://localhost:8080/webbeans-numberguess" />!
- </para>
-
- </section>
-
- <section>
- <title>Using GlassFish</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.
- </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.
- </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:
- </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>
-
-</faces-config>]]></programlisting>
-
- <para>
- There is an empty <literal>web-beans.xml</literal> file, which marks
- this application as a Web Beans application.
- </para>
-
- <para>
- Finally there is <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" />
- </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">
-
- <display-name>Web Beans Numbergues example</display-name>
-
- <!-- JSF -->
-
- <servlet>
- <servlet-name>Faces Servlet</servlet-name>
- <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>Faces Servlet</servlet-name>
- <url-pattern>*.jsf</url-pattern>
- </servlet-mapping>
-
- <context-param>
- <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
- <param-value>.xhtml</param-value>
- </context-param>
-
- <session-config>
- <session-timeout>10</session-timeout>
- </session-config>
-
-</web-app>]]></programlisting>
- <calloutlist>
- <callout arearefs="faces.servlet">
- <para>
- Enable and load the JSF servlet
- </para>
- </callout>
- <callout arearefs="faces.servlet.mapping">
- <para>
- Configure requests to <literal>.jsf</literal> pages 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
- extension of <literal>.xhtml</literal>
- </para>
- </callout>
- <callout arearefs="session.timeout">
- <para>
- Configure a session timeout of 10 minutes
- </para>
- </callout>
- </calloutlist>
- </programlistingco>
-
- <note>
- <para>
- Whilst this demo is a JSF demo, you can use Web Beans with any
- Servlet based web framework.
- </para>
- </note>
-
- <para>
- Let's take a look at the Facelet view:
- </para>
-
- <programlistingco>
- <areaspec>
- <area id="template" coords="8" />
- <area id="messages" coords="12" />
- <area id="instructions" coords="19" />
- <area id="guess" coords="25" />
- <area id="validator" coords="30" />
- <area id="submit" coords="33" />
- </areaspec>
- <programlisting><![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">
-
- <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>
-</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.
- </para>
- </callout>
- <callout arearefs="messages">
- <para>
- There are a number of messages which can be sent to the user,
- "Higher!", "Lower!" and "Correct!"
- </para>
- </callout>
- <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.
- </para>
- </callout>
- <callout arearefs="guess">
- <para>
- This input field is bound to a Web Bean, using the value
- expression.
- </para>
- </callout>
- <callout arearefs="validator">
- <para>
- A range validator 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.
- </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.
- </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:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
-@Retention(RUNTIME)
-@Documented
-@BindingType
-public @interface Random {}]]></programlisting>
-
- <para>
- There is also the <literal>@MaxNumber</literal> binding type, used for
- injecting the maximum number that can be injected:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Target( { TYPE, METHOD, PARAMETER, FIELD })
-@Retention(RUNTIME)
-@Documented
-@BindingType
-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:
- </para>
-
- <programlisting role="JAVA"><![CDATA[@ApplicationScoped
-public class Generator {
-
- private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
-
- private int maxNumber = 100;
-
- java.util.Random getRandom()
- {
- return random;
- }
-
- @Produces @Random int next() {
- return getRandom().nextInt(maxNumber);
- }
-
- @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.
- </para>
-
- <para>
- The final Web Bean in the application is the session scoped
- <literal>Game</literal>.
- </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>.
- </para>
-
- <programlisting role="JAVA"><![CDATA[package org.jboss.webbeans.examples.numberguess;
-
-
-import javax.annotation.PostConstruct;
-import javax.faces.application.FacesMessage;
-import javax.faces.context.FacesContext;
-import javax.webbeans.AnnotationLiteral;
-import javax.webbeans.Current;
-import javax.webbeans.Initializer;
-import javax.webbeans.Named;
-import javax.webbeans.SessionScoped;
-import javax.webbeans.manager.Manager;
-
-@Named
-@SessionScoped
-public class Game
-{
- private int number;
-
- private int guess;
- private int smallest;
- private int biggest;
- private int remainingGuesses;
-
- @Current Manager manager;
-
- public Game()
- {
- }
-
- @Initializer
- Game(@MaxNumber int maxNumber)
- {
- this.biggest = maxNumber;
- }
-
- 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;
- }
-
- public String check()
- {
- if (guess>number)
- {
- biggest = guess - 1;
- }
- if (guess<number)
- {
- smallest = guess + 1;
- }
- if (guess == number)
- {
- FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
- }
- remainingGuesses--;
- return null;
- }
-
- @PostConstruct
- public void reset()
- {
- this.smallest = 0;
- this.guess = 0;
- this.remainingGuesses = 10;
- this.number = manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){});
- }
-
-}]]></programlisting>
-
- <section>
- <title>The numberguess example for Tomcat</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>.
- </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.
- </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>:
- </para>
-
- <programlisting><![CDATA[<listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
-</listener>]]></programlisting>
-
- </section>
-
- <section id="numberguessWicket">
- <title>The numberguess example in 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.
- </para>
-
- <note>
- <para>
- You may want to review the Wicket documentation at
- <ulink url="http://wicket.apache.org/">http://wicket.apache.org/</ulink>.
- </para>
- </note>
-
- <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.
- </para>
-
- <para>
- These examples make use of the Eclipse IDE; instructions are also
- given to deploy the application from the command line.
- </para>
-
- <section>
- <title>Creating the Eclipse project</title>
-
- <para>
- To generate an Eclipse project from the example:
- </para>
-
- <programlisting><![CDATA[cd examples/wicket/numberguess
-mvn 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. This will create a project in your workspace called
- <literal>webbeans-wicket-numberguess</literal>
- </para>
-
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/wicket-numberguess-project.png" format="PNG"/>
- </imageobject>
- </mediaobject>
- </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>.
- </para>
- </section>
-
- <section>
- <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>.
- </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).
- </para>
-
- <para>
- The code in the wicket numberguess example is very similar to the
- JSF-based numberguess example. The business layer is identical!
- </para>
-
- <para>
- Differences are:
- </para>
- <itemizedlist>
- <listitem>
- <para>
- Each wicket application must have a
- <literal>WebApplication</literal> subclass, In our case,
- our application class is
- <literal>SampleApplication</literal>:
- </para>
- <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication {
- @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>
- </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:
- </para>
-
- <programlisting><![CDATA[ @Current Game game;]]></programlisting>
-
- <para>
- 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") {
- protected void onSubmit(AjaxRequestTarget target, Form form) {
- if (game.check()) {]]></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
- <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.
- </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.
- </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:
- </para>
- <programlisting><![CDATA[<filter>
- <filter-name>wicket.numberguess-example</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>
- </init-param>
-</filter>
-
-<filter-mapping>
- <filter-name>wicket.numberguess-example</filter-name>
- <url-pattern>/*</url-pattern>
-</filter-mapping>
-
-<listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
-</listener>]]></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.
- </para>
- </listitem>
-
- </itemizedlist>
- </section>
- </section>
- </section>
-
- <section>
- <title>The translator example</title>
-
- <para>
- The translator example will take any sentences you enter, and translate
- them to Latin.
- </para>
-
- <para>
- 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!
- </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:
- </para>
-
- <programlisting role="XML"><![CDATA[<plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-ear-plugin</artifactId>
- <configuration>
- <modules>
- <webModule>
- <groupId>org.jboss.webbeans.examples.translator</groupId>
- <artifactId>webbeans-translator-war</artifactId>
- <contextRoot>/webbeans-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>).
- </para>
-
- <tip>
- <para>
- If you aren'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>
-
- <module>
- <web>
- <web-uri>webbeans-translator.war</web-uri>
- <context-root>/webbeans-translator</context-root>
- </web>
- </module>
- <module>
- <ejb>webbeans-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>.
- </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):
- </para>
-
- <programlisting role="XML"><![CDATA[<h:form id="NumberGuessMain">
-
- <table>
- <tr align="center" style="font-weight: bold" >
- <td>
- Your text
- </td>
- <td>
- Translation
- </td>
- </tr>
- <tr>
- <td>
- <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
- </td>
- <td>
- <h:outputText value="#{translator.translatedText}" />
- </td>
- </tr>
- </table>
- <div>
- <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
- </div>
-
-</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.
- </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.
- </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.
- </para>
-
- <para>
- Both <literal>SentenceParser</literal> and
- <literal>TextTranslator</literal> are dependent beans, and
- <literal>TextTranslator</literal> uses constructor initialization:
- </para>
-
- <programlisting role="JAVA"><![CDATA[public class TextTranslator {
- private SentenceParser sentenceParser;
- private Translator sentenceTranslator;
-
- @Initializer
- TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator)
- {
- this.sentenceParser = sentenceParser;
- this.sentenceTranslator = sentenceTranslator;]]></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!
- </para>
-
- <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.
- </para>
-
- <programlisting role="JAVA"><![CDATA[@Stateful
-@RequestScoped
-@Named("translator")
-public class TranslatorControllerBean implements TranslatorController
-{
-
- @Current TextTranslator translator;]]></programlisting>
-
- <para>
- The bean also has getters and setters for all the fields on the page.
- </para>
-
- <para>
- As this is a stateful session bean, we have to have a remove method:
- </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://www.seamframework.org/WebBeans/Development</ulink>.
- </para>
-
- <para>
- We need help in all areas - bug fixing, writing new features, writing
- examples and translating this reference guide.
- </para>
-
-</chapter>
\ No newline at end of file
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2515 - doc/trunk/reference/en-US.
by webbeans-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2009-04-19 15:57:30 -0400 (Sun, 19 Apr 2009)
New Revision: 2515
Modified:
doc/trunk/reference/en-US/ri.xml
Log:
minor
Modified: doc/trunk/reference/en-US/ri.xml
===================================================================
--- doc/trunk/reference/en-US/ri.xml 2009-04-19 19:56:39 UTC (rev 2514)
+++ doc/trunk/reference/en-US/ri.xml 2009-04-19 19:57:30 UTC (rev 2515)
@@ -1,7 +1,7 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
<chapter id="ri">
- <title>Web Beans, the Reference Implementation of JSR-299</title>
+ <title>Getting started with Web Beans, the Reference Implementation of JSR-299</title>
<para>
The Web Beans is being developed at
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2514 - doc/trunk/reference/en-US.
by webbeans-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2009-04-19 15:56:39 -0400 (Sun, 19 Apr 2009)
New Revision: 2514
Added:
doc/trunk/reference/en-US/viewlayers.xml
Modified:
doc/trunk/reference/en-US/master.xml
doc/trunk/reference/en-US/ri.xml
doc/trunk/reference/en-US/scopescontexts.xml
Log:
reorganize wicket docs
Modified: doc/trunk/reference/en-US/master.xml
===================================================================
--- doc/trunk/reference/en-US/master.xml 2009-04-19 09:55:50 UTC (rev 2513)
+++ doc/trunk/reference/en-US/master.xml 2009-04-19 19:56:39 UTC (rev 2514)
@@ -79,6 +79,7 @@
<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>
Modified: doc/trunk/reference/en-US/ri.xml
===================================================================
--- doc/trunk/reference/en-US/ri.xml 2009-04-19 09:55:50 UTC (rev 2513)
+++ doc/trunk/reference/en-US/ri.xml 2009-04-19 19:56:39 UTC (rev 2514)
@@ -676,135 +676,213 @@
<section id="numberguessWicket">
<title>The numberguess example in Apache Wicket</title>
- <para>Although the JSR299 specification includes detailed information on how WebBeans integrates
- with Java Server Faces, it is possible to use WebBeans injection, as well as the WebBeans conversational
- context, with other web frameworks. In this section, we'll look at the module which allows integration of
- WebBeans with the Apache Wicket framework. This documentation assumes that you have some familiarity
- with Wicket; if not, please visit <ulink url="http://wicket.apache.org/">http://wicket.apache.org/</ulink>
- to learn more. In this section we'll look at the previous "numberguess" example as implemented with Wicket.
- We'll look at the conversational aspects of the Wicket/WebBeans integration in <xref linkend="wicketContexts"/></para>
+ <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.
+ </para>
+
+ <note>
+ <para>
+ You may want to review the Wicket documentation at
+ <ulink url="http://wicket.apache.org/">http://wicket.apache.org/</ulink>.
+ </para>
+ </note>
- <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. Since we
- are deploying to a servlet container, we are also building as a WAR. In addition, these examples make use of the Eclipse IDE,
- although instructions are also given to deploy the application from the command line.</para>
+ <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.
+ </para>
+
+ <para>
+ These examples make use of the Eclipse IDE; instructions are also
+ given to deploy the application from the command line.
+ </para>
- <section>
- <title>Creating the eclipse project</title>
- <para>To generate an eclipse project from the example, use apache maven and the eclipse:eclipse
- plugin:
- <programlisting><![CDATA[cd examples/wicket/numberguess
-mvn eclipse:eclipse -DdownloadSources]]></programlisting>
- Then, from eclipse, choose <literal>File -> Import -> General -> Existing Projects into Workspace</literal>, choose
- the root directory of the numberguess example, and click finish. This should result in a project in
- your workspace named <literal>webbeans-wicket-numberguess</literal>:
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/wicket-numberguess-project.png" format="png"/>
- </imageobject>
- </mediaobject>
- </para>
- </section>
+ <section>
+ <title>Creating the Eclipse project</title>
+
+ <para>
+ To generate an Eclipse project from the example:
+ </para>
+
+ <programlisting><![CDATA[cd examples/wicket/numberguess
+mvn 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. This will create a project in your workspace called
+ <literal>webbeans-wicket-numberguess</literal>
+ </para>
- <section>
- <title>Running the example from eclipse</title>
- <para>This project follows the <literal>wicket-quickstart</literal>
- approach of creating an instance of <literal>jetty</literal> through a <literal>Start</literal>
- class. So running the example is as simple as right-clicking on that Start class in src/test/java in the package
- explorer and choosing "Run as Java Application." You should then see console output related to jetty starting up,
- and then be able to hit <literal>http://localhost:8080</literal> to view the app. To stop the app, switch to the Console
- View and click the red stop square. One can also debug in the same fashion, by choosing "Debug as Java Application" when right-clicking.
- </para>
- </section>
- <section>
- <title>Running the example from the command line in Jboss or Tomcat</title>
- <para>This example can also be deployed from the command line in a fashion 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 or Tomcat, as previously
- described, you can simply 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>.
- </para>
- </section>
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/wicket-numberguess-project.png" format="PNG"/>
+ </imageobject>
+ </mediaobject>
+ </section>
- <section>
- <title>Understanding the code</title>
- <para>While JSF uses unified EL expressions to bind view layer components in jsp or xhtml to
- WebBeans, Wicket keeps a stricter separation of concerns in place. The markup is plain html with
- a one-to-one mapping between html elements and the view components, which are constructed in java code. All
- view logic, including binding of components to models and controlling the response of view actions,
- is handled in java code. Therefore, the integration of WebBeans with Wicket takes place through annotated
- injections of WebBeans into your WebPage subclass (or into other custom wicket component subclasses.)</para>
+ <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>.
+ </para>
+ </section>
+
+ <section>
+ <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>.
+ </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).
+ </para>
- <para>The code in the wicket numberguess example is very similar to the JSF-based numberguess example described previously. The business logic
- components (Game, Generator, MaxNumber, etc.) are the same. Differences include the following:</para>
- <itemizedlist>
- <listitem><para>Each wicket application must have a <literal>WebApplication</literal> subclass,
- and in the case of the Wicket/WebBeans integration, this class should subclass <literal>
- org.jboss.webbeans.wicket.WebBeansApplication</literal>. (If you would prefer not to subclass
- WebBeansApplication, you can manually add the small number of overrides and listeners to your own WebApplication
- subclass. See the javadocs on WebBeansApplication for details.) In our case, our application class is called<literal>
- SampleApplication</literal>:
- <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication
-{
+ <para>
+ The code in the wicket numberguess example is very similar to the
+ JSF-based numberguess example. The business layer is identical!
+ </para>
+
+ <para>
+ Differences are:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Each wicket application must have a
+ <literal>WebApplication</literal> subclass, In our case,
+ our application class is
+ <literal>SampleApplication</literal>:
+ </para>
+ <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication {
@Override
- public Class getHomePage()
- {
+ public Class getHomePage() {
return HomePage.class;
}
-}]]></programlisting>This class specifies which page wicket should treat as our HomePage,
-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
- bits that are interesting with respect to WebBeans are the injection of the <literal>Game</literal>
- WebBean the top of the class</para>
- <programlisting><![CDATA[ @Current Game game;]]></programlisting> which is then used later in,
- for example, the code for submitting a guess:<programlisting><![CDATA[final Component guessButton = new AjaxButton("GuessButton") {
+}]]></programlisting>
+ <para>
+ 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:
+ </para>
+
+ <programlisting><![CDATA[ @Current Game game;]]></programlisting>
+
+ <para>
+ 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") {
protected void onSubmit(AjaxRequestTarget target, Form form) {
- if (game.check()) {]]></programlisting>This injection is a proxy which holds a transient reference to the actual
- Game WebBean, and is therefore safe with respect to the serialization of the wicket page. Actual
- storage of the bean is in the session, and is managed by WebBeans. Note that Wicket components, like the HomePage and its
- subcomponents, are <emphasis>not</emphasis> WebBeans. Their construction is handled directly by wicket (for
- the page itself) and by the example code (for the nested page elements), and not by the WebBeans
- Manager. However, the <literal>
- webbeans-wicket</literal> integration takes care of injecting dependencies into the page for us. This
- injection occurs through an <literal>IComponentInstantiationListener</literal> which is
- registered by the <literal>WebbeansWebApplication</literal>. This means that although wicket
- components can have injections, they <emphasis>cannot</emphasis> use interceptors and the other features
- of real WebBeans. The delegate beans used by the wicket code can of course be full WebBeans,
- as the <literal>Game</literal> bean is in this example.</listitem>
- <listitem><para>Note that this example also uses ajax for processing of button events, and
- dynamically hides buttons that are no longer revelant, for example when the user has won the game.</para></listitem>
+ if (game.check()) {]]></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
+ <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.
+ </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.
+ </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:
- <programlisting><![CDATA[ <filter>
- <filter-name>wicket.numberguess-example</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>
- </init-param>
+ <listitem>
+ <para>
+ In order to activate wicket for this webapp, the Wicket
+ filter is added to web.xml, and our application class is
+ specified:
+ </para>
+ <programlisting><![CDATA[<filter>
+ <filter-name>wicket.numberguess-example</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>
+ </init-param>
</filter>
<filter-mapping>
- <filter-name>wicket.numberguess-example</filter-name>
- <url-pattern>/*</url-pattern>
+ <filter-name>wicket.numberguess-example</filter-name>
+ <url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
- <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
-</listener>]]></programlisting>Note that the servlet listener is also added, as in the tomcat example, in order to boostrap
-WebBeans when jetty starts, and to hook WebBeans into the jetty servlet request and session lifecycles.</para>
-</listitem>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+</listener>]]></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.
+ </para>
+ </listitem>
- </itemizedlist>
-
-
- </section>
-
+ </itemizedlist>
+ </section>
+ </section>
</section>
- </section>
<section>
<title>The translator example</title>
Modified: doc/trunk/reference/en-US/scopescontexts.xml
===================================================================
--- doc/trunk/reference/en-US/scopescontexts.xml 2009-04-19 09:55:50 UTC (rev 2513)
+++ doc/trunk/reference/en-US/scopescontexts.xml 2009-04-19 19:56:39 UTC (rev 2514)
@@ -246,148 +246,8 @@
<programlisting role="JAVA">conversation.setTimeout(timeoutInMillis);</programlisting>
</section>
-
- <section id="wicketContexts">
- <title>Conversations using Wicket</title>
- <para>The conversation scope can also be used in WebBeans with the Apache Wicket web framework, through the
- <literal>webbeans-wicket</literal> module. This module takes care of:
- <itemizedlist>
- <listitem><para>Setting up the conversation context at the beginning of a wicket request, and tearing it down afterwards</para></listitem>
- <listitem><para>Storing the id of any long-running conversation in Wicket's WebPage metadata when the page response is complete</para></listitem>
- <listitem><para>Activating the correct long-running conversation based upon which page is being accessed</para></listitem>
- <listitem><para>Propagating the conversation context for any long-running conversation to new pages</para></listitem>
- </itemizedlist> </para>
- <section>
- <title>Starting and stopping conversations in Wicket</title>
- <para>As in WebBeans JSF applications, a conversation <emphasis>always</emphasis> exists for any request, but its lifetime is only that of the current request unless it is marked as
- <emphasis>long-running</emphasis>. For Wicket applications this is accomplished exactly as in JSF applications, by injecting the <literal>@Current Conversation</literal> and then
- invoking <literal>conversation.begin()</literal>. Likewise, conversations are ended with <literal>conversation.end()</literal>
- </para>
- </section>
-
- <section>
- <title>Long running conversation propagation in Wicket</title>
- <para>
- When a conversation is marked as long-running, the id of that conversation will be stored in Wicket's WebPage metadata for the current page.
- In addition, if a new page is created and set as the response target through <literal>setResponsePage</literal>, this new page will also participate
- in this conversation. This occurs for both directly instantiated pages, i.e. <literal>setResponsePage(new OtherPage())</literal> as well as for
- bookmarkable pages created with <literal>setResponsePage(OtherPage.class)</literal> where <literal>OtherPage.class</literal> is mounted as bookmarkable
- from your <literal>WebApplication</literal> subclass (or through annotations.) In the latter case, because the new page instance is not created until after
- a redirect, the conversation id will be propagated through a request parameter, and then stored in page metadata after the redirect.
- </para>
- </section>
- <section>
- <title>The Wicket Conversations Example</title>
- <para>In <literal>examples/wicket/conversations</literal> there is an example application for using conversations from Wicket. To setup and run the
- application, follow the examples in <xref linkend="numberguessWicket"/>. If running within eclipse, the application is available at <literal>http://localhost:8080</literal>,
- and if running within an external container, the app is available at <literal>http://localhost:8080/webbeans-conversations-wicket</literal>.
- </para>
- <section>
- <title>Using the application</title>
- <para>The <emphasis>conversations</emphasis> application is simply an interface to begin and end conversations, switch between them, and store a single piece of data in each.
- The interface looks like the following:
- <mediaobject>
- <imageobject>
- <imagedata fileref="images/wicket-conversations-snap.png" format="PNG"/>
- </imageobject>
- </mediaobject></para>
- <para>
- The menu at the top will show the list of long-running conversations, along with data about each,
- as well as the active conversation (even if it is not long running.) The currently selected item
- of this menu is the current conversation for the last request that was processed. Changing this menu
- changes the current conversation. The "Data in conversation" text box and the submit
- button labeled "Change Value" allow you to change a piece of string data associated
- with the conversation. The "begin" button marks the conversation as long running.
- The "noop" button submits the form without changing the state of the conversation.
- The "end" button ends the current conversation. The "longop" button
- executes a method that takes a few seconds, which can be used to play with conversation timeouts and
- synchronization/locking. The "Abandon" link redirects to the HomePage without propagating
- the conversation, thus starting a new temporary conversation. The conversation that has been abandoned
- can be rejoined by selecting it in the popup.</para>
- </section>
- <section>
- <title>Understanding the code</title>
- <para>As in <xref linkend="numberguessWicket"/>, there is boilerplate code in the
- SampleApplication, as well as in web.xml, to ensure correct integration of Wicket and Webbeans.
- Other pieces of this application include:</para>
- <itemizedlist>
- <listitem><para>The <literal>Conversations</literal> class exists to allow configuration of the conversation
- timeout for the current session<programlisting><![CDATA[@Produces
-@ConversationInactivityTimeout
-@Example
-public static long getConversationTimeoutInMilliseconds()
-{
- return 600000;
-}]]></programlisting>The <literal>Example</literal> deployment type is used to illustrate
-custom deployment types. It is defined in Example.java:<programlisting><![CDATA[@Target( { TYPE, METHOD, FIELD })
-@Retention(RUNTIME)
-@Documented
-@DeploymentType
-public @interface Example
-{
-}]]></programlisting> and is activated in <literal>WEB-INF/beans.xml</literal>:
-<programlisting><![CDATA[<Beans xmlns="urn:java:ee" xmlns:conversations="urn:java:org.jboss.webbeans.examples.conversations">
- <Deploy>
- <Standard />
- <Production />
- <conversations:Example />
- </Deploy>
-</Beans>]]></programlisting></para></listitem>
-<listitem><para>The <literal>Data</literal> class is our conversational component that stores a
-single string:<programlisting><![CDATA[@ConversationScoped
-@Named
-public class Data implements Serializable
-{
- private String data;
- public String getData()
- {
- return data;
- }
-
- public void setData(String data)
- {
- this.data = data;
- }
-}]]></programlisting></para></listitem>
-<listitem><para>The <literal>HomePage</literal> class is where
-the brunt of the work takes place. It injects the WebBeans-provided <literal>ConversationManager</literal>
-component in order to access the list of long-running conversations, injects the current <literal>Conversation</literal>
-in order to allow control over whether that conversation is long-running, and injects the <literal>Data</literal>
-component to allow its manipulation by the textfield:<programlisting><![CDATA[/**
-* These are injections for displaying information about existing conversations to the user
-*/
-@Current ConversationManager conversationManager;
-@Current Conversation currentConversation;
-
-/**
-* This is our conversational data component, to illustrate how data is used in conversations and
-* exists per-conversation.
-*/
-@Current Data data;
-]]></programlisting>The data component is referenced by the wicket TextField using a
-<literal>PropertyModel</literal>:<programlisting><![CDATA[form.add(new TextField("dataField", new PropertyModel(this, "data.data")));]]></programlisting>
-This means that for each page, the text field is referring to the "data" property of the "Data" bean that is specific to
-the conversation that is active for the request, whether that be a transient conversation that is created for the request
-or a long-running conversation associated with the page. If one types data into the text field
-and clicks <literal>Change Value</literal>
-when a long-running conversation is not started, and then clicks <literal>noop</literal>, the
-value in the text field disappears, because it was associated with a transient conversation, and
-upon redirect, the new conversation had a different Data object, which had the default (empty) value.</para>
-<para>As you can see by the other code in this example, conversations are started and ended programmatically,
-and no WebBeans-specific code is necessary to propagate the conversation. The only exception to this
-is in the code to <emphasis>switch</emphasis> conversations, which is not a typical operation in real scenarios.
-In this case, a conversation id (<literal>cid</literal>) request parameter is passed to the <literal>setResponsePage</literal>
-invocation, and this explicit conversation id will override the id that the wicket/webbeans integration
-code would normally generate in order to propagate the current conversation, and hence the specified
-conversation will be active upon redirect.</para>
-</listitem>
-</itemizedlist>
-
</section>
-</section>
-</section>
-</section>
<section>
<title>The dependent pseudo-scope</title>
Added: doc/trunk/reference/en-US/viewlayers.xml
===================================================================
--- doc/trunk/reference/en-US/viewlayers.xml (rev 0)
+++ doc/trunk/reference/en-US/viewlayers.xml 2009-04-19 19:56:39 UTC (rev 2514)
@@ -0,0 +1,113 @@
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ ]>
+
+<chapter id="viewlayers">
+ <title>Alternative view layers</title>
+
+ <section>
+ <title>Using Web Beans with Wicket</title>
+
+ <section>
+ <title>The <literal>WebApplication</literal> class</title>
+
+ <para>
+ Each wicket application must have a
+ <literal>WebApplication</literal> subclass; Web Beans provides, for
+ your utility, a subclass of this which sets up the Wicket/JSR-299
+ integration. You should subclass
+ <literal>org.jboss.webbeans.wicket.WebBeansApplication</literal>.
+ </para>
+
+ <note>
+ <para>
+ If you would prefer not to subclass
+ <literal>WebBeansApplication</literal>, you can manually add a
+ (small!) number of overrides and listeners to your own
+ <literal>WebApplication</literal> subclass. The javadocs of
+ <literal>WebBeansApplication</literal>detail this.
+ </para>
+ </note>
+
+ <para>
+ For example:
+ </para>
+ <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication {
+ @Override
+ public Class getHomePage() {
+ return HomePage.class;
+ }
+}]]></programlisting>
+ </section>
+
+ <section id="wicketContexts">
+ <title>Conversations with Wicket</title>
+ <para>
+ The conversation scope can be used in Web Beans with the Apache
+ Wicket web framework, through the <literal>webbeans-wicket</literal>
+ module. This module takes care of:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Setting up the conversation context at the beginning of a
+ Wicket request, and tearing it down afterwards
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Storing the id of any long-running conversation in Wicket's
+ metadata when the page response is complete
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Activating the correct long-running conversation based upon
+ which page is being accessed
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Propagating the conversation context for any long-running conversation to new pages
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <section>
+ <title>Starting and stopping conversations in Wicket</title>
+ <para>
+ As JSF applications, a conversation
+ <emphasis>always</emphasis> exists for any request, but its
+ lifetime is only that of the current request unless it is
+ marked as <emphasis>long-running</emphasis>. For Wicket
+ applications this is accomplished as in JSF applications, by
+ injecting the <literal>@Current Conversation</literal> and
+ then invoking <literal>conversation.begin()</literal>.
+ Likewise, conversations are ended with
+ <literal>conversation.end()</literal>
+ </para>
+ </section>
+
+ <section>
+ <title>Long running conversation propagation in Wicket</title>
+ <para>
+ When a conversation is marked as long-running, the id of that
+ conversation will be stored in Wicket's metadata for the current
+ page. If a new page is created and set as the response target
+ through <literal>setResponsePage</literal>, this new page will
+ also participate in this conversation. This occurs for both
+ directly instantiated pages
+ (<literal>setResponsePage(new OtherPage())</literal>), as well as
+ for bookmarkable pages created with
+ <literal>setResponsePage(OtherPage.class)</literal> where
+ <literal>OtherPage.class</literal> is mounted as bookmarkable
+ from your <literal>WebApplication</literal> subclass (or through
+ annotations). In the latter case, because the new page instance
+ is not created until after a redirect, the conversation id will
+ be propagated through a request parameter, and then stored in
+ page metadata after the redirect.
+ </para>
+ </section>
+ </section>
+
+ </section>
+
+</chapter>
\ No newline at end of file
Property changes on: doc/trunk/reference/en-US/viewlayers.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2513 - doc/trunk/reference/en-US.
by webbeans-commits@lists.jboss.org
Author: peteroyle
Date: 2009-04-19 05:55:50 -0400 (Sun, 19 Apr 2009)
New Revision: 2513
Modified:
doc/trunk/reference/en-US/environments.xml
Log:
added documentation for Swing Number Guess SE example
Modified: doc/trunk/reference/en-US/environments.xml
===================================================================
--- doc/trunk/reference/en-US/environments.xml 2009-04-19 09:50:29 UTC (rev 2512)
+++ doc/trunk/reference/en-US/environments.xml 2009-04-19 09:55:50 UTC (rev 2513)
@@ -276,12 +276,399 @@
<literal>StartMain</literal>.
</para>
</note>
-
-
</section>
+ <section>
+ <title>Swing Example: Number Guess</title>
+ <para>Here's an example of a Swing application, Number Guess, similar to the example in
+ chapter 3.4. In the Number Guess 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. This example can be found in the
+ <literal>examples/se/numberguess</literal> folder of the Web Beans distribution.
+ </para>
+
+ <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.
+ </para>
+
+ <para>The game's main logic is located in <literal>Game.java</literal>. Here is the code for
+ that class, excluding that which is identical to the JSF version: </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="scope" coords="1" />
+ <area id="name" coords="1" />
+ <area id="messages" coords="26" />
+ <area id="validation" coords="39" />
+ <area id="reset" coords="68" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[@ApplicationScoped
+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;
+
+ ...
+
+ public boolean isValidNumberRange()
+ {
+ return validNumberRange;
+ }
+
+ public boolean isGameWon()
+ {
+ return guess == number;
+ }
+
+ public boolean isGameLost()
+ {
+ return guess != number && remainingGuesses <= 0;
+ }
+
+ public boolean check()
+ {
+ boolean result = false;
+
+ if ( checkNewNumberRangeIsValid() )
+ {
+ if ( guess > number )
+ {
+ biggest = guess - 1;
+ }
+
+ if ( guess < number )
+ {
+ smallest = guess + 1;
+ }
+
+ if ( guess == number )
+ {
+ result = true;
+ }
+
+ remainingGuesses--;
+ }
+
+ return result;
+ }
+
+ private boolean checkNewNumberRangeIsValid()
+ {
+ return validNumberRange = ( ( guess >= smallest ) && ( guess <= biggest ) );
+ }
+
+ @PostConstruct
+ public void reset()
+ {
+ this.smallest = 0;
+ ...
+ this.number = rndGenerator.next();
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="scope">
+ <para>
+ The bean is application scoped instead of session scoped, since an instance of the
+ application represents a single 'session'.
+ </para>
+ </callout>
+ <callout arearefs="name">
+ <para>
+ The bean is not named, since it doesn't need to be accessed via EL
+ </para>
+ </callout>
+ <callout arearefs="messages">
+ <para>There is no JSF <literal>FacesContext</literal> to add messages to. Instead the <literal>Game</literal> class provides
+ additional information about the state of the current game including:
+ </para>
+
+
+ <itemizedlist>
+ <listitem>
+ <para>If the game has been won or lost</para>
+ </listitem>
+ <listitem>
+ <para>If the most recent guess was invalid</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>This allows the Swing UI to query the state of the game, which it does
+ indirectly via a class called <literal>MessageGenerator,</literal> in order to determine the appropriate
+ messages to display to the user during the game.
+ </para>
+ </callout>
+ <callout arearefs="validation">
+ <para>
+ Validation of user input is performed during the <literal>check()</literal> method, since there is
+ no dedicated validation phase
+ </para>
+ </callout>
+ <callout arearefs="reset">
+ <para>
+ The <literal>reset()</literal> method makes a call to the injected <literal>rndGenerator</literal> in order to get the
+ random number at the start of each game. It cannot use
+ <literal>manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random>(){})</literal>
+ as the JSF example does because there will not be any active contexts like
+ there is during a JSF request.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>The <literal>MessageGenerator</literal> class depends on the current instance of <literal>Game</literal>, and queries
+ its state in order to determine the appropriate messages to provide as the
+ prompt for the user's next guess and the response to the previous guess.
+ The code for <literal>MessageGenerator</literal> is as follows:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="game" coords="3" />
+ <area id="challenge" coords="5" />
+ <area id="result" coords="16" />
+ </areaspec>
+ <programlisting role="JAVA"><![CDATA[public class MessageGenerator
+{
+ @Current Game game;
+
+ public String getChallengeMessage()
+ {
+ StringBuilder challengeMsg = new StringBuilder( "I'm thinking of a number between " );
+ challengeMsg.append( game.getSmallest() );
+ challengeMsg.append( " and " );
+ challengeMsg.append( game.getBiggest() );
+ challengeMsg.append( ". Can you guess what it is?" );
+
+ return challengeMsg.toString();
+ }
+
+ public String getResultMessage()
+ {
+ if ( game.isGameWon() )
+ {
+ return "You guess it! The number was " + game.getNumber();
+ } else if ( game.isGameLost() )
+ {
+ return "You are fail! The number was " + game.getNumber();
+ } else if ( ! game.isValidNumberRange() )
+ {
+ return "Invalid number range!";
+ } else if ( game.getRemainingGuesses() == Game.MAX_NUM_GUESSES )
+ {
+ return "What is your first guess?";
+ } else
+ {
+ String direction = null;
+
+ if ( game.getGuess() < game.getNumber() )
+ {
+ direction = "Higher";
+ } else
+ {
+ direction = "Lower";
+ }
+
+ return direction + "! You have " + game.getRemainingGuesses() + " guesses left.";
+ }
+ }
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="game">
+ <para>
+ The instance of <literal>Game</literal> for the application is injected here.
+ </para>
+ </callout>
+ <callout arearefs="challenge">
+ <para>
+ The <literal>Game</literal>'s state is interrogated to determine the appropriate
+ challenge message.
+ </para>
+ </callout>
+ <callout arearefs="result">
+ <para>
+ And again to determine whether to congratulate, console or
+ encourage the user to continue.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>Finally we come to the <literal>NumberGuessFrame</literal> class which provides the Swing
+ front end to our guessing game. </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="gameIn" coords="3" />
+ <area id="messagesIn" coords="4" />
+ <area id="start" coords="6" />
+ <area id="init" coords="18" />
+ <area id="guess" coords="34" />
+ <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;
+
+ public void start( @Observes @Deployed Manager manager )
+ {
+ java.awt.EventQueue.invokeLater( new Runnable()
+ {
+ public void run()
+ {
+ initComponents();
+ setVisible( true );
+ }
+ } );
+ }
+
+ private void initComponents() {
+
+ buttonPanel = new javax.swing.JPanel();
+ mainMsgPanel = new javax.swing.JPanel();
+ mainLabel = new javax.swing.JLabel();
+ messageLabel = new javax.swing.JLabel();
+ guessText = new javax.swing.JTextField();
+ ...
+ mainLabel.setText(msgGenerator.getChallengeMessage());
+ mainMsgPanel.add(mainLabel);
+
+ messageLabel.setText(msgGenerator.getResultMessage());
+ mainMsgPanel.add(messageLabel);
+ ...
+ }
+
+ private void guessButtonActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ int guess = Integer.parseInt(guessText.getText());
+
+ game.setGuess( guess );
+ game.check();
+ refreshUI();
+
+ }
+
+ private void replayBtnActionPerformed( java.awt.event.ActionEvent evt )
+ {
+ game.reset();
+ refreshUI();
+ }
+
+ private void refreshUI()
+ {
+ mainLabel.setText( msgGenerator.getChallengeMessage() );
+ messageLabel.setText( msgGenerator.getResultMessage() );
+ guessText.setText( "" );
+ guessesLeftBar.setValue( game.getRemainingGuesses() );
+ guessText.requestFocus();
+ }
+
+ // swing components
+ private javax.swing.JPanel borderPanel;
+ ...
+ private javax.swing.JButton replayBtn;
+
+}]]></programlisting>
+ <calloutlist>
+ <callout arearefs="gameIn">
+ <para>
+ The injected instance of the game (logic and state).
+ </para>
+ </callout>
+ <callout arearefs="messagesIn">
+ <para>
+ The injected message generator for UI messages.
+ </para>
+ </callout>
+ <callout arearefs="start">
+ <para>
+ This application is started in the usual Web Beans SE way, by observing the
+ <literal>@Deployed Manager</literal> event.
+ </para>
+ </callout>
+ <callout arearefs="init">
+ <para>
+ This method initialises all of the Swing components. Note the use
+ of the <literal>msgGenerator</literal>.
+ </para>
+ </callout>
+ <callout arearefs="guess">
+ <para>
+ <literal>guessButtonActionPerformed</literal> is called when the 'Guess' button is clicked, and
+ it does the following:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Gets the guess entered by the user and sets it as the current guess in the <literal>Game</literal></para>
+ </listitem>
+ <listitem>
+ <para>Calls <literal>game.check()</literal> to validate and perform one 'turn' of the game</para>
+ </listitem>
+ <listitem>
+ <para> Calls <literal>refreshUI</literal>. If there were validation errors with the input, this
+ will have been captured during <literal>game.check()</literal> and as such will be reflected
+ in the messeges returned by <literal>MessageGenerator</literal> and subsequently presented
+ to the user. If there are no validation errors then the user will be told
+ to guess again (higher or lower) or that the game has ended either in a
+ win (correct guess) or a loss (ran out of guesses).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </callout>
+ <callout arearefs="replay">
+ <para>
+ <literal>replayBtnActionPerformed</literal> simply calls <literal>game.reset()</literal> to start a new game
+ and refreshes the messages in the UI.
+ </para>
+ </callout>
+ <callout arearefs="refresh">
+ <para>
+ <literal>refreshUI</literal> uses the <literal>MessageGenerator</literal> to update the messages to the user based
+ on the current state of the Game.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ To run this example simply
+ <itemizedlist>
+ <listitem>
+ <para>Open a command line/terminal window in the
+ <literal>examples/se/numberguess</literal> directory</para>
+ </listitem>
+ <listitem>
+ <para>Ensure that Maven 2 is installed and in your PATH</para>
+ </listitem>
+ <listitem>
+ <para>Ensure that the <literal>JAVA_HOME</literal> environment variable is pointing to your JDK installation</para>
+ </listitem>
+ <listitem>
+ <para>execute the following command</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <programlisting>mvn -Drun</programlisting>
+
+ </section>
+
</section>
</chapter>
\ No newline at end of file
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2512 - in examples/trunk/se/hello-world: src/main/java/org/jboss/webbeans/environment/se/example/simple and 1 other directories.
by webbeans-commits@lists.jboss.org
Author: peteroyle
Date: 2009-04-19 05:50:29 -0400 (Sun, 19 Apr 2009)
New Revision: 2512
Removed:
examples/trunk/se/hello-world/src/test/java/com/
Modified:
examples/trunk/se/hello-world/pom.xml
examples/trunk/se/hello-world/src/main/java/org/jboss/webbeans/environment/se/example/simple/CommandLineArgsValidator.java
Log:
Fixed bug where CommandLineArgsValidator would try to clear the non modifiable list of all parameters is any params were invalid.
Removed legacy packages and empty unit test.
Removed JUnit dependency and added 'run' goal to the POM, though not yet sure how to pass command line parameters.
Modified: examples/trunk/se/hello-world/pom.xml
===================================================================
--- examples/trunk/se/hello-world/pom.xml 2009-04-18 21:50:57 UTC (rev 2511)
+++ examples/trunk/se/hello-world/pom.xml 2009-04-19 09:50:29 UTC (rev 2512)
@@ -1,107 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
- <artifactId>parent</artifactId>
+ <artifactId>webbeans-parent</artifactId>
<groupId>org.jboss.webbeans</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
- <groupId>org.jboss.webbeans</groupId>
+ <groupId>org.jboss.webbeans.examples</groupId>
<artifactId>hello-world-se</artifactId>
<packaging>jar</packaging>
<name>Hello World SE</name>
- <url>http://maven.apache.org</url>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <version>2.0.2</version>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>jalopy-maven-plugin</artifactId>
- <version>1.0-alpha-1</version>
- <!-- This wipes out UNDO in IDEs. Run manually instead.
- <executions>
- <execution>
- <phase>compile</phase>
- <goals>
- <goal>format</goal>
- </goals>
- </execution>
- </executions>
- -->
- </plugin>
- <plugin>
- <groupId>com.google.code.maven-license-plugin</groupId>
- <artifactId>maven-license-plugin</artifactId>
- <version>1.4.0</version>
- <configuration>
- <basedir>${basedir}</basedir>
- <header>${basedir}/src/etc/header.txt</header>
- <quiet>false</quiet>
- <failIfMissing>true</failIfMissing>
- <aggregate>false</aggregate>
- <encoding>UTF-8</encoding>
- </configuration>
- <executions>
- <execution>
- <phase>compile</phase>
- <goals>
- <goal>format</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
-
- <repositories>
- <repository>
- <id>repository.jboss.org</id>
- <name>JBoss Repository</name>
- <url>http://repository.jboss.org/maven2</url>
- <releases>
- </releases>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </repository>
- <repository>
- <id>snapshots.jboss.org</id>
- <name>JBoss Snapshots Repository</name>
- <url>http://snapshots.jboss.org/maven2</url>
- <releases>
- <enabled>false</enabled>
- </releases>
- <snapshots>
- <updatePolicy>always</updatePolicy>
- </snapshots>
- </repository>
- <repository>
- <id>repository.codehaus.org</id>
- <name>Codehaus Repository</name>
- <url>http://repository.codehaus.org</url>
- </repository>
- </repositories>
+ <profiles>
+ <profile>
+ <id>run</id>
+ <activation>
+ <property>
+ <name>run</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <executions>
+ <execution>
+ <id>run</id>
+ <phase>package</phase>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <configuration>
+ <mainClass>org.jboss.webbeans.environment.se.StartMain</mainClass>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>com.google.code.maven-license-plugin</groupId>
+ <artifactId>maven-license-plugin</artifactId>
+ <version>1.4.0</version>
+ <configuration>
+ <basedir>${basedir}</basedir>
+ <header>${basedir}/src/etc/header.txt</header>
+ <quiet>false</quiet>
+ <failIfMissing>true</failIfMissing>
+ <aggregate>false</aggregate>
+ <encoding>UTF-8</encoding>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>format</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifest>
+ <mainClass>org.jboss.webbeans.environment.se.StartMain</mainClass>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
<dependencies>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.jboss.webbeans</groupId>
<artifactId>se-module</artifactId>
- <version>1.0.0-SNAPSHOT</version>
- <scope>compile</scope>
</dependency>
</dependencies>
+
</project>
Modified: examples/trunk/se/hello-world/src/main/java/org/jboss/webbeans/environment/se/example/simple/CommandLineArgsValidator.java
===================================================================
--- examples/trunk/se/hello-world/src/main/java/org/jboss/webbeans/environment/se/example/simple/CommandLineArgsValidator.java 2009-04-18 21:50:57 UTC (rev 2511)
+++ examples/trunk/se/hello-world/src/main/java/org/jboss/webbeans/environment/se/example/simple/CommandLineArgsValidator.java 2009-04-19 09:50:29 UTC (rev 2512)
@@ -17,9 +17,9 @@
package org.jboss.webbeans.environment.se.example.simple;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import javax.context.ApplicationScoped;
-import javax.inject.Current;
import javax.inject.Initializer;
import org.jboss.webbeans.environment.se.bindings.Parameters;
@@ -40,7 +40,7 @@
if (validParams.size() != 1)
{
errors.add( "Please supply just one parameter: your first name" );
- validParams.clear();
+ validParams = Collections.EMPTY_LIST;
}
}
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2511 - in ri/trunk: impl/src/main/java/org/jboss/webbeans/bootstrap and 5 other directories.
by webbeans-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2009-04-18 17:50:57 -0400 (Sat, 18 Apr 2009)
New Revision: 2511
Added:
ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Lifecycle.java
Modified:
ri/trunk/impl/src/main/java/org/jboss/webbeans/CurrentManager.java
ri/trunk/impl/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java
ri/trunk/impl/src/main/java/org/jboss/webbeans/context/ContextLifecycle.java
ri/trunk/impl/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java
ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/ServletLifecycle.java
ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/WebBeansListener.java
ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environment.java
ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environments.java
ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/ServiceRegistry.java
ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/SingletonProvider.java
ri/trunk/tests/src/main/java/org/jboss/webbeans/mock/MockServletLifecycle.java
Log:
Make context lifecycle a service of the manager
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/CurrentManager.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/CurrentManager.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/CurrentManager.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -42,12 +42,12 @@
public class CurrentManager
{
- private static class IntegerMaangerImplMap extends TypeLiteral<Map<Integer, ManagerImpl>> {}
+ private static class IntegerMangerImplMap extends TypeLiteral<Map<Integer, ManagerImpl>> {}
// The root manager instance
private static Singleton<ManagerImpl> rootManager = SingletonProvider.instance().create(ManagerImpl.class);
- private final static Singleton<Map<Integer, ManagerImpl>> managers = SingletonProvider.instance().create(new IntegerMaangerImplMap().getRawType());
+ private final static Singleton<Map<Integer, ManagerImpl>> managers = SingletonProvider.instance().create(new IntegerMangerImplMap().getRawType());
public static void cleanup()
{
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -35,6 +35,7 @@
import org.jboss.webbeans.bootstrap.api.helpers.ServiceRegistries;
import org.jboss.webbeans.bootstrap.spi.WebBeanDiscovery;
import org.jboss.webbeans.context.ApplicationContext;
+import org.jboss.webbeans.context.ContextLifecycle;
import org.jboss.webbeans.context.ConversationContext;
import org.jboss.webbeans.context.DependentContext;
import org.jboss.webbeans.context.RequestContext;
@@ -231,6 +232,7 @@
protected void createContexts()
{
+ getServices().add(ContextLifecycle.class, new ContextLifecycle());
getServices().add(DependentContext.class, new DependentContext());
getServices().add(RequestContext.class, new RequestContext());
getServices().add(ConversationContext.class, new ConversationContext());
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/context/ContextLifecycle.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/context/ContextLifecycle.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/context/ContextLifecycle.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -24,8 +24,7 @@
package org.jboss.webbeans.context;
import org.jboss.webbeans.CurrentManager;
-import org.jboss.webbeans.bootstrap.api.Singleton;
-import org.jboss.webbeans.bootstrap.api.SingletonProvider;
+import org.jboss.webbeans.bootstrap.api.Lifecycle;
import org.jboss.webbeans.context.api.BeanStore;
import org.jboss.webbeans.conversation.ConversationManager;
import org.jboss.webbeans.log.LogProvider;
@@ -39,31 +38,19 @@
* @author Pete Muir
*
*/
-public class ContextLifecycle
+public class ContextLifecycle implements Lifecycle
{
- private static Singleton<ContextLifecycle> instance = SingletonProvider.instance().create(ContextLifecycle.class);
-
- public static ContextLifecycle instance()
- {
- return instance.get();
- }
-
- protected static void setInstance(ContextLifecycle instance)
- {
- ContextLifecycle.instance.set(instance);
- }
-
private static LogProvider log = Logging.getLogProvider(ContextLifecycle.class);
- protected void restoreSession(String id, BeanStore sessionBeanStore)
+ public void restoreSession(String id, BeanStore sessionBeanStore)
{
log.trace("Restoring session " + id);
SessionContext.instance().setBeanStore(sessionBeanStore);
SessionContext.instance().setActive(true);
}
- protected void endSession(String id, BeanStore sessionBeanStore)
+ public void endSession(String id, BeanStore sessionBeanStore)
{
log.trace("Ending session " + id);
SessionContext.instance().setActive(true);
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -17,6 +17,7 @@
package org.jboss.webbeans.event;
+import org.jboss.webbeans.CurrentManager;
import org.jboss.webbeans.context.ContextLifecycle;
import org.jboss.webbeans.context.api.BeanStore;
import org.jboss.webbeans.context.api.helpers.ConcurrentHashMapBeanStore;
@@ -51,8 +52,9 @@
public void run()
{
+ ContextLifecycle lifecycle = getLifecycle();
BeanStore requestBeanStore = new ConcurrentHashMapBeanStore();
- ContextLifecycle.instance().beginRequest("async invocation", requestBeanStore);
+ lifecycle.beginRequest("async invocation", requestBeanStore);
try
{
log.debug("Sending event [" + event + "] directly to observer " + observer);
@@ -64,7 +66,7 @@
}
finally
{
- ContextLifecycle.instance().endRequest("async invocation", requestBeanStore);
+ lifecycle.endRequest("async invocation", requestBeanStore);
}
}
@@ -73,4 +75,9 @@
{
return "Deferred event [" + event + "] for [" + observer + "]";
}
+
+ private ContextLifecycle getLifecycle()
+ {
+ return CurrentManager.rootManager().getServices().get(ContextLifecycle.class);
+ }
}
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/ServletLifecycle.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/ServletLifecycle.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/ServletLifecycle.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -42,26 +42,23 @@
* @author Pete Muir
* @author Nicklas Karlsson
*/
-public class ServletLifecycle extends ContextLifecycle
+public class ServletLifecycle
{
+ private final ContextLifecycle lifecycle;
+
public static final String REQUEST_ATTRIBUTE_NAME = ServletLifecycle.class.getName() + ".requestBeanStore";
- // This is a temporray solution. We should remove the static field from
- // ContextLifecycle and just tie the lifecycle of ContextLifecycle
- // with that of manager.
- public ServletLifecycle()
+ private static LogProvider log = Logging.getLogProvider(ServletLifecycle.class);
+
+ /**
+ *
+ */
+ public ServletLifecycle(ContextLifecycle lifecycle)
{
- ContextLifecycle.setInstance(this);
+ this.lifecycle = lifecycle;
}
- public static ServletLifecycle instance()
- {
- return (ServletLifecycle) ContextLifecycle.instance();
- }
-
- private static LogProvider log = Logging.getLogProvider(ServletLifecycle.class);
-
/**
* Begins a session
*
@@ -79,9 +76,9 @@
public void endSession(HttpSession session)
{
BeanStore mockRequest = new ConcurrentHashMapBeanStore();
- super.beginRequest("endSession-" + session.getId(), mockRequest);
- super.endSession(session.getId(), restoreSessionContext(session));
- super.endRequest("endSession-" + session.getId(), mockRequest);
+ lifecycle.beginRequest("endSession-" + session.getId(), mockRequest);
+ lifecycle.endSession(session.getId(), restoreSessionContext(session));
+ lifecycle.endRequest("endSession-" + session.getId(), mockRequest);
}
/**
@@ -95,7 +92,7 @@
{
BeanStore sessionBeanStore = new HttpRequestSessionBeanStore(request);
HttpSession session = request.getSession(false);
- super.restoreSession(session == null ? "Inactive session" : session.getId(), sessionBeanStore);
+ lifecycle.restoreSession(session == null ? "Inactive session" : session.getId(), sessionBeanStore);
if (session != null)
{
CurrentManager.rootManager().getInstanceByType(HttpSessionManager.class).setSession(session);
@@ -106,7 +103,7 @@
protected BeanStore restoreSessionContext(HttpSession session)
{
BeanStore beanStore = new HttpSessionBeanStore(session);
- super.restoreSession(session.getId(), beanStore);
+ lifecycle.restoreSession(session.getId(), beanStore);
CurrentManager.rootManager().getInstanceByType(HttpSessionManager.class).setSession(session);
return beanStore;
}
@@ -124,7 +121,7 @@
{
BeanStore beanStore = new ConcurrentHashMapBeanStore();
request.setAttribute(REQUEST_ATTRIBUTE_NAME, beanStore);
- super.beginRequest(request.getRequestURI(), beanStore);
+ lifecycle.beginRequest(request.getRequestURI(), beanStore);
restoreSessionContext(request);
}
}
@@ -143,7 +140,7 @@
{
throw new IllegalStateException("Cannot obtain request scoped beans from the request");
}
- super.endRequest(request.getRequestURI(), beanStore);
+ lifecycle.endRequest(request.getRequestURI(), beanStore);
request.removeAttribute(REQUEST_ATTRIBUTE_NAME);
SessionContext.instance().setBeanStore(null);
}
Modified: ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/WebBeansListener.java
===================================================================
--- ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/WebBeansListener.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/impl/src/main/java/org/jboss/webbeans/servlet/WebBeansListener.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -27,6 +27,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionEvent;
+import org.jboss.webbeans.CurrentManager;
+import org.jboss.webbeans.context.ContextLifecycle;
import org.jboss.webbeans.servlet.api.helpers.AbstractServletListener;
/**
@@ -42,11 +44,15 @@
public class WebBeansListener extends AbstractServletListener
{
- private final ServletLifecycle lifecycle;
-
- public WebBeansListener()
+ private ServletLifecycle lifecycle;
+
+ private ServletLifecycle getLifecycle()
{
- lifecycle = new ServletLifecycle();
+ if (lifecycle == null)
+ {
+ this.lifecycle = new ServletLifecycle(CurrentManager.rootManager().getServices().get(ContextLifecycle.class));
+ }
+ return lifecycle;
}
/**
@@ -57,7 +63,7 @@
@Override
public void sessionCreated(HttpSessionEvent event)
{
- lifecycle.beginSession(event.getSession());
+ getLifecycle().beginSession(event.getSession());
}
/**
@@ -68,7 +74,7 @@
@Override
public void sessionDestroyed(HttpSessionEvent event)
{
- lifecycle.endSession(event.getSession());
+ getLifecycle().endSession(event.getSession());
}
/**
@@ -81,7 +87,7 @@
{
if (event.getServletRequest() instanceof HttpServletRequest)
{
- lifecycle.endRequest((HttpServletRequest) event.getServletRequest());
+ getLifecycle().endRequest((HttpServletRequest) event.getServletRequest());
}
else
{
@@ -99,7 +105,7 @@
{
if (event.getServletRequest() instanceof HttpServletRequest)
{
- lifecycle.beginRequest((HttpServletRequest) event.getServletRequest());
+ getLifecycle().beginRequest((HttpServletRequest) event.getServletRequest());
}
else
{
Modified: ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environment.java
===================================================================
--- ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environment.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environment.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -26,12 +26,12 @@
*/
public interface Environment
{
-
+
/**
* The services to require for this environment
*
* @return the services to require
*/
public Set<Class<? extends Service>> getRequiredServices();
-
+
}
Modified: ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environments.java
===================================================================
--- ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environments.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Environments.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -59,7 +59,7 @@
*/
SE(WebBeanDiscovery.class, ResourceLoader.class);
- private Set<Class<? extends Service>> requiredServices;
+ private final Set<Class<? extends Service>> requiredServices;
private Environments(Class<? extends Service>... requiredServices)
{
Added: ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Lifecycle.java
===================================================================
--- ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Lifecycle.java (rev 0)
+++ ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Lifecycle.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -0,0 +1,12 @@
+package org.jboss.webbeans.bootstrap.api;
+
+/**
+ * Note Lifecycle is not complete, and the API may change
+ *
+ * @author pmuir
+ *
+ */
+public interface Lifecycle extends Service
+{
+
+}
Property changes on: ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/Lifecycle.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/ServiceRegistry.java
===================================================================
--- ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/ServiceRegistry.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/ServiceRegistry.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -18,7 +18,7 @@
* @param serviceType the service type to add
* @param service the service implementation
*/
- public <S extends Service> void add(java.lang.Class<S> type, S service);
+ public <S extends Service> void add(Class<S> type, S service);
/**
* Retrieve a service implementation
Modified: ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/SingletonProvider.java
===================================================================
--- ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/SingletonProvider.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/spi/src/main/java/org/jboss/webbeans/bootstrap/api/SingletonProvider.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -110,7 +110,7 @@
}
else
{
- throw new RuntimeException("ScopeFactory is already initialized with " + INSTANCE);
+ throw new RuntimeException("SingletonProvider is already initialized with " + INSTANCE);
}
}
}
Modified: ri/trunk/tests/src/main/java/org/jboss/webbeans/mock/MockServletLifecycle.java
===================================================================
--- ri/trunk/tests/src/main/java/org/jboss/webbeans/mock/MockServletLifecycle.java 2009-04-18 15:55:48 UTC (rev 2510)
+++ ri/trunk/tests/src/main/java/org/jboss/webbeans/mock/MockServletLifecycle.java 2009-04-18 21:50:57 UTC (rev 2511)
@@ -30,7 +30,6 @@
bootstrap.getServices().add(ResourceLoader.class, MOCK_RESOURCE_LOADER);
bootstrap.getServices().add(WebBeanDiscovery.class, webBeanDiscovery);
bootstrap.setApplicationContext(applicationBeanStore);
- setInstance(this);
}
public void initialize()
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2510 - in doc/trunk/reference/en-US: images and 1 other directory.
by webbeans-commits@lists.jboss.org
Author: cpopetz
Date: 2009-04-18 11:55:48 -0400 (Sat, 18 Apr 2009)
New Revision: 2510
Added:
doc/trunk/reference/en-US/images/wicket-conversations-snap.png
doc/trunk/reference/en-US/images/wicket-numberguess-project.png
Modified:
doc/trunk/reference/en-US/ri.xml
doc/trunk/reference/en-US/scopescontexts.xml
Log:
Document wicket integration and wicket examples (WBX-26)
Added: doc/trunk/reference/en-US/images/wicket-conversations-snap.png
===================================================================
(Binary files differ)
Property changes on: doc/trunk/reference/en-US/images/wicket-conversations-snap.png
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: doc/trunk/reference/en-US/images/wicket-numberguess-project.png
===================================================================
(Binary files differ)
Property changes on: doc/trunk/reference/en-US/images/wicket-numberguess-project.png
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Modified: doc/trunk/reference/en-US/ri.xml
===================================================================
--- doc/trunk/reference/en-US/ri.xml 2009-04-18 07:33:09 UTC (rev 2509)
+++ doc/trunk/reference/en-US/ri.xml 2009-04-18 15:55:48 UTC (rev 2510)
@@ -650,8 +650,8 @@
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 on Tomcat
- <literal>webbeans-tomcat.jar</literal>.
+ single jar suitable for running Web Beans in any servlet container
+ <literal>webbeans-servlet.jar</literal>.
</para>
<tip>
@@ -663,19 +663,150 @@
</tip>
<para>
- Secondly, we need to explicitly specify the Tomcat servlet listener
+ 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>:
</para>
<programlisting><![CDATA[<listener>
- <listener-class>org.jboss.webbeans.environment.tomcat.Listener</listener-class>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
</listener>]]></programlisting>
</section>
+
+ <section id="numberguessWicket">
+ <title>The numberguess example in Apache Wicket</title>
+ <para>Although the JSR299 specification includes detailed information on how WebBeans integrates
+ with Java Server Faces, it is possible to use WebBeans injection, as well as the WebBeans conversational
+ context, with other web frameworks. In this section, we'll look at the module which allows integration of
+ WebBeans with the Apache Wicket framework. This documentation assumes that you have some familiarity
+ with Wicket; if not, please visit <ulink url="http://wicket.apache.org/">http://wicket.apache.org/</ulink>
+ to learn more. In this section we'll look at the previous "numberguess" example as implemented with Wicket.
+ We'll look at the conversational aspects of the Wicket/WebBeans integration in <xref linkend="wicketContexts"/></para>
+
+ <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. Since we
+ are deploying to a servlet container, we are also building as a WAR. In addition, these examples make use of the Eclipse IDE,
+ although instructions are also given to deploy the application from the command line.</para>
+
+ <section>
+ <title>Creating the eclipse project</title>
+ <para>To generate an eclipse project from the example, use apache maven and the eclipse:eclipse
+ plugin:
+ <programlisting><![CDATA[cd examples/wicket/numberguess
+mvn eclipse:eclipse -DdownloadSources]]></programlisting>
+ Then, from eclipse, choose <literal>File -> Import -> General -> Existing Projects into Workspace</literal>, choose
+ the root directory of the numberguess example, and click finish. This should result in a project in
+ your workspace named <literal>webbeans-wicket-numberguess</literal>:
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/wicket-numberguess-project.png" format="png"/>
+ </imageobject>
+ </mediaobject>
+ </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 <literal>jetty</literal> through a <literal>Start</literal>
+ class. So running the example is as simple as right-clicking on that Start class in src/test/java in the package
+ explorer and choosing "Run as Java Application." You should then see console output related to jetty starting up,
+ and then be able to hit <literal>http://localhost:8080</literal> to view the app. To stop the app, switch to the Console
+ View and click the red stop square. One can also debug in the same fashion, by choosing "Debug as Java Application" when right-clicking.
+ </para>
+ </section>
+ <section>
+ <title>Running the example from the command line in Jboss or Tomcat</title>
+ <para>This example can also be deployed from the command line in a fashion 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 or Tomcat, as previously
+ described, you can simply 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>.
+ </para>
+ </section>
+
+ <section>
+ <title>Understanding the code</title>
+ <para>While JSF uses unified EL expressions to bind view layer components in jsp or xhtml to
+ WebBeans, Wicket keeps a stricter separation of concerns in place. The markup is plain html with
+ a one-to-one mapping between html elements and the view components, which are constructed in java code. All
+ view logic, including binding of components to models and controlling the response of view actions,
+ is handled in java code. Therefore, the integration of WebBeans with Wicket takes place through annotated
+ injections of WebBeans into your WebPage subclass (or into other custom wicket component subclasses.)</para>
+
+ <para>The code in the wicket numberguess example is very similar to the JSF-based numberguess example described previously. The business logic
+ components (Game, Generator, MaxNumber, etc.) are the same. Differences include the following:</para>
+ <itemizedlist>
+ <listitem><para>Each wicket application must have a <literal>WebApplication</literal> subclass,
+ and in the case of the Wicket/WebBeans integration, this class should subclass <literal>
+ org.jboss.webbeans.wicket.WebBeansApplication</literal>. (If you would prefer not to subclass
+ WebBeansApplication, you can manually add the small number of overrides and listeners to your own WebApplication
+ subclass. See the javadocs on WebBeansApplication for details.) In our case, our application class is called<literal>
+ SampleApplication</literal>:
+ <programlisting><![CDATA[public class SampleApplication extends WebBeansApplication
+{
+ @Override
+ public Class getHomePage()
+ {
+ return HomePage.class;
+ }
+}]]></programlisting>This class specifies which page wicket should treat as our HomePage,
+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
+ bits that are interesting with respect to WebBeans are the injection of the <literal>Game</literal>
+ WebBean the top of the class</para>
+ <programlisting><![CDATA[ @Current Game game;]]></programlisting> which is then used later in,
+ for example, the code for submitting a guess:<programlisting><![CDATA[final Component guessButton = new AjaxButton("GuessButton") {
+ protected void onSubmit(AjaxRequestTarget target, Form form) {
+ if (game.check()) {]]></programlisting>This injection is a proxy which holds a transient reference to the actual
+ Game WebBean, and is therefore safe with respect to the serialization of the wicket page. Actual
+ storage of the bean is in the session, and is managed by WebBeans. Note that Wicket components, like the HomePage and its
+ subcomponents, are <emphasis>not</emphasis> WebBeans. Their construction is handled directly by wicket (for
+ the page itself) and by the example code (for the nested page elements), and not by the WebBeans
+ Manager. However, the <literal>
+ webbeans-wicket</literal> integration takes care of injecting dependencies into the page for us. This
+ injection occurs through an <literal>IComponentInstantiationListener</literal> which is
+ registered by the <literal>WebbeansWebApplication</literal>. This means that although wicket
+ components can have injections, they <emphasis>cannot</emphasis> use interceptors and the other features
+ of real WebBeans. The delegate beans used by the wicket code can of course be full WebBeans,
+ as the <literal>Game</literal> bean is in this example.</listitem>
+ <listitem><para>Note that this example also uses ajax for processing of button events, and
+ dynamically hides buttons that are no longer revelant, 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:
+ <programlisting><![CDATA[ <filter>
+ <filter-name>wicket.numberguess-example</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>
+ </init-param>
+</filter>
+
+<filter-mapping>
+ <filter-name>wicket.numberguess-example</filter-name>
+ <url-pattern>/*</url-pattern>
+</filter-mapping>
+
+<listener>
+ <listener-class>org.jboss.webbeans.environment.servlet.Listener</listener-class>
+</listener>]]></programlisting>Note that the servlet listener is also added, as in the tomcat example, in order to boostrap
+WebBeans when jetty starts, and to hook WebBeans into the jetty servlet request and session lifecycles.</para>
+</listitem>
+
+ </itemizedlist>
+
+
+ </section>
+
+ </section>
+ </section>
+
+ <section>
<title>The translator example</title>
<para>
Modified: doc/trunk/reference/en-US/scopescontexts.xml
===================================================================
--- doc/trunk/reference/en-US/scopescontexts.xml 2009-04-18 07:33:09 UTC (rev 2509)
+++ doc/trunk/reference/en-US/scopescontexts.xml 2009-04-18 15:55:48 UTC (rev 2510)
@@ -247,8 +247,147 @@
</section>
+ <section id="wicketContexts">
+ <title>Conversations using Wicket</title>
+ <para>The conversation scope can also be used in WebBeans with the Apache Wicket web framework, through the
+ <literal>webbeans-wicket</literal> module. This module takes care of:
+ <itemizedlist>
+ <listitem><para>Setting up the conversation context at the beginning of a wicket request, and tearing it down afterwards</para></listitem>
+ <listitem><para>Storing the id of any long-running conversation in Wicket's WebPage metadata when the page response is complete</para></listitem>
+ <listitem><para>Activating the correct long-running conversation based upon which page is being accessed</para></listitem>
+ <listitem><para>Propagating the conversation context for any long-running conversation to new pages</para></listitem>
+ </itemizedlist> </para>
+ <section>
+ <title>Starting and stopping conversations in Wicket</title>
+ <para>As in WebBeans JSF applications, a conversation <emphasis>always</emphasis> exists for any request, but its lifetime is only that of the current request unless it is marked as
+ <emphasis>long-running</emphasis>. For Wicket applications this is accomplished exactly as in JSF applications, by injecting the <literal>@Current Conversation</literal> and then
+ invoking <literal>conversation.begin()</literal>. Likewise, conversations are ended with <literal>conversation.end()</literal>
+ </para>
+ </section>
+
+ <section>
+ <title>Long running conversation propagation in Wicket</title>
+ <para>
+ When a conversation is marked as long-running, the id of that conversation will be stored in Wicket's WebPage metadata for the current page.
+ In addition, if a new page is created and set as the response target through <literal>setResponsePage</literal>, this new page will also participate
+ in this conversation. This occurs for both directly instantiated pages, i.e. <literal>setResponsePage(new OtherPage())</literal> as well as for
+ bookmarkable pages created with <literal>setResponsePage(OtherPage.class)</literal> where <literal>OtherPage.class</literal> is mounted as bookmarkable
+ from your <literal>WebApplication</literal> subclass (or through annotations.) In the latter case, because the new page instance is not created until after
+ a redirect, the conversation id will be propagated through a request parameter, and then stored in page metadata after the redirect.
+ </para>
+ </section>
+ <section>
+ <title>The Wicket Conversations Example</title>
+ <para>In <literal>examples/wicket/conversations</literal> there is an example application for using conversations from Wicket. To setup and run the
+ application, follow the examples in <xref linkend="numberguessWicket"/>. If running within eclipse, the application is available at <literal>http://localhost:8080</literal>,
+ and if running within an external container, the app is available at <literal>http://localhost:8080/webbeans-conversations-wicket</literal>.
+ </para>
+ <section>
+ <title>Using the application</title>
+ <para>The <emphasis>conversations</emphasis> application is simply an interface to begin and end conversations, switch between them, and store a single piece of data in each.
+ The interface looks like the following:
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/wicket-conversations-snap.png" format="PNG"/>
+ </imageobject>
+ </mediaobject></para>
+ <para>
+ The menu at the top will show the list of long-running conversations, along with data about each,
+ as well as the active conversation (even if it is not long running.) The currently selected item
+ of this menu is the current conversation for the last request that was processed. Changing this menu
+ changes the current conversation. The "Data in conversation" text box and the submit
+ button labeled "Change Value" allow you to change a piece of string data associated
+ with the conversation. The "begin" button marks the conversation as long running.
+ The "noop" button submits the form without changing the state of the conversation.
+ The "end" button ends the current conversation. The "longop" button
+ executes a method that takes a few seconds, which can be used to play with conversation timeouts and
+ synchronization/locking. The "Abandon" link redirects to the HomePage without propagating
+ the conversation, thus starting a new temporary conversation. The conversation that has been abandoned
+ can be rejoined by selecting it in the popup.</para>
+ </section>
+ <section>
+ <title>Understanding the code</title>
+ <para>As in <xref linkend="numberguessWicket"/>, there is boilerplate code in the
+ SampleApplication, as well as in web.xml, to ensure correct integration of Wicket and Webbeans.
+ Other pieces of this application include:</para>
+ <itemizedlist>
+ <listitem><para>The <literal>Conversations</literal> class exists to allow configuration of the conversation
+ timeout for the current session<programlisting><![CDATA[@Produces
+@ConversationInactivityTimeout
+@Example
+public static long getConversationTimeoutInMilliseconds()
+{
+ return 600000;
+}]]></programlisting>The <literal>Example</literal> deployment type is used to illustrate
+custom deployment types. It is defined in Example.java:<programlisting><![CDATA[@Target( { TYPE, METHOD, FIELD })
+@Retention(RUNTIME)
+@Documented
+@DeploymentType
+public @interface Example
+{
+}]]></programlisting> and is activated in <literal>WEB-INF/beans.xml</literal>:
+<programlisting><![CDATA[<Beans xmlns="urn:java:ee" xmlns:conversations="urn:java:org.jboss.webbeans.examples.conversations">
+ <Deploy>
+ <Standard />
+ <Production />
+ <conversations:Example />
+ </Deploy>
+</Beans>]]></programlisting></para></listitem>
+<listitem><para>The <literal>Data</literal> class is our conversational component that stores a
+single string:<programlisting><![CDATA[@ConversationScoped
+@Named
+public class Data implements Serializable
+{
+ private String data;
+
+ public String getData()
+ {
+ return data;
+ }
+
+ public void setData(String data)
+ {
+ this.data = data;
+ }
+}]]></programlisting></para></listitem>
+<listitem><para>The <literal>HomePage</literal> class is where
+the brunt of the work takes place. It injects the WebBeans-provided <literal>ConversationManager</literal>
+component in order to access the list of long-running conversations, injects the current <literal>Conversation</literal>
+in order to allow control over whether that conversation is long-running, and injects the <literal>Data</literal>
+component to allow its manipulation by the textfield:<programlisting><![CDATA[/**
+* These are injections for displaying information about existing conversations to the user
+*/
+@Current ConversationManager conversationManager;
+@Current Conversation currentConversation;
+
+/**
+* This is our conversational data component, to illustrate how data is used in conversations and
+* exists per-conversation.
+*/
+@Current Data data;
+]]></programlisting>The data component is referenced by the wicket TextField using a
+<literal>PropertyModel</literal>:<programlisting><![CDATA[form.add(new TextField("dataField", new PropertyModel(this, "data.data")));]]></programlisting>
+This means that for each page, the text field is referring to the "data" property of the "Data" bean that is specific to
+the conversation that is active for the request, whether that be a transient conversation that is created for the request
+or a long-running conversation associated with the page. If one types data into the text field
+and clicks <literal>Change Value</literal>
+when a long-running conversation is not started, and then clicks <literal>noop</literal>, the
+value in the text field disappears, because it was associated with a transient conversation, and
+upon redirect, the new conversation had a different Data object, which had the default (empty) value.</para>
+<para>As you can see by the other code in this example, conversations are started and ended programmatically,
+and no WebBeans-specific code is necessary to propagate the conversation. The only exception to this
+is in the code to <emphasis>switch</emphasis> conversations, which is not a typical operation in real scenarios.
+In this case, a conversation id (<literal>cid</literal>) request parameter is passed to the <literal>setResponsePage</literal>
+invocation, and this explicit conversation id will override the id that the wicket/webbeans integration
+code would normally generate in order to propagate the current conversation, and hence the specified
+conversation will be active upon redirect.</para>
+</listitem>
+</itemizedlist>
+
</section>
-
+</section>
+</section>
+</section>
<section>
<title>The dependent pseudo-scope</title>
16 years, 12 months
[webbeans-commits] Webbeans SVN: r2509 - extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket.
by webbeans-commits@lists.jboss.org
Author: pete.muir(a)jboss.org
Date: 2009-04-18 03:33:09 -0400 (Sat, 18 Apr 2009)
New Revision: 2509
Modified:
extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansRequestCycle.java
extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansWebRequestCycleProcessor.java
Log:
oops
Modified: extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansRequestCycle.java
===================================================================
--- extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansRequestCycle.java 2009-04-18 00:46:28 UTC (rev 2508)
+++ extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansRequestCycle.java 2009-04-18 07:33:09 UTC (rev 2509)
@@ -108,10 +108,10 @@
}
// Now set up the conversational context if it isn't already
- if (!ConversationContext.INSTANCE.isActive())
+ if (!ConversationContext.instance().isActive())
{
- ConversationContext.INSTANCE.setBeanStore(new ConversationBeanStore(((WebRequest) request).getHttpServletRequest().getSession(), conversation.getId()));
- ConversationContext.INSTANCE.setActive(true);
+ ConversationContext.instance().setBeanStore(new ConversationBeanStore(((WebRequest) request).getHttpServletRequest().getSession(), conversation.getId()));
+ ConversationContext.instance().setActive(true);
}
}
}
\ No newline at end of file
Modified: extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansWebRequestCycleProcessor.java
===================================================================
--- extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansWebRequestCycleProcessor.java 2009-04-18 00:46:28 UTC (rev 2508)
+++ extensions/trunk/wicket/src/main/java/org/jboss/webbeans/wicket/WebBeansWebRequestCycleProcessor.java 2009-04-18 07:33:09 UTC (rev 2509)
@@ -41,6 +41,6 @@
//cleanup and deactivate the conversation context
CurrentManager.rootManager().getInstanceByType(ConversationManager.class).cleanupConversation();
- ConversationContext.INSTANCE.setActive(false);
+ ConversationContext.instance().setActive(false);
}
}
\ No newline at end of file
16 years, 12 months