Building Portals with sunSpot
http://xml.apache.org/http://www.apache.org/http://www.w3.org/

Main
Dev Guide

Webapps
Overview
Session Contexts
Authentication
Form Handling
Portal

Scratchpad
Session Contexts
Authentication
Portal

Introduction

NoteIMPORTANT: sunSpot (= portal framework) is part of the scratchpad area of the current Cocoon release. This means it is not officially released yet. The API and functionality might change before it is moved into the official release. Using this is at your own risk! If you want to catch the latest status of these components check out Cocoon from CVS and have a look at this upto-date documentation.

sunSpot is the portal engine of sunShine. It provides the required functionality to display user dependent content with a user defineable layout.

The sunShine portal defintion framework is an XML description of the portal and the contained content. The rendering of the portal to the needed format (such as HTML) is done through stylesheets and is therefore very flexible.

A portal definition can be configured for all users (global), for groups of users (group or role) and for the individual user. The portal admininstrator can use the provided tools to configure every aspect of the portal (from colours to content).

Each "blob" of portal content is contained in a "sunLet". sunLets can be configured into the portal on a per-user or per-group basis allowing a flexible content definition.

sunLets can be minimized, maximized or even removed by the user if he does not wish to see the content. However, the administrator may configure sunLets to be mandatory, in which case they may not be removed.

The different portals are administrated by sunRise applications. Each application can have its own portal.

This documentation explains the different resources for sunSpot, the configuration of a portal and how sunSpot creates the portal view derived from this information. After that all is put together by creating the needed entries in the sitemap for using and displaying a portal.

The Profile

A sunSpot portal is built upon a profile which contains all necessary information: the portal possibilites (the available sunLets, the possible changes to the layout etc.) and the portal view (the layout for this user and the sunLets he chose for himself). This profile is generated when a user logs into the application the portal belongs to. The building of the profile is a very flexible process which allows to have different configurations for different users.

In general the building of the profile consists of four steps:

  1. Building the base profile. This profile defines which possibilites the portal has, which sunLets are available to the portal and which parts of the profile can be changed by the user.
  2. Building the global profile. The base profile is enhanced by a global delta which contains a predefined portal view. This predefined portal view is a starting point for all users.
  3. Building the role profile. The global profile is enhanced by a role delta which contains a predefined portal view. This predefined portal view is a starting point for all users of that role.
  4. Building the user profile. The role profile is augmented by a user delta which contains the portal for this specific user. An optional user status profile with often changing information can optional be appended to the profile.

Only step 1 and 2 are mandatory for the building process. Steps 3 and 4 are optional and depend on the configuration of the users and roles in the system.

Each delta (steps 2, 3 and 4) can modify the possibilites of the portal and the configuration of the sunLets. But it is not allowed to add new features or sunLets. In addition a delta may contain a predefined portal view.

This building process is invoked each time the user logs into the application. So a change to any profile (delta) is incorporated into the user profile: If e.g. a sunLet , which a user has choosen for his portal view, is removed from the system, it is not available to the user anymore and therefore also removed from his portal view.

The global delta, the role delta and the user delta are very similar. They only differ in the name of the root node.

The Base Profile

The base profile consists of three data sources:

  1. The layout profile describes the possibilites and layout of the portal.
  2. The sunLets profile defines all available sunLets for the portal view.
  3. The type profile describes the parts of the profile which can be changed by the user.
The Layout Profile

The layout profile describes the overall layout of the portal including if header or footer are present which colors and fonts are used and so on.

An example profile is shown below. The profile is enclosed in the root node "layout-profile" and consists of the "portal" part and the "sunlets" part:

<layout-profile>
    <portal> <!-- This node contains the layout of the portal view -->
                  <layouts>

                        <layout>
                   <!-- The color of the background -->
                                  <background>
                                       <color>#ffffff</color>
                                  </background>
                   <!-- The font and color for usual text -->
                                  <font>
                                       <type>Arial, Helvetica, sans-serif</type>
                                       <size>2</size>
                                       <color>black</color>
                                  </font>
                          </layout>
                </layouts>

                  <!-- The following means that the sunSpot portal has a header area -->
                <header>
                         <exists>true</exists>
                </header>

                <!-- The following means that sunSpot has 3 columns -->
                <columns>
                         <number>3</number>
                  </columns>

                <!-- The following means that the sunSpot has not a footer area -->
                <footer>
                         <exists>false</exists>
                </footer>
           </portal>

           <sunlets> <!-- This node contains the layout of the sunLets -->
              <layouts>
                    <layout>
                            <title>  <!-- The layout of the title -->
                                   <background>
                                       <color>#46627A</color>
                                   </background>
                                   <font>
                                        <type>Arial</type>
                                        <size>2</size>
                                        <color>#ffffff</color>
                                   </font>
                            </title>

             <content> <!-- The layout of the content -->
                                   <font>
                                        <type>Arial</type>
                                        <size>2</size>
                                        <color>#000000</color>
                                   </font>
                                <background>
                                       <color>#ffffff</color>
                                   </background>
                            </content>
                     </layout>
              </layouts>
          </sunlets>

</layout-profile>
        
The sunLets Profile

