Custom context attributes


Summary This topic discusses how to add a custom context attribute by creating a Java class to contain business logic, implementing Web Application Developer Framework (ADF)-specific interfaces that allow your object to participate in the Web ADF lifecycle and be notified of changes to other context attributes, declaring your class as a managed bean, and adding it to the attributes property of the WebContext. It's not necessary to implement the ADF-specific interfaces; you can also add Plain Old Java Objects (POJOs) as custom attributes.

In this topic


WebContext

In a Web ADF application, the WebContext model object ties together various other model objects such as WebMap, WebToc, WebOverview, and so on. Each of these model objects represents the state of a Web ADF JavaServer Faces (JSF) control. For example, WebContext is associated with a Context control, and WebMap is associated with a MapControl. It is this link between the model objects that allows operations on one control to affect the state of other controls. For example, when you zoom in on a map, the overview rectangle is updated, and scale dependent layers in the table of contents (TOC) are toggled.
WebContext connects all the model tier objects that participate in a Web ADF application. WebContext maintains a property called attributes. Any object added to this property is considered a context attribute. WebContext provides facilities, such as lifecycle management and change notification, to these context attributes. By default, each Web ADF application is set up in such a way that all the model tier 1 objects are added as context attributes.
These objects are declared in WEB-INF/context-attributes.xml as shown in the following sample code.
[Java]
 < managed - bean >  < managed - bean - name > map <  / managed - bean - name >  <
     managed - bean - class > com.esri.adf.web.data.WebMap <  / managed - bean -
     class >  < managed - bean - scope > none <  / managed - bean - scope >  <
     managed - property >  < property - name > imageFormat <  / property - name >  <
     value > PNG <  / value >  <  / managed - property >  <  / managed - bean >  <
     managed - bean >  < managed - bean - name > overview <  / managed - bean - name
     >  < managed - bean - class > com.esri.adf.web.data.WebOverview <  / managed -
     bean - class >  < managed - bean - scope > none <  / managed - bean - scope > 
     <  / managed - bean >  < managed - bean >  < managed - bean - name > toc <  /
     managed - bean - name >  < managed - bean - class >
     com.esri.adf.web.data.WebToc <  / managed - bean - class >  < managed - bean -
     scope > none <  / managed - bean - scope >  < managed - property >  < property 
     - name > expandLevel <  / property - name >  < value > 1 <  / value >  <  /
     managed - property >  <  / managed - bean > ....
The objects are also added as context attributes in WEB-INF/faces-config.xml as shown in the following sample code.
[Java]
 < managed - bean >  < managed - bean - name > mapContext <  / managed - bean - name
     >  < managed - bean - class > com.esri.adf.web.data.WebContext <  / managed -
     bean - class >  < managed - bean - scope > session <  / managed - bean - scope
     > ..... < managed - property >  < property - name > attributes <  / property -
     name >  < map - entries >  < map - entry >  < key > map <  / key >  < value > #{
    map
}

 <  / value >  <  / map - entry >  < map - entry >  < key > overview <  / key >  <
     value > #{
    overview
}

 <  / value >  <  / map - entry >  < map - entry >  < key > toc <  / key >  < value
     > #{
    toc
}

 <  / value >  <  / map - entry > .... <  / map - entries >  <  / managed - property
     > .... <  / managed - bean >
You can use this approach, and add your own POJO as a context attribute by adding a <map-entry> to the <map-entries> list as shown in the following sample code.
[Java]
 < managed - bean >  < managed - bean - name > mapContext <  / managed - bean - name
     > ... < managed - property >  < property - name > attributes <  / property -
     name >  < map - entries > .... < map - entry >  < key >
     my_custom_context_attribute <  / key >  < value > #{
    myPojo
}

 <  / value >  <  / mep - entry > .... <  / map - entries >  <  / managed - property
     >  <  / managed - bean > ... < managed - bean >  < managed - bean - name >
     myPojo <  / managed - bean - name >  < managed - bean - class >
     com.mycompany.MyPojoClass <  / managed - bean - class >  < !--Do not specify a
     scope, it will inherit the scope of the WebContext-- >  < managed - bean -
     scope > none <  / managed - bean - scope >  <  / managed - bean >
