cziegeler    2004/02/12 01:26:46

  Modified:    src/documentation/xdocs/developing/webapps portal.xml
                        book.xml
               src/documentation/xdocs/developing/portal book.xml index.xml
  Added:       src/documentation/xdocs/developing/portal events.xml
                        forms.xml
  Log:
  Updating docs
  
  Revision  Changes    Path
  1.6       +2 -0      
cocoon-2.1/src/documentation/xdocs/developing/webapps/portal.xml
  
  Index: portal.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/documentation/xdocs/developing/webapps/portal.xml,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- portal.xml        15 Oct 2003 11:36:15 -0000      1.5
  +++ portal.xml        12 Feb 2004 09:26:46 -0000      1.6
  @@ -9,6 +9,8 @@
       </header>
       <body>
     <s1 title="Introduction">
  +     <note>This is the description of the "old" portal framework, please 
also have
  +      a look at the newer <link href="../portal/index.html">portal 
block</link>.</note>
        <p>The portal engine of Cocoon provides the required
           functionality to display user dependent content with a user 
defineable
           layout.</p>
  
  
  
  1.5       +2 -1      
cocoon-2.1/src/documentation/xdocs/developing/webapps/book.xml
  
  Index: book.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/documentation/xdocs/developing/webapps/book.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- book.xml  12 Oct 2003 13:16:32 -0000      1.4
  +++ book.xml  12 Feb 2004 09:26:46 -0000      1.5
  @@ -16,7 +16,8 @@
       <menu-item label="Authentication" href="authentication.html"/>
       <menu-item label="Simple Forms" href="forms.html"/>
       <menu-item label="Form Handling" 
href="../../userdocs/concepts/xmlform.html"/>
  -    <menu-item label="Portal" href="portal.html"/>
  +    <menu-item label="Portal FW" href="portal.html"/>
  +    <menu-item label="Portal Engine" href="../portal/index.html"/>
     </menu>
   
   </book>
  
  
  
  1.4       +4 -1      
cocoon-2.1/src/documentation/xdocs/developing/portal/book.xml
  
  Index: book.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/documentation/xdocs/developing/portal/book.xml,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- book.xml  12 Oct 2003 13:16:32 -0000      1.3
  +++ book.xml  12 Feb 2004 09:26:46 -0000      1.4
  @@ -13,9 +13,12 @@
     <menu label="Portal">
       <menu-item label="Introduction" href="index.html"/>
       <menu-item label="Portal Engine" href="portal-block.html"/>
  +    <menu-item label="Event Handling" href="events.html"/>
       <menu-item label="Authentication" href="../webapps/authentication.html"/>
     </menu>
  -
  +  <menu label="Samples">
  +    <menu-item label="Form handling" href="forms.html"/>
  +  </menu>
   </book>
   
   
  
  
  
  1.11      +3 -2      
cocoon-2.1/src/documentation/xdocs/developing/portal/index.xml
  
  Index: index.xml
  ===================================================================
  RCS file: 
/home/cvs/cocoon-2.1/src/documentation/xdocs/developing/portal/index.xml,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- index.xml 12 Nov 2003 10:39:06 -0000      1.10
  +++ index.xml 12 Feb 2004 09:26:46 -0000      1.11
  @@ -18,8 +18,9 @@
      be used to quickly develop portal applications.</p> 
   <p>The new <link href="portal-block.html">portal engine</link> is a new
     implementation of a portal engine which focuses on more flexibility
  -  and ease-of-use. The current state of this engine is <em>alpha</em>
  -  which means that the engine can still change in every aspect.</p>
  +  and ease-of-use. In addition it supports the JSR-168. The current state of 
  +  this engine is <em>alpha</em> which means that the engine can still change 
  +  in some aspects.</p>
   
    </s1>
     <s1 title="Features">
  
  
  
  1.1                  
cocoon-2.1/src/documentation/xdocs/developing/portal/events.xml
  
  Index: events.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" 
"../../dtd/document-v10.dtd">
  
  <document>
   <header>
    <title>Portal: Event Handling</title>
    <subtitle>Overview</subtitle>
    <authors>
     <person name="Carsten Ziegeler" email="[EMAIL PROTECTED]"/>
    </authors>
   </header>
  
   <body>
    <s1 title="Overview">
     <p>
       This document gives an overview of the event handling of the portal 