The sunLets profile contains all sunLets which are available in the system. It is an XML based resource with the root node "sunlets-profile". All sunLets are defined under a node called "sunlets", so an example profile could look like this:

    <sunlets-profile>
        <sunlets>
            <sunlet id="bankingnews">
                <resource uri="cocoon://sunlet-banking.xml"/>
                <transformation> <!-- optional xsl transformation -->
                    <stylesheet>sunbank/styles/sunlet.xsl</stylesheet>
                </transformation>
                <configuration>
                    <mandatory>false</mandatory>
                    <sizable>true</sizable>
                    <active>true</active>
                    <timeout>5000</timeout> <!-- optional, milliseconds -->
                    <messages>              <!-- optional: Messages -->
                        <sunlet_not_available>
                           Display this if the sunLet is not available.
                        </sunlet_not_available>
                    </messages>
                </configuration>
                <title>Banking News</title>
                <status>
                    <visible>true</visible>
                    <size>max</size>
                </status>
            </sunlet>
        </sunlets>
    </sunlets-profile>

This example defines one sunLet: the bankingnews sunLet with the title "Banking News". The title is displayed in the portal view above the sunLet content. The most important part is the resource definition. Using this resource the sunLet is displayed in the portalview of the user.

  • An uri, e.g.: <resource uri=".."/>. This URI can be a local one which is retrieved using the sitemap or a distant one which is retrieved using an HTTP request. In both cases the resource must deliver valid XML for the sunLet content. If you don't use a protocol, the URI is assumed to be a file.
  • A java class delivering the content.

There a several mandatory configuration parameters for a sunLet. This configuration parameters can only be changed by the portal administrator. The user cannot change them for his portal view.

  • mandatory: Indicates if the sunLet can be removed by the user or if it is always visible.
  • sizable: Is the sunLet sizable? If the value is true the user can minimize this sunLet in his portal view.
  • active: Using this parameter, a sunLet can be deactivated for a distinct period of time. If a sunLet is not active it will not displayed to the user even if he has configured it.

In addition there are some optional parameters:

  • timeout: This is the time in milliseconds, sunSpot waits to get the sunLet content. If the content is not available within this time frame, the sunLet is declared as not available at the moment. The default value for the timeout can be set in the sunSpot configuration (see next chapter).
  • handlesSizable: If this value is true, the sunLet (or better the resource) handles the sizing of this sunLet itselt. This means it determines the data to be displayed if the sunLet is minimized or maximized. If this value is false sunSpot displayes the whole sunLet if it is maximized and only its title if it is minimized. This is the default behaviour.
  • handlesParameters: If this value is true (which is the default value) the resource gets all configuration and status parameters passed, e.g. if the resource is an uri, the parameters are passed as HTTP request parameters.
  • messages/sunlet_not_available: If the sunLet is not available (e.g. external data where the server is not available), a message is displayed. With this optional parameter each sunlet can get a distinct message which overrides the message provided by the user profile.

The status parameters can be changed by the user for configuring his own portal view:

  • visible: If a sunLet is visible it is included in the portal view. If it is not visible it is still configured for the user but it will not displayed.
  • size: Currently two sizes (min and max) are distinquished.

If the source of the sunLet needs additional transformation there are two possibilities for doing the transformation. The first one is creating a pipeline in the sitemap for this sunLet and the second one usses the sunLet configuration for this. As the first one is the usual sunShine pipeline creating process only the second one is covered here.

By defining the "transformation" node inside the "sunlet" node, the source of the sunLet can be transformed with one or more stylesheets. For each stylesheet a "stylesheet" node with the value of the stylesheet path has to be created. The order of appearance determines the order of processing. If e.g. the source of a sunLet is a class or a file, there is no need to specify a pipeline only for this sunLet. Specifying a file/class as source and a "stylesheet" node has the same effect.

Adding a new sunLet

Adding new information to the portal requires four basic steps:

  • Defining the resource containing the information. For external resources only the address (mainly an URI) and the protocol (usually HTTP) is required. Otherwise a new XML resource has to be created with the new content.
  • Defining the stylesheet for the presentation of this content.
  • For local resources: Definition of the pipeline in the sitemap. This pipeline must contain all necessary steps for building the information. It must deliver XML as the serialized format.
  • Adding a new "sunlet" node to the sunLets profile.

After these steps are finished, the new sunLet is automatically available for each user which logs in after the addition. If the sunLet is even mandatory it will be added to the portal view of the user.

For more information see the chapter "The Pipelines".

Customizable sunLets

Each sunLet can have its own configuration, e.g. a weather sunLet should display the weather for a particular city etc.

    <sunlets-profile>
        <sunlets>
            <sunlet id="bankingnews">
                <resource uri="cocoon://sunlet-banking.xml"/>
                <customization uri="cocoon://customize-sunlet-banking.xml"/> <!-- optional -->
                <transformation> <!-- optional xsl transformation -->
                    <stylesheet>sunbank/styles/sunlet.xsl</stylesheet>
                </transformation>
                <configuration>
                    <mandatory>false</mandatory>
                    <sizable>true</sizable>
                    <active>true</active>
                    <timeout>5000</timeout> <!-- optional, milliseconds -->
                    <messages>              <!-- optional: Messages -->
                        <sunlet_not_available>
                           Display this if the sunLet is not available.
                        </sunlet_not_available>
                    </messages>
                    <customizable>true</customizable> <!-- optional -->
                    <persistent>false</persistent>    <!-- optional -->
                </configuration>
                <title>Banking News</title>
                <status>
                    <visible>true</visible>
                    <size>max</size>
                </status>
            </sunlet>
        </sunlets>
    </sunlets-profile>

