Java Studio Creator Portlets: Under the Hood #1

So this is the first of hopefully several blogs on looking under the hood of portlet development in Java Studio Creator.

Background

Today I'll cover getting at portlet preferences. First, let's get some background information about preferences out of the way. JSR-168 says:

"Portlet preferences are intended to store basic configuration data for portlets. It is not the purpose of the portlet preferences to replace general purpose databases."

Most portal users would expect to click on the window decoration associated with "EDIT" to get to the settings for the portlet. JSR-168 also puts a restriction on when preferences can be changed. From JSR-168:

Portlets have access to the associated PortletPreferences object while they are processing requests. Portlets may only modify preferences attributes during a processAction invocation.

Details

Enough background, let's get to some code. As stated in JSR-168, you get to portlet preferences through a "PortletRequest". We can get to "PortletRequest" through "javax.faces.context.ExternalContext". Finally, we can get "javax.faces.context.ExternalContext" through the session bean created for each Creator portlet.

From the session bean, the code would look like this:


        ExternalContext externalContext = this.getExternalContext();
        PortletRequest request = (PortletRequest) externalContext.getRequest();
        PortletPreferences portletPreferences = request.getPreferences();

From the page bean, the code would look like this:

        ExternalContext externalContext = this.getSessionBean1().getExternalContext();
        PortletRequest request = (PortletRequest) externalContext.getRequest();
        PortletPreferences portletPreferences = request.getPreferences();

Gotchas

A logical approach would be to associate the portlet preferences with the session bean and let the session bean manage getting the preferences. This works fine for reading the preferences. If you want to save the preferences through "store", however, the Pluto implementation has a "gotcha". Pluto enforces the JSR-168 restriction Portlets may only modify preferences attributes during a processAction invocation. by checking what type of request you're in when you get the preferences. This means if you get the preferences from the session bean when you want to read values to fill in content, the Pluto implemented PortletPreferences record the fact that you got them through a render request. When you go to "store" the preferences, Pluto throws an IllegalStateException exception stating "store is only allowed inside a processAction call". One way around this would be to get the preferences just before you "store" and set the new preferences with values from the existing preferences. Please see the solution below.

Solution

Here's an example of how to manage preferences from a Creator portlet.

  1. Create your preferences page something like this.
  2. Modify SessionBean1.
    snip..
        
        private PortletPreferenceAdapter portletPreferenceAdapter;
    snip...
        public void init() {
    
            portletPreferenceAdapter = new PortletPreferenceAdapter(this);
        }
    snip...    
        
        public PortletPreferenceAdapter getPortletPreferenceAdapter() {
            return portletPreferenceAdapter;
        }    
        public ExternalContext getSessionContext() {
            return this.getExternalContext();
        }
        
    
  3. Create PortletPreferencesAdapter.
    import java.io.IOException;
    import javax.faces.context.ExternalContext;
    import javax.portlet.PortletPreferences;
    import javax.portlet.PortletRequest;
    import javax.portlet.ReadOnlyException;
    import javax.portlet.ValidatorException;
    
    /\*\*
     \*
     \* @author David Botterill
     \*/
    public class PortletPreferenceAdapter {
        
        private PortletPreferences portletPreferences;
        private SessionBean1 sessionBean;
        
        /\*\* Creates a new instance of MyPortletPreferences \*/
        public PortletPreferenceAdapter(SessionBean1 inSessionBean) {
            sessionBean = inSessionBean;
            ExternalContext context = sessionBean.getSessionContext();
            PortletRequest request = (PortletRequest) context.getRequest();
            this.portletPreferences = request.getPreferences();
        }
        
        
        /\*\*
         \* Getter for property name.
         \* @return Value of property name.
         \*/
        public String getName() {
            
            return (String) portletPreferences.getValue("name",null);
        }
        
        /\*\*
         \* Setter for property name.
         \* @param name New value of property name.
         \*/
        public void setName(String name) throws ReadOnlyException {
            
            portletPreferences.setValue("name", name);
        }
        
        
        /\*\*
         \* Getter for property phone.
         \* @return Value of property phone.
         \*/
        public String getPhone() {
            
            return (String) portletPreferences.getValue("phone",null);
        }
        
        /\*\*
         \* Setter for property phone.
         \* @param phone New value of property phone.
         \*/
        public void setPhone(String phone) throws ReadOnlyException  {
            
            portletPreferences.setValue("phone", phone);
            
        }
        
        public void save() throws ReadOnlyException, IOException, ValidatorException  {
            ExternalContext context = sessionBean.getSessionContext();
            PortletRequest request = (PortletRequest) context.getRequest();
            PortletPreferences storePreferences = request.getPreferences();
                    
            storePreferences.setValue("name", this.getName());
            storePreferences.setValue("phone", this.getPhone());
            storePreferences.store();   
        }   
    }
    
  4. Double-click your "save" button and input code something like this.
            try {
                this.getSessionBean1().getPortletPreferenceAdapter().setName((String)this.getTxtName().getText());
                this.getSessionBean1().getPortletPreferenceAdapter().setPhone((String)this.getTxtPhone().getText());
                this.getSessionBean1().getPortletPreferenceAdapter().save();
            } catch(ReadOnlyException proe) {
                log("Portlet ReadOnlyException=" + proe);
            } catch(IOException ioe) {
                log("IOException storing preferences=" + ioe);
            } catch(ValidatorException ve) {
                log("ValidatorException storing preferences=" + ve);
            }
    
  5. Bind your text fields on Page bean to the preferences. In the page bean add this code.
        public void prerender() {
            this.txtName.setValue(this.getSessionBean1().getPortletPreferenceAdapter().getName());
            this.txtPhone.setValue(this.getSessionBean1().getPortletPreferenceAdapter().getPhone());        
        }
    
Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

David Botterill

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today