[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