To declare a sunLet as customizable it must get a configuration resource which is displayed to a user of this sunLet to enter all required configuration values. This is done with the customization tag. The value for this tag has the same possibilities as the resource tag, usually the uri attribute points to a pipeline.

When a user has configured/choosen a customizable sunLet, sunSpot detects if this sunLet has its configuration. If it does not have one, the customization resource of the sunLet is displayed in the portal view. Otherwise the sunLet itself is displayed.

In addition a customizable sunLet can be persistent, e.g. the configuration is saved for a longer period than the current session of the user. If the sunLet is not persistent the configuration is lost when the user logs out. The next time he logs in, the customization page is displayed to configure this sunLet again.

If you use persistent sunLets you have to configure resources for loading and saving the status profile (See configuration). More about writing customizable sunLets can be found in the chapter "Writing Customizable sunLets".

The Type Profile

The type profile describes the possible values the user can change for his portal view. Using this flexible approach the portal administrator can decide which user can choose what. For example, a normal user might change the layout and content of his portal view, but a guest might not be allowed to change anything, whereas the administrator can change everything.

The type profile is surrounded by the root node "type-profile". It consists of two parts: the typedefs section and the elements section. The type profile can be compared with a programming language. The typedefs section declares all available types and the the elements section declares all variables with their corresponding types. A "variable" defines a place or element in the user profile which can be changed by the user. The possibilites for this element are defined by the type.

The typedefs contains enumerations, e.g. a set of possible values with a user presentable name. In addition sunSpot has the following predefined types: STRING (arbitrary text), BOOLEAN (true or false), INTEGER (a number) and CARDINAL (a positiv number).

<type-profile>

     <typedefs>
                <!-- The following types are defined by sunSpot: (Names are casesensitiv!)
                          STRING, BOOLEAN, ENUMERATION, INTEGER, CARDINAL -->

          <typedef name="backgroundcolor" type="ENUMERATION">
                    <value name="weiss">#ffffff</value>
                    <value name="hellgrau">#cccccc</value>
                    <value name="hellgruen">#aab9bf</value>
                    <value name="dunkelgruen">#46627A</value>
                </typedef>
                <typedef name="textcolor" type="ENUMERATION">
                    <value name="weiss">white</value>
                    <value name="schwarz">black</value>
                    <value name="weiss">#ffffff</value>
                    <value name="hellgrau">#cccccc</value>
                    <value name="hellgruen">#aab9bf</value>
                    <value name="dunkelgruen">#46627A</value>
                </typedef>
                <typedef name="sunletsize" type="ENUMERATION">
                    <value name="Maximized">max</value>
                    <value name="Minimized">min</value>
                </typedef>
                <typedef name="columnnumber" type="ENUMERATION">
                    <value name="1">1</value>
                    <value name="2">2</value>
                    <value name="3">3</value>
                    <value name="4">4</value>
                    <value name="5">5</value>
                </typedef>
    </typedefs>

</type-profile>

The element section has the same structure a the user profile. For each leave which is changeable by the user the elements section contains an entry for the type of this node. The node is enhanced by two attributes: type for the node type and description for a user readable title. This information is used by sunSpot to present the configuration screen for the portal. It displayes for each changeable leave a form field with the corresponding type.

<type-profile>
        <elements>
               <layout-profile>
                   <portal><layouts>
                          <layout>
                     <!-- The user can change the background.
                          The possible values are taken from the enumeration
                          backgroundcolor. The user gets the title "Background"
                          displayed for the form field. -->
                            <background>
                                     <color type="backgroundcolor" description="Background"/>
                             </background>
                        <font>
                         <color type="textcolor" description="Font color"/>
                              </font>
                          </layout>
                        </layouts>
                         <columns>
                    <!-- The user can change the number of columns -->
                    <number type="columnnumber" description="Number of columns"/>
                </columns>
                   </portal>
               </layout-profile>

         <portal-profile>
                    <content>
                 <!-- Using the * the following configuration is applied for
                      all columns regardless of their position. -->
                            <column position="*">
                                    <width type="CARDINAL" description="Width"/>
                                    <sunlets>
                         <!-- Using the * the following configuration is applied for
                              each sunlet. -->
                                        <sunlet id="*" position="*" number="*">
                                            <status>
                             <!-- The user can change the visibility and size
                                  of the sunLet -->
                                                    <visible type="BOOLEAN" description="Visible"/>
                                                    <size type="sunletsize" description="Size"/>
                                        </status>
                                        </sunlet>
                                </sunlets>
                            </column>
                    </content>
               </portal-profile>
        </elements>
</type-profile>
The Global Profile

The global delta, the role delta and the user delta are very similar. They only differ in the name of the root node. So this chapter only describes the global delta and points out the differences between the deltas at the various place rather than repeating the same information in different chapters.

The global delta is enclosed in the root node "global-delta", the role delta uses the node "role-delta" and the user delta the node "user-delta".