engine.
     </p>
     <p>
       The sample portal that comes with the Cocoon distribution contains 
several
       working samples for event handling.
     </p>
    </s1>
    <s1 title="Introduction">
      <p>
        The event handling is a central mechanism used in the portal engine. 
Every
        change (changes in status or layout, links etc) is propagated through an
        event. The portal uses the publisher/subscribe paradigm, so each 
component
        that is interested in a specific event can subscribe itself for this 
type
        of event. In addition each component can send out events.
      </p>
      <p>
        The processing of a portal request (a request send to the cocoon portal)
        is divided into two parts: event handling and rendering. In the first 
part
        all events are processed. For example if the user clicks a link this
        triggers an event that is published. Any receiver of this event might
        in turn fire new events that are published as well.
      </p>
      <p>
        When all events are processed, the first phase is finished and the 
second
        phase, the rendering, is started. At this point of time all event 
handling
        and all information exchange should be finished.
      </p>
    </s1>
    <s1 title="Events and the request/response cycle">
      <p>
        In the Portal, an event is represented by a Java object. This event 
object
        contains all necessary information to process the event. So, in most 
cases an
        event contains the object to modify, what to modify and the value to 
set.
        For example, the minimize event for minimizing a coplet, contains the
        coplet, the information to change the window state and the value 
"minimize" 
        to set.
      </p>
      <p>
        A component that processes this request is subscribed to this minimize 
event
        and when such an event is fired, it changes the window state of the
        layout object to minimize. Every data this component needs is stored in
        the event. This is a very important detail: the event is not directly 
processed
        (in this case) by the object that is changed (the coplet) but by a 
central
        subscribed component that changes the coplet.
      </p>
      <p>
        Let's have a look how such an event is created:
      </p>
      <source>
  Event event;
  event = new ChangeCopletInstanceAspectDataEvent(
              copletInstanceData,
              "size", 
              SizingStatus.STATUS_MINIMIZEDD);
      </source>
      <p>
        <em>Event</em> is just a marker interface, the concrete implementation
        <em>ChangeCopletInstanceAspectDataEvent</em> implements this interface
        and requires three pieces of information: the CopletInstanceData,
        the information about what to change (size) and the new value.
      </p>
      <p>
        If you want to fire this event, you have to publish it. Therefore you
        need the event manager a central portal component. You can lookup this
        component, fire the event and release the manager again. If you fire
        the event, the event is directly published to all subscribed components.
      </p>
      <source>
  EventManager manager = null;
  try {
      manager = serviceManager.lookup(EventManager.ROLE);
      manager.getPublisher().publish(event);
  } finally {
      serviceManager.release(manager);
  }
      </source>
      <p>
        As noted above, the event will be directly fired. But usually in a 
portal
        application, events are not fired directly but are invoked by some user
        action. This means, the user clicks on a link in the browser, the
        request is targetted at Cocoon and the portal invokes the correct 
events.
      </p>
      <p>
        For this, a link (or a form action) must know, which event it should
        fire, if it is clicked. So, in other words, a link is associated with
        a concrete event. But on the other site, an event is a Java object and 
we can only use
        strings in URLs. So how does this work?
      </p>
      <p>
        The part of the portal that generates the link, creates the event object
        with all necessary data, transforms this event into a usable URI and 
this
        URI is the target of the link. When the user clicks on this link, the 
portal
        transforms the URI into the Java event object and fires the event.
      </p>
      <p>
        The transformation Event->URI->Event is done by another portal 
component,
        the link service. Most portal components (apart from the event manager)
        are available through another central component, the portal service. So
        you need to have access to the portal service component. (Renderers e.g.
        don't have to lookup the service by itself, they get it as a method
        parameter).
      </p>
      <source>
  PortalService service = null;
  try {
      service = serviceManager.lookup(PortalService.ROLE);
      LinkService ls = service.getComponentManager().getLinkService();
  
      String uri = getLinkURI( event );
  
      // create a link that references the uri
  } finally {
      serviceManager.release(service);
  }
      </source>
      <p>
        That's all you have to do: create the event object, get the link 
service,
        transform the event into a URI using the service and then create the
        (html) link using the URI. Everything else is handled by the portal for 
