[webbeans-commits] Webbeans SVN: r2510 - in doc/trunk/reference/en-US: images and 1 other directory.
webbeans-commits at lists.jboss.org
webbeans-commits at lists.jboss.org
Sat Apr 18 11:55:49 EDT 2009
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
+ at ConversationInactivityTimeout
+ at 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 })
+ at Retention(RUNTIME)
+ at Documented
+ at 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
+ at 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
+*/
+ at Current ConversationManager conversationManager;
+ at Current Conversation currentConversation;
+
+/**
+* This is our conversational data component, to illustrate how data is used in conversations and
+* exists per-conversation.
+*/
+ at 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>
More information about the weld-commits
mailing list