In general a delta defines the differences between two profiles. The sunSpot deltas allow only adding and changing but not removing nodes. Each delta can contain the following parts:

  • The layout delta containing the difference to the layout profile.
  • The sunlets delta describing the differences to the sunlets profile.
  • The portal profile containing a complete portal view. This part is not a delta. If it is contained in a delta and the profile already has this information, that information is replaced by the one from the delta. Otherwise the delta information is added. For the global profile the portal profile is mandatory.
  • The personal profile. This part contains personal information of the user, e.g. are welcome text. For the global profile this information again is mandatory. It defines the possibilites the user has. The role and the user profile can only change this information. But they cannot add any new nodes.

So here is an example:

<global-delta>
       <!-- No difference to the base profile -->
    <layout-delta>
       </layout-delta>

       <!-- No difference to the base profile -->
       <sunlets-delta>
       </sunlets-delta>

    <!-- This is the starting portal view for all users.
         It has to be defined in the global profile -->
    <portal-profile>

        <!-- This is the content of the portal view -->
           <content>
                  <header>
                          <sunlet id="personalize" position="1">
                                 <status>
                                          <visible>true</visible>
                                          <size>max</size>
                                </status>
                            </sunlet>
                  </header>
                  <column position="1">
                         <width>28%</width>
                                                                <!-- The sunLets are displayed in the order of their
                     position attribute in each column. -->
                         <sunlets>
                              <sunlet id="administration" number="1" position="1">
                                     <status>
                                              <visible>true</visible>
                                            <size>max</size>
                                       </status>
                                </sunlet>
                         </sunlets>
                  </column>

                  <column position="2">
                         <width>50%</width>
                             <sunlets>
                                <sunlet id="banknews" number="2" position="1"/>
                            </sunlets>
                </column>

                  <column position="3">
                         <width>22%</width>
                         <sunlets/>
                </column>
        </content>
</portal-profile>

<personal-profile>
       <greeting>Herzlich willkommen</greeting>
       <messages>
              <sunlet_not_available>Das sunLet ist zur Zeit nicht verfuegbar.</sunlet_not_available>
       </messages>
</personal-profile>

</global-delta>
The User Status Profile

The user status profile contains often changing information like the configuration of configurable sunLets, the last login time etc. The user status profile is optional, but if it is not accessible, customizable sunLets are not possible.

For each customizable sunLet which is in the portal view of the user the status profile contains an XML block with the sunLet specific configuration for this sunLet.

<status-profile>
    <customization>
        <!-- Custom information for each customizable sunLet -->
        <sunlet id="popmail" number="3">
            <host>mail</host>
            <password>gsgdgsg</password>
            <mailcount>4</mailcount>
            <user>walter</user>
        </sunlet>
    </customization>
</status-profile>
Configuring sunSpot

The configuration of sunSpot is actually a sunRise application configuration. Please refer to the sunRise documentation for more information about sunRise handler and application configuration.

Inside your sunRise handler configuration you define for each portal an application configuration for sunSpot like the example portal called "sunBank" below:

    <application name="sunBank">
        <configuration name="sunSpot"> <!-- This is the portal configuration -->
            <portal-uri>finance-portal</portal-uri>
            <profile-cache>true</profile-cache>
            <process-sunlets-parallel>false</process-sunlets-parallel>
            <default-sunlet-timeout>10000</default-sunlet-timeout>
            <profile>
                <!-- The resource for loading the layout profile -->
                <layout-base uri="cocoon://financeresource-layoutprofile"/>
                <!-- The resource for loading the base sunlets profile -->
                <sunlet-base uri="cocoon://financeresource-sunletprofile"/>
                <!-- The optional resource for saving the base sunlets profile -->
                <sunlet-base-save uri="cocoon://financeresource-savesunletprofile"/>

                <!-- The optional type resource -->
                <type-base uri="cocoon://financeresource-types"/>
                                     <!-- The optional type resource for the admin configuration -->
                <admin-type-base uri="cocoon://financeresource-admintypes"/>

                <!-- The resources for loading/saving the deltas -->
                <global-delta-load uri="cocoon://financeresource-globalprofile"/>
                <global-delta-save uri="cocoon://financeresource-saveglobalprofile"/>
                <role-delta-load uri="cocoon://financeresource-roleprofile"/>
                <role-delta-save uri="cocoon://financeresource-saveroleprofile"/>
                <user-delta-load uri="cocoon://financeresource-userprofile"/>
                <user-delta-save uri="cocoon://financeresource-saveuserprofile"/>

                <!-- Optional resources for loading/saving the status profile
                     which is required for persistent, customizable sunLets -->
                <user-status-load uri="cocoon://financeresource-loadstatusprofile"/>
                <user-status-save uri="cocoon://financeresource-savestatusprofile"/>

                <!-- optional type resources -->
                <global-type-delta uri="..."/>
                <role-type-delta uri="..."/>
                <user-type-delta uri="..."/>
            </profile>
            <!-- Redirect to this resource, if the user is not authenticated
                 to view that sunLet -->
            <auth-redirect>finance-portal</auth-redirect>
        </configuration>
    </application>
Global Portal Configuration

One mandatory configuration value for the portal is the portal-uri. It must point to a pipeline which produces the portal view for a user (see next section for more information about the pipelines).

Profile Caching

sunSpot contains an intelligent profile caching mechanism which detects automatically changes to profiles and determines upon this information which profile must be rebuild.

Without profile caching a profile is build each time a user logs in. With profile caching the profile is only build if there is no cached profile or if something has changed in the profiles for this user. Only the user status profile is not cached at all as it is often changing.