you.
      </p>
    </s1>
    <s1 title="Changing the State of a Coplet">
      <p>
        In most cases you want to change the state of a coplet because the user
        performed an action. The portal engine provides you with some events
        that you can directly use.
      </p>
      <ul>
        <li>CopletJXPathEvent</li>
        <li>ChangeCopletInstanceAspectDataEvent</li>
      </ul>
      <p>
        The <em>CopletJXPathEvent</em> requires again three pieces of 
information:
        the coplet instance data to change, the JXPath expression that defines 
the
        data to change and the value:
      </p>
      <source>
  Event event = new CopletJXPathEvent(copletInstanceData, 
                                      "attributes/username", 
                                      username); 
      </source>
      <p>
        In the previous chapter, we already saw an example of the usage of the
        <em>ChangeCopletInstanceAspectDataEvent</em>.
      </p>
      <p>
        It is of course possible that you write your own events for 
        changing the state of a coplet. But in this case make sure that
        your own event implements the interface <em>CopletInstanceEvent</em>.
      </p>
    </s1>
    <s1 title="Subscribing to Events">
      <p>
        If you are interested in events, you can subscribe to a specific event
        type. As events are Java objects, you subscribe for all events of a
        specific interface or class (and all of the subclasses).
        Subscribing is done using the event manager:
      </p>
      <source>
  EventManager manager = null;
  try {
      manager = serviceManager.lookup(EventManager.ROLE);
      manager.getRegister().subscribe( myComponent );
  } finally {
      serviceManager.release(manager);
  }
      </source>
      <p>
        The component you subscribe must implement the Subscriber interface:
      </p>
      <source>
  Subscriber interface:
  
  public Class getEventType();
  
  public void inform( Event event );
      </source>
      <p>
        The getEventType() method returns the class/interfaces of the events
        the component is interested and each time such an event occurs,
        the inform() method is invoked.
      </p>
      <p>
        For example one central component in the portal subscribes for
        all events dealing with coplets, so it returns 
<em>CopletInstanceEvent</em>
        as the class in getEventType().
      </p>
    </s1>
    <s1 title="Inter Coplet Communication">
      <p>
        A very interesting feature of the portal is inter-coplet communication.
        The sample portal already has a simple sample where the name of an
        image selected in an image gallery is transfered to a different coplet.
      </p>
      <p>
        Now, there is only one (minor) problem: in the cocoon portal coplets 
        (or more precisly CopletInstanceData objects) are not components but
        just data objects. So, a coplet can't directly register itself as 
        a subcriber for events. 
      </p>
      <p>
        Remember that we mentioned earlier on a central component that 
processes 
        the change events for coplets? So, this is basically one possibility: if
        you want to pass information from one coplet to another one, create
        a CopletJXPathEvent and pass the information to the other coplet.
      </p>
      <p>
        Imagine a form coplet where the user can enter a city. When this form is
        processed by the form coplet, it can generate one (or more) 
CopletJXPathEvents
        and push the entered city information to a weather coplet and a hotel 
guide
        coplet. So, these two coplets display the information about the selected
        city.
      </p>
    </s1>
    <s1 title="Further Information">
      <p>
        The event.impl package contains all currently processed events, so you 
can
        study the events and see how to create them. In general most events are
        created inside the renderers, especially the renderer aspects that 
render
        specific details (e.g. the sizing buttons for a coplet). So, you can 
have
        a look at the code as well.
      </p>
      <p>
        There are several transformers that help in creating events inside a 
Cocoon
        pipeline. For example the <em>coplet transformer</em> can be used to
        create links that contain events to change the status of a coplet or a 
layout   
        object. The gallery sample uses this transformer as a demo.
      </p>
    </s1>
   </body>
  </document>
  
  
  
  1.1                  
cocoon-2.1/src/documentation/xdocs/developing/portal/forms.xml
  
  Index: forms.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" 
"../../dtd/document-v10.dtd">
  
  <document>
   <header>
    <title>Portal: Using forms</title>
    <subtitle>Overview</subtitle>
    <authors>
     <person name="Carsten Ziegeler" email="[EMAIL PROTECTED]"/>
    </authors>
   </header>
  
   <body>
    <s1 title="Overview">
     <p>This document gives an overview over how to use forms within the portal 
engine.
     </p>
     <p>
       The sample portal that comes with the Cocoon distribution contains a 
