ADF: simple EL expression to a method with params on a bean

3

Based upon an old blogpost of Lucas “How to call methods from EL expressions- pre JSP 2.0 trick for JSPs with JSTL” I’ve created an ADF bean with a method that accepts params which you can call with a EL expression. In this example I’ve created my own SecurityBean, so you can write EL expressions like “#{securitybean.isUserInRole['KING,ADMIN']}”. Of course you can apply this concept to each bean you want to.

The idea is pretty simple. Use an innerclass that implements the getObject method of the map interface with your specific argument method and in your bean return an instance of this innerclass on the method with a readable and sensible name.

(the blog of Lucas explains why to use a class with a map interface).

Below an example of a ADF security bean that implements the method isUserInRole and accepts as argument a csv string containing roles:

package amis.view.security;

import java.io.IOException;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class SecurityBean {
   
    private final UserRoleMap userRoleMap = new UserRoleMap();
   
    public SecurityBean() {
    }

    public String getUserName(){
        ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
        if (ectx != null){
            if (ectx.getUserPrincipal() != null){
                return ectx.getUserPrincipal().getName();
            }
            else{
                return "No User Principal";
            }
        }
        else{
            return "No External Context";
        }
    }
   	   
    public UserRoleMap getIsUserInRole(){
        return userRoleMap;
    }

    public String logout() throws IOException {
        ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
        HttpServletResponse response = (HttpServletResponse)ectx.getResponse();
        HttpSession session = (HttpSession)ectx.getSession(false);
        session.invalidate();
        // redirect is with regard to current page       
        // if we want to use an absolute path (starting with /), then we have        
        // to include the context root such as SecureWebApp-SecureApp-context-root       
        response.sendRedirect("test.jspx");
        return null;
    }


    public static final class UserRoleMap implements Map {
        private UserRoleMap() {
            super();
        }
        public int size() {
            return 0;
        }
        public boolean isEmpty() {
            return false;
        }
        public boolean containsKey(Object key) {
            return true;
        }
        public boolean containsValue(Object value) {
            return true;
        }

        public Object get(Object roles) {
            String[] roleArray = ((String)roles).split(",");
            for (int i=0; i < rolearray.length; i++){
              String role = roleArray[i];
              if (FacesContext.getCurrentInstance().getExternalContext().isUserInRole(role)){
                return true;
              }
            }
            return false;
        }

        public Object put(Object key, Object value) {
            return null;
        }
        public Object remove(Object key) {
            return null;
        }
        public void putAll(Map m) {
        }
        public void clear() {
        }
        public Set keySet() {
            return Collections.emptySet();
        }
        public Collection values() {
            return Collections.emptySet();
        }
        public Set entrySet() {
            return Collections.emptySet();
        }
    }
   
}

Example of usage in a test welcome adf page that displays the rolls of the user:

<f:view>
  <af:document id="d1" title="Welkom">
    <af:form id="f1">
      <af:panelformlayout id="pf1">
        <af:outputformatted id="of1" value="Welcome! - Logged in as #{securitybean.userName}"/>
        <af:outputformatted id="of2" value="King" 
                            rendered="#{securitybean.isUserInRole['KING']}" />
        <af:outputformatted id="of3" value="User" 
                            rendered="#{securitybean.isUserInRole['USER']}" />
        <af:outputformatted id="of4" value="SubUser"
                            rendered="#{securitybean.isUserInRole['SUBUSER']}" />
        <af:outputformatted id="of5" value="Admin" 
                            rendered="#{securitybean.isUserInRole['ADMIN']}" />
        <af:outputformatted id="o6f" value="SubUser, King or Admin" 
                            rendered="#{securitybean.isUserInRole['SUBUSER,KONING,ADMIN']}" />
        <af:commandbutton text="Home" id="cb1" action="goHome"/>
      </af:panelformlayout>
    </af:form>
  </af:document>
</f:view>

 

 

Share.

About Author

Emiel is a senior Java & SOA consultant at AMIS, Nieuwegein (The Netherlands).

3 Comments

  1. Thanks for the example.  What changes are required to the faces-config.xml file to have the bean available at runtime?

  2. I agree, but I just wanted to explain how you can pass params to a session bean by using an inner class, so you class model is not polluted with ‘strange map interface’ classes which are only used within a certain bean. Maybe I better should have chosen for other functionality then checking on security roles.

  3. If this is ADF 11g then this functionality is all available on the security context anyway and if this is 10g then this already exists in the form of the JSFSecurity project on SourceForge which does exactly the same kind of thing.
    Just an FYI