By specifying the profile-cache tag in the sunSpot configuration with the value true the profile caching is turned on. If the tag is not available no profile caching is performed.

If profile caching is turned on, the profiles should not be changed by hand as the cache does not detect such changes. All changes to the profiles must be done using the sunSpot tools. However if you change a profile or part of a profile by hand, make sure that you clean the cache afterwords. Cleaning the cache can be done either by the provided sunSpot tools or by deleting all files inside the cache directory.

Global sunLet configuration

Usually the portal view is generated step by step, e.g. the sunLets are build one after the other. sunSpot can be configured to get the sunLets content parallel to decrease the response time for the portal view. By specifying the process-sunlets-parallel tag with the value true, the sunLets are processed parallel.

If the content of a sunLet is not available, e.g. if the contentresides on an external HTTP server, the processing of this sunLet can take a "very long" time, e.g. until a timeout occures. sunSpot monitors the sunLets and can stop the processing of a sunLet after a distinct period of time. This period can be specified by the tag "default-sunlet-timeout" in milliseconds. If the content of the sunLet is not available after the time has expired, the sunLet is declared as "not available". The default timeout is 10 minutes.

For a fine-tuning of sunLet timeouts, each sunLet can get its own timeout (see the sections below).

Profile Resources

Each part of the profile has a corresponding resource which is invoked for loading or saving the profile part, e.g. one resource for loading the global profile delta and a separate one for saving it. The loading resources must deliver the xml described in the previous chapters.

All resources get the parameter "application" with the name of the corresponding application and "handler" with the name of the sunRise handler. The list below shows the additional parameters for the other resources.

  • sunlet-base: "profile" with value "sunlet-base"
  • sunlet-base-save: "profile" with value "sunlet-base"
  • layout-base: "profile" with value "layout-base"
  • type-base: "profile" with value "type-base"
  • admin-type-base: "profile" with value "admin-type-base"
  • global-delta-load: "profile" with value "global-delta"
  • global-type-delta: "profile" with value "global-type-delta"
  • global-delta-save: "profile" with value "global-delta"
  • role-delta-load: "profile" with value "role-delta", "role" with name of the role
  • role-delta-save: "profile" with value "role-delta", "role" with name of the role
  • role-type-delta: "profile" with value "role-type-delta", "role" with role name
  • user-delta-load: "profile" with value "user-delta", "role" with role name, "ID" with user ID
  • user-delta-save: "profile" with value "user-delta", "role" with role name, "ID" with user ID
  • user-type-delta: "profile" with value "user-type-delta", "role" with role name, "ID" with user ID
  • user-status-load: "profile" with value "user-status", "role" with role name, "ID" with the user ID
  • user-status-save: "profile" with value "user-status", "role" with role name, "ID" with the user ID
The Pipelines

So far the chapters only described configuring sunSpot and writing resources. This chapter closes the gap and explains the steps for showing the portal.

For defining the pipelines in the sitemap, sunSpot declares two generators (the "sunSpotGenerator" and the "sunSpotConfGenerator") and one transformer ("sunSpot").

Displaying the portal view

Displaying the portal view is a very simple step: defining a pipeline with the "sunSpotGenerator" as the generator, the sunRise transformer for defining the application and an stylesheet for creating the presentation:

		<map:match pattern="sunbank-portal">
                <map:act type="sunRise-auth"/>         <!-- for getting the sunSpot configuration -->
                        <map:parameter name="handler" value="sunshinehandler"/>
                         <map:parameter name="application" value="sunBank"/>

                    <map:generate type="sunSpot"/> <!-- generate the portal view -->
                            <map:transform src="sunbank/styles/portalHTML.xsl"/> <!-- presentation in HTML -->
                      <map:serialize/>
      </map:act>
        </map:match>
The Generated Portal View

The XML generated by the "sunSpotGenerator" is not exactly the same as for the user profile. sunSpot optimizes and reorganizes the profile. All fields (or nodes) which are changeable have the attributes "formdescription", "formpath" and "formtype". "formdescription" is a user readable description of the field, "formpath" is the name of the form parameter which can be used to set the value and "formtype" indicates the type of the field. The belonging type can be found in the types section of the profile.