working sample
       for form handling. 
     </p>
    </s1>
    <s1 title="Including Applications">
      <p>
       The portal allows to include a complete web application (with forms, 
links etc.)
       that is build with Cocoon. Therefore it's possible to develop the forms
       like you usually do with Cocoon without thinking about the portal. When 
you
       are finished just include this application into the portal as a coplet.
       The following shows you how to configure such an application as a coplet.
      </p>
      <p>
        For including complete applications, the portal offers a specific 
coplet adapter,
        the caching URI adapter. This is configured as the coplet base type: 
<em>CachingURICoplet</em>.
        So each coplet you configure has to use this base type.
      </p>
      <p>
        For each application you have to configure a coplet data object in the 
profile:
      </p>
      <source>
  <![CDATA[...
     <coplet-data id="app-test-two" name="standard">
        <title>Application Test</title>
        <coplet-base-data>CachingURICoplet</coplet-base-data>
        <attribute>
                <name>buffer</name>
                <value xsi:type="java:java.lang.Boolean" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>true</value>
        </attribute>
        <attribute>
                <name>handleParameters</name>
                <value xsi:type="java:java.lang.Boolean" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>true</value>
        </attribute>
        <attribute>
                <name>uri</name>
                <value xsi:type="java:java.lang.String" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>cocoon:/coplets/html/application</value>
        </attribute>
        <attribute>
                <name>temporary:application-uri</name>
                <value xsi:type="java:java.lang.String" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>cocoon://samples/flow/jxcalc/</value>
        </attribute>
     </coplet-data>
  ...]]>
      </source>
      <p>
        As usual, the coplet data gets a unique id, a title and in this case 
the reference 
        to the <em>CachingURICoplet</em>. In addition the <em>buffer</em> 
attribute is used
        to buffer the output of the coplet which avoids broken responses in the 
case of a
        malformed stream comming from the included application.
      </p>
      <p>
        The <em>handleParameters</em> attribute has to be set to <em>true</em> 
as well, as 
        the application has to handle it's own request parameters (for links or 
forms).
      </p>
      <p>
        The <em>uri</em> attribute points to a Cocoon pipeline that will 
include your
        application. This is not the pipeline of your application itself. The 
starting
        URI for your application has to be configured using the attribute 
        <em>temporary:application-uri</em>.
      </p>
      <p>
        With this configuration you can configure instances of the coplet for 
each
        user. In addition a user can have several instances of the same 
application.
        If you look at the provided samples, you see two instances of a flow 
example
        and two instances of a forms sample at the same time for each user.
      </p>
      <p>
        However, if you allow several instances per user of the same 
application,
        this application has to be developed with this aspect in mind. More 
about
        this topic later on.
      </p>
      <p>
        So, basically this is all you have to do. Develop your application 
standalone
        without the example and include it as outlined above. You can for 
example
        invoke the sample above (cocoon://samples/flow/jxcalc/) directly 
without the
        portal.
      </p>
    </s1>
    <s1 title="Building forms">
      <p>
        In this chapter we demonstrate using a sample how to build forms that 
can
        be used with the portal. We will use Cocoon flow to define the logic for
        the form, but for your own form you can of course use a different 
approach
        as well. If you want to have complex forms, you can also use Cocoon 
forms
        (Woody), but you have to be careful with correctly using JavaScript on
        the client, which means you have to add the JavaScript to the response 
in
        the main portal pipeline and not by the form itself. Or you avoid using
        JavaScript on the client :)
      </p>
      <p>
        As outlined in the previous chapter, you can define your form handling 
application
        without taking care about the portal, so let's start developing it.
      </p>
      <s2 title="A Sample">
        <p>
          We will use flow for the logic. Each time the application is invoked, 
the same
          URI is used; this URI calls a flow function. Inside this function we 
check
          whether we have to display the form or a different (result) page.
          So our sitemap looks like this:
        </p>
      <source>
  <![CDATA[...
        <map:match pattern="form">
          <map:call function="form"/>
        </map:match>
  ...]]>
      </source>
        <p>
          We have one single function in the flow, that checks if a session
          attribute already contains a value or not. If no value is stored
          in the session, this means that either the form has to be displayed
          or the user just submitted some values. So we have to distinguish 