Alternatively, you can programmatically add your class as a context attribute at runtime as shown in the following sample code.
[Java]
//Get a reference to the WebContext.
WebContext context = .... 
//Add a custom context attribute.
context.setAttribute("my_custom_context_attribute", new com.mycompany.MyPojoClass());
Once added, the context attribute can leverage facilities provided by WebContext by implementing the following appropriate interfaces.
  • WebContextInitialize—Allows the context to initialize and clean up the attribute.
  • WebLifecycle—Allows the context to activate and passivate the attribute while serving a request.
  • WebContextObserver—Allows the context to notify the attribute of changes initiated by other attributes.

Scenario

Imagine you have a Web site that serves maps of your city. Your Web site also has a column showing advertisements from local merchants. You want to modify the Web site so that the displayed advertisements are selected based on the map location.

Implementation

Create a class to extract advertisements from your database based on geographic location as shown in the following sample code.
[Java]
package com.mypackage;
public class AdvertisementSelector{
    public Advertisment[] getAds(){
        //Return the most recently selected advertisements.  }
        private void updateAds(WebExtent extent){
            //Select advertisements based on the map extent.  }
            private void createDatabaseConnection(){
                //Create a connection to the advertisement database.  }
                private void cleanupDatabaseConnection(){
                    //Close the connection to the database. }
                }
Implement the WebContextObserver interface and update the list of advertisements each time the map extent changes. You need to implement the WebContextInitialize interface and add this class as an observer when it is initialized by the Web ADF. This allows WebContext to notify it of any changes. You should also implement the WebLifecycle interface so that you can open and close database connections while servicing a request.
The following sample code shows how your class should look.
[Java]
public class AdvertisementSelector implements WebContextObserver, WebLifecycle,
    WebContextInitialize{
    //WebContextInitialize::init()
    public void init(WebContext context){
        //Add this object as an observer.
        // Its update() method will be called by the context each time a change occurs.
        context.addObserver(this);
    }
    //WebContextInitialize::destroy()
    public void destroy(){}
    //WebLifecycle::activate()
    public void activate(){
        this.createDatabaseConnection();
    }
    //WebLifecycle::passivate()
    public void passivate(){
        this.cleanupDatabaseConnection();
    }
    //WebContextObserver::update()
    public void update(WebContext context, Object arg){
        //Update the advertisements based on the new map extent.
        WebExtent currentExtent = context.getWebMap.getCurrentExtent();
        this.updateAds(currentExtent);
    }
    public Advertisment[] getAds(){
        ....
    }
    private void updateAds(WebExtent extent){
        ....
    }
    private void createDatabaseConnection(){
        ....
    }
    private void cleanupDatabaseConnection(){
        ....
    }
}
Declare this class as a managed bean, and add it as a context attribute in WEB-INF/faces-config.xml as shown in the following sample code.
[Java]
 < managed - bean >  < managed - bean - name > mapContext <  / managed - bean - name
     > ... < managed - property >  < property - name > attributes <  / property -
     name >  < map - entries > .... < map - entry >  < key > advertisement_selector
     <  / key >  < value > #{
    adSelector
}

 <  / value >  <  / mep - entry > .... <  / map - entries >  <  / managed - property
     >  <  / managed - bean > ... < managed - bean >  < managed - bean - name >
     adSelector <  / managed - bean - name >  < managed - bean - class >
     com.mypackage.AdvertisementSelector <  / managed - bean - class >  < managed -
     bean - scope > none <  / managed - bean - scope >  <  / managed - bean >


See Also:

Custom commands and tools