<!-- The portal indicates that the following is the portal view -->
<portal>

    <!-- The configuration of the portal -->
    <configuration>
        <!-- This is the uri which should be invoked for rebuilding the portal view
             and for changing the view. The parameter sunspotprofile is always
             present and indicates the current profile. -->
        <uri>finance-portlets?sunspotprofile=uprofile:sunBank:user_admin_sunshine</uri>
        <!-- This is the uniquie sunSpot profile ID -->
        <profile>uprofile:sunBank:user_admin_sunshine</profile>
        <media>html</media> <!-- The current media: html or wap -->
    </configuration>

    <!-- Now the needed part of the layout profile: -->
    <layout>
        <portal>
                        <background>
                                <color formdescription="Hintergrundfarbe" formpath="sunspotconf.0.0" formtype="backgroundcolor">#aab9bf</color>
                        </background>
                        <font>
                                <type>Arial, Helvetica, sans-serif</type>
                                <size>2</size>
                                <color formdescription="Schriftfarbe" formpath="sunspotconf.1.0" formtype="textcolor">black</color>
                        </font>
                    </portal>

        <sunlets>
                           <title>
                                <background>
                                      <color>#46627A</color>
                                </background>
                                  <font>
                                    <type>Arial</type>
                                       <size>2</size>
                                       <color>#ffffff</color>
                                  </font>
                           </title>
                        <content>
                                <background>
                                      <color>#000000</color>
                                </background>
                                  <font>
                                    <type>Arial</type>
                                       <size>2</size>
                                       <color>#ffffff</color>
                                  </font>
                           </content>
                    </sunlets>
    </layout>

    <!-- This is the portal view: -->
    <header>
        <sunlet id="personalize" position="1" number="1">
            <resource uri="financesunlet-personalize.xml"/>
            <configuration>
                            <mandatory>true</mandatory>
                            <sizable>true</sizable>
                            <active>true</active>
                        </configuration>
            <title>Personalisieren</title>
            <status>
                <visible>true</visible>
                <size>max</size>
            </status>
            <content>..the sunLet content...</content>
        </sunlet>
          </header>

    <columns number="3">
        <column position="1" width="28%">
                        <sunlet id="administration" position="1" number="1">
                  <resource uri="financesunlet-administration.xml"/>
                  <configuration>
                      <mandatory>false</mandatory>
                      <sizable>true</sizable>
                      <active>true</active>
                            </configuration>
                  <title>sunShine Administration</title>
                  <status>
                      <visible formdescription="Sichtbar" formpath="sunspotconf.4.0" formtype="BOOLEAN">true</visible>
                      <size formdescription="Groesse" formpath="sunspotconf.5.0" formtype="sunletsize">max</size>
                  </status>
                  <content>..the sunLet content...</content>
              </sunlet>
                        ....
                 </column>
        <column position="2" width="50%">
            ...
            </column>
        <column position="3" width="22%">
            ...
                 </column>
    </columns>

    <!-- The personal information -->
    <personal-profile>
        <greeting>Hi there!</greeting>
        <messages>
                <sunlet_not_available>The sunLet is currently not available.</sunlet_not_available>
        </messages>
    </personal-profile>
</portal>
Administration of the portal view

Displaying the administration page of the portal is as simple as displaying the portal. The difference lies in changing the generator to the "sunSpotConfGenerator":

		<map:match pattern="sunbank-conf">
                  <map:act type="sunRise-auth">
                         <map:parameter name="handler" value="sunshinehandler"/>
                         <map:parameter name="application" value="sunBank"/>

                    <map:generate type="sunSpot-conf"/>
                      <map:transform src="sunbank/styles/portalconfHTML.xsl"/>
                      <map:serialize/>
                  </map:act>
        </map:match>

Make sure to protect the portal configuration generator as the administrator can change all profiles, clear the cache etc. It should only be available for real sunSpot administrators.

The Generated Administration View

The XML generated by the "sunSpotConfGenerator" is not exactly the same as the user profile. sunSpot addes some information to the profile. All fields (or nodes) which are changeable have the attributes "formdescription", "formpath" and "formtype". "formdescription" is a user readable description of the field, "formpath" is the name of the form parameter which can be used to set the value and "formtype" indicates the type of the field. The belonging type can be found in the types section of the profile.

<!-- The portalconf node indicates that the following is the portal administration view -->
<portalconf>

<!-- The configuration of the portal -->
    <configuration>
        <!-- This is the uri which should be invoked for rebuilding the portal view
             and for changing the view. The parameter sunspotprofile is always
             present and indicates the current profile. -->
        <uri>finance-portlets?sunspotprofile=uprofile:sunBank:user_admin_sunshine</uri>
        <!-- This is the uniquie sunSpot profile ID -->
        <profile>uprofile:sunBank:user_admin_sunshine</profile>
        <media>html</media> <!-- The current media: html or wap -->
    </configuration>

    <!-- The layout profile, see chapter about the layout profile -->
    <layout-profile>
            <portal>
                     <layouts>
                         <layout>
                                   <background>
                                        <color formdescription="Hintergrundfarbe" formpath="sunspotconf.0.0" formtype="backgroundcolor">#aab9bf</color>
                                   </background>
                                   <font>
                                        <type>Arial, Helvetica, sans-serif</type>
                                        <size>2</size>
                                        <color formdescription="Schriftfarbe" formpath="sunspotconf.1.0" formtype="textcolor">black</color>
                                   </font>
                           </layout>
                   </layouts>

                   <header>
                            <exists>true</exists>
                    </header>

                     <columns>
                            <number formdescription="Anzahl" formpath="sunspotconf.2.0" formtype="columnnumber">3</number>
                     </columns>

                    <footer>
                            <exists>false</exists>
                    </footer>
              </portal>

              <sunlets>
                     <layouts>
                            <layout>
                                <title>
                                          <background>
                                              <color>#46627A</color>
                                        </background>
                                        <font>
                                               <type>Arial</type>
                                                <size>2</size>
                                            <color>#ffffff</color>
                                        </font>
                                </title>
                                <content>
                                        <font>
                                               <type>Arial</type>
                                                <size>2</size>
                                            <color>#000000</color>
                                        </font>
                                          <background>
                                              <color>#ffffff</color>
                                        </background>
                                </content>
                            </layout>
                    </layouts>
            </sunlets>

        </layout-profile>

     <!-- The sunLets profile, see chapter about the sunLets profile -->
     <sunlets-profile>
              <sunlets>
             <sunlet id="banknews">
                             <resource uri="onlinesunlet-banking.xml"/>
                            <configuration>
                                    <mandatory>false</mandatory>
                                <sizable>true</sizable>
                                    <active>true</active>
                             </configuration>
                            <title>Banking News</title>
                             <status>
                                <visible>true</visible>
                                <size>max</size>
                            </status>
                    </sunlet>
             ...
            </sunlets>

        </sunlets-profile>

     <!-- The type profile, see the chapter about the type profile -->
     <typedefs>
         ...
     </typedefs>

      <!-- And now the portal view, see chapter about the portal profile -->
     <portal-profile>

            <content>
                   <header>
                           <sunlet id="personalize" position="1" number="1">
                                  <status>
                                           <visible>true</visible>
                                           <size>max</size>
                                    </status>
                             </sunlet>
                </header>
                <column position="1">
                        <width formdescription="Breite" formpath="sunspotconf.3.0" formtype="CARDINAL">28%</width>
                        <sunlets>
                               <sunlet id="administration" position="1" number="2">
                                        <status>
                                            <visible formdescription="Sichtbar" formpath="sunspotconf.4.0" formtype="BOOLEAN">true</visible>
                                            <size formdescription="Groesse" formpath="sunspotconf.5.0" formtype="sunletsize">max</size>
                                        </status>
                                </sunlet>
                               ...
                        </sunlets>
                   </column>

                    <column position="2">
                   ...
                    </column>

                    <column position="3">
                   ...
                    </column>

            </content>
     </portal-profile>

     <!-- The personal profile, see the corresponding chapter -->
     <personal-profile>
            <greeting>Hi there!</greeting>
            <messages>
                <sunlet_not_available>The sunLet is currently not available.</sunlet_not_available>
            </messages>
     </personal-profile>