these
          two cases as well:
        </p>
        <source>
  <![CDATA[...
  function form() {
      // is the value stored in the session?
      if ( cocoon.session.getAttribute("form") == null ) {
          // No: is this a submit?
          var name = cocoon.request.getParameter("name");
          if ( name == null ) {
              // No: display the form
              cocoon.sendPage("page/form", {});
          } else {
              // It's a submit, so process the value
              cocoon.session.setAttribute("form", name);
              cocoon.sendPage("page/received", {"name" : name});         
          }
      } else {
          // just display the value
          var name = cocoon.session.getAttribute("form");
          cocoon.sendPage("page/content", {"name" : name});         
      }
  }...]]>
        </source>
        <p>
          This schema allows to use the same pipeline for all purposes. However,
          if you want a different design, you could e.g. use a different 
pipeline
          for processing the form data etc.
        </p>
        <p>
          In each case, the view is called which is a Cocoon pipeline. For
          example the pipeline for the form reads an XML document that looks 
like
          this:
        </p>
        <source>
  <![CDATA[...
  <page>
      <title>Form</title>
      <content>
        <form method="post" action="form">
          <para>Please enter your <strong>name</strong>: <input type="text" 
name="name"/></para>
          <input type="submit" name="submit" value="Enter"/>
        </form>
      </content>
  </page>
  }...]]>
        </source>
        <p>
          As already pointed out, you develop your application like you would 
do without
          the portal. Note in the sample above that the target of the form is 
the
          <em>form</em> pipeline, containing the call to the flow.
        </p>
        <p>
          So, how does this work? Each link (or target of a form action) is 
rewritten
          by the portal engine. The link is transformed into an event. When now 
the
          user activates such a link (or form) the event is send to the portal 
and
          the portal updates the URI to call for the portlet. The 
<em>portal-html-eventlink</em>
          transformer does the rewriting of all links and forms in combination
          with the <em>portal-coplet</em> transformer that is one of the last
          transformers in the main portal pipeline.
        </p>
        <p>
          Each application portlet that isn't changed during this single 
request/response
          cycle, isn't "activated" which means the corresponding application 
pipeline
          is not called.
        </p>
        <p>
          The portal caches the response of an application and severes the 
coplet out
          of the cache until an action for this coplet is triggered.
        </p>
      </s2>
      <s2 title="Several instances of an application">
        <p>
          If you allow the user to have several instances of the same 
application,
          the application has to be aware of this fact. Imagine that each 
instance
          should have its own data set, but as the user is the same, the session
          is shared by the instances. So, a unique identifier for each instance
          is required.
        </p>
        <p>
          The portal framework already supplies this identifier and passes it
          as a request parameter to the pipeline of your application. The name
          of the parameter is <em>copletid</em> and the value is the unique id.
          In our sample, we pass this identifier to the flow script using an
          input module:
        </p>
        <source>
  <![CDATA[...
        <map:match pattern="form">
          <map:call function="form">
            <map:parameter name="copletId" value="{request-param:copletid}"/>
          </map:call>
        </map:match>
  ...]]>
        </source>
        <p>
          In the flow script, we can now use this identifier to calculate a 
unique
          session key to store the information:
        </p>
        <source>
      // get the coplet id
      var cid = cocoon.parameters["copletId"];
      var key = cid + "/myform";
        </source>
        <p>
          From now on you can use this key to get/store session attributes etc. 
In
          addition you can use all features available to flow, like looking up
          components and using them.
        </p>
      </s2>
      <s2 title="Extending the Sample">
        <p>
          Although the sample is very simple (or more precisly the form is very 
simple)
          it demonstrates a possible way to build coplets that handle forms. 
You can
          use this as a guideline for your own forms.
        </p>
        <p>
          If you need, e.g. validation of the form, you can simply add the 
validation
          in the flow script and return a corresponding view in the case of a
          validation error. If you need a more complex processing, e.g. sending 
an
          email, you can simply add this in the flow script as well. Or you can
          code the logic into a Java class and call this class from the flow 
script.
        </p>
        <p>
          In addition, you can use Cocoon forms with all the nice features 
(widgets,
          validation, binding etc.) as well. You only have to provide a working 
set
          of stylesheets that work in the portal.
        </p>
      </s2>
    </s1>
   </body>
  </document>
  
  
  

Reply via email to