</portalconf>
Changing the Profile

The profile can be changed using a HTTP request. The invoked resources is the uri defined in the "configuration" section of the portal view. It contains already the needed parameter "sunspotprofile" with the given value. This parameter tells sunSpot which profile it should change.

Each field which is changeable has the parameters "formdescription", "formtype" and "formpath". The "formdescription" is a user-readable text for this field. The "formtype" is the type of the field. It is a type name which has a corresponding entry in the type profile. The type profile contains all possible values for this particular type. The "formpath" contains the name of the field to change. So changing an field is submitting a form value with the name of "formpath" and one of the values denoted by the "formtype".

In addition to this sunSpot recognizes the special parameter "sunspotcmd". It can control the appearance of the sunLets. The value of the parameter is one of the following followed by '_', the sunLet id attribute, another '_' and the sunLet number attribute. For example minimizing a sunLet is done by passing "sunspotcmd=minimize_1_3" to the request. The commands are as follows:

  • "maximize" : Maximize the sunLet.
  • "minimize" : Minimize the sunLet.
  • "close" or "hide" : Close the sunLet, it will not be displayed in the portal view, but is still configured.
  • "open" or "show" : A configured sunLet will be included in the portal view again.
  • "delete" : Remove the sunLet from the profile.
  • "move" : Move the sunLet to the column which is append to value separated by '_'. So "sunspotcmd=move_1_3_2" would move the sunLet into the 2nd column.
  • "new" : Add a new sunLet to the profile. Only the attribute id of the sunLet is passed. Instead of the number attribute the column number is appended. If instead "header" or "footer" is passed instead of the column number, the sunLet is moved into that special area.
  • "update" : Change from the customization view of the sunLet to the sunLet content view.

The profile can be save persistent by sending the parameter "sunspotcmd" with the value "save"in addition to the "sunspotprofile" parameter.

Defining sunLets

Defining a pipeline for a sunLet is also very straightforward. Together with your "real" pipeline for defining the content and doing the presentation, the "sunSpot-auth" action and the sunRise-auth action are needed. The first one for protecting the sunLet and the second one for defining the application the resource belongs to:

		<map:match pattern="licence-sunlet">
      <!-- Get the application configuration -->
                  <map:act type="sunRise-auth">
                         <map:parameter name="handler" value="sunshinehandler"/>
                         <map:parameter name="application" value="sunBank"/>

          <!-- secure the sunLet: -->
          <map:act type="sunSpot-auth">
               <map:parameter name="sunLet" value="licencing"/>
          </map:act>

                <!-- The resource containg the licencing information: -->
          <map:generate src="sunshine/licencing.xml"/>

          <!-- present it in HTML -->
                      <map:transform src="sunbank/styles/HTML.xsl"/>
          <!-- Serialize it to XML for including in the portal view: -->
                      <map:serialize/>
      </map:act>
        </map:match>

In this example the sunLet is protected by the use of the parameter tag inside the "sunSpot-auth" action. Only if the user is allowed to view/configure the sunLet with the ID "licencing", he can invoke this resource. If this security command is left out, everyone is able to get the resource by simply invoking it directly from the browser. However, if the sunLet is protected it is not necessary that a user has choosen that sunLet for his current portal view to invoke the resource. In addition it is possible to specify the parameter without a specific sunlet name. This protects the resource as a sunLet: Only users which are logged in to the portal can view the resource.

Getting Profile Information within a sunLet

Each sunLet has access to nearly all information of the profile, including layout information and configuration. The sunLet can retrieve this information using a special session context called sunSpot. With the familiar commands of the sunShine transformer (getxml etc.) the information can be included in the current xml stream of a sunLet.

The content of the context looks like the following:

<layout>
    <portal>
                <background>
                            <color formdescription="Hintergrundfarbe" formpath="sunspotconf.0.0" formtype="backgroundcolor">#aab9bf</color>
                </background>
                <font>
                            <type>Arial, Helvetica, sans-serif</type>
                            <size>2</size>
                            <color formdescription="Schriftfarbe" formpath="sunspotconf.1.0" formtype="textcolor">black</color>
                     </font>
    </portal>

    <sunlets>
                    <title>
                            <background>
                            <color>#46627A</color>
                            </background>
                        <font>
                                <type>Arial</type>
                                   <size>2</size>
                                   <color>#ffffff</color>
                        </font>
                    </title>
                    <content>
                            <background>
                            <color>#000000</color>
                            </background>
                        <font>
                                <type>Arial</type>
                                   <size>2</size>
                                   <color>#ffffff</color>
                        </font>
                    </content>
                </sunlets>
</layout>
<configuration>
        <!-- This is the uri which should be invoked for rebuilding the portal view
             The parameter sunspotprofile is always
             present and indicates the current profile. -->
        <uri>finance-portlets?sunspotprofile=uprofile:sunBank:user_admin_sunshine</uri>
        <!-- This is the uniquie sunSpot profile ID -->
        <profile>uprofile:sunBank:user_admin_sunshine</profile>
        <media>html</media> <!-- The current media: html or wap -->
</configuration>

Using this information the sunLet can layout itself with the layout chosen by the user for the portal. For example a <sunshine:getxml context="sunSpot" path="/layout/sunlets/content/background/color"/> is replaced by the sunShine transformer with the color value for the background (here "#000000)".

Writing Customizable sunLets

Writing a customizable sunLet requires two task:

  1. Creating the resource for the customization of the sunLet
  2. Creating a resource for the sunLet content which uses the configuration

The resource for the customization is very similar to the "real" resource for the sunLet. It is - in most cases - a pipeline which delivers xml and this xml is included in the portal view. Usually this xml contains a form for the user to define the configuration of the sunLet.

The configuration of the sunLet is available using the special sunSpot session context. For a customizable sunLet this context is augmented with the current configuration of the sunLet:

<layout>
    ...
</layout>
<configuration>
    ...
    <context>unique id for the sunLet for external applications</context>
</configuration>
<sunlet-data>
    ... the configuration ....
</sunlet-data>

Using the sunShine form handling it is very easy to write a customization view for a sunLet. The following example dispalys a form for a mail sunLet which requires the configuration for a mail host, a user name and a password.

<page xmlns:sunshine="http://cocoon.apache.org/sunshine/1.0">
       <!-- Define a form -->
    <sunshine:form name="popmail" method="POST">
            <sunshine:action>
            <!-- The action is send to the pipeline redisplaying the portal -->
            <sunshine:getxml context="sunSpot" path="/configuration/uri"/>
        </sunshine:action>
        <!-- Create the input fields for
             host, username and password -->
            <sunshine:content>
                     <sunshine:inputxml context="sunSpot" path="/sunlet-data/host" name="Host" type="text"/>
                     <sunshine:inputxml context="sunSpot" path="/sunlet-data/user" name="User" type="text"/>
                     <sunshine:inputxml context="sunSpot" path="/sunlet-data/password" name="Password" type="password"/>
            </sunshine:content>
        <!-- The submit button -->
        <input type="submit" value="Customize"/>
    </sunshine:form>
</page>
        

The sunShine inputxml tags assure that the information provided by the user is automatically written into the sunSpot context at the places provided.

Writing the resource for the sunLet is as easy. The sunLet can use the getxml command to retrieve to configuration from the sunSpot context:

<page xmlns:sunshine="http://cocoon.apache.org/sunshine/1.0">
    <!-- Get the configuration information out of the sunSpot context -->
    <!-- and feed it into the getmail command -->
        <sunshine:getmail>
            <sunshine:user> <!-- Set the user -->
             <sunshine:getxml path="/sunlet-data/user" context="sunSpot"/>
         </sunshine:user>
            <sunshine:password> <!-- Set the password -->
             <sunshine:getxml path="/sunlet-data/password" context="sunSpot"/>
         </sunshine:password>
            <sunshine:host> <!-- Seet the host -->
             <sunshine:getxml path="/sunlet-data/host" context="sunSpot"/>
         </sunshine:host>
        </sunshine:getmail>
</page>

Each time the sunLet configuration changes the user status profile is automatically saved.

External Resources and Customizable sunLets

External resources which are configured with the same sunRise handler and application as the portal can retrieve configuration information from a sunLet. If the resource is invoked with the request parameter sunspotcontext it has access to the same sunSpot context as the sunLet.

The value for the request parameter can be retrieved by the calling resource, e.g. the sunLet, from the sunSpot context using the path /configuration/context. The external resource must have the sunSpot-auth action configured in its pipeline. The action checks for the request parameter and grants the resource access to the sunSpot context of the sunLet.

Copyright © 1999-2002 The Apache Software Foundation. All Rights Reserved.