Pages

Tuesday, February 18, 2014

Hide move all/remove all buttons from SelectManyShuttle component


In this post, I will share how to hide move_all / remove_all buttons using skinning. With no additional skinning SelectManyShuttle component looks like this :



Now to hide move_all / remove_all buttons, define a style class on shuttle component like this



Now add the below code to your skin file and you are done.


New look for Shuttle component after skinning change :



Enjoy :)

Accessing Messages From Resource Bundle


Accessing Messages from Resource Bundle


1. Passing Parameters to Messaages from Resource Bundle in PageFragment

At times there are requirements to show messages like : 'Entered email Address "xyz@gmail.com" is not valid' . 
There are different ways to achieve this:
a. Construct a Java message dynamically - not scalable
b. Return a Bean message - makes a trip to the bean everytime
c. Break the string to different strings and join them dynamically - Doesn't support internationalization

Correct way for implementing above would be : 
1. Create an entry in resourceBundle of your application like this 
    EMAIL_ADDRESS_INVALID=Entered email Address {EMAIL_ADDRESS_TOKEN} is not valid.
2. Now use below tag to show message :
   requiredMessageDetail="#{af:formatNamed(viewcontrollerBundle.EMAIL_ADDRESS_INVALID,'EMAIL_ADDRESS_TOKEN', pageFlowScope.EmployeeBean.emailAddress)}"
 where emailAddress is a property in pageFlowScope EmployeeBean holding the value of EmailAddress.
           EMAIL_ADDRESS_TOKEN is the parameter for which value is passed.
Note: 
a. af:format, af:format1, af:format2, af:format3, af:format4 can be used to send parameters to the messages. The number in the af:format denotes the  number of tokens it accepts
b. af:format can accept 1 parameter

2. Passing Parameters to Messages in Resource Bundle and accessing from Managed Bean

At times you write custom Validator method for input fields or do some other kind of validations in actionListener before calling service or calling commit. In case of some validation failure, it is common tendency to add error messages or return validation message from bean as a hardcoded String. For example see below code in custom Validator :

if (!matcher.matches()) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Entered email Address "+getEmailAddress()+" is not valid",null );

It is not good practice to use hardcoding for errorMessaage as String. Rather one should create entry in Resource Bundle and then fetch it in Bean for adding any validation message.

Steps to implement in correctly : 
1. Create an entry in resourceBundle of your application like this 
    EMAIL_ADDRESS_INVALID=Entered email Address {EMAIL_ADDRESS_TOKEN} is not valid.
2. Create below methods in your utility class ( ADFUtils.java )

import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import oracle.javatools.resourcebundle.BundleFactory;
import oracle.javatools.resourcebundle.NamedMessageFormat;
import javax.faces.context.FacesContext;

public static final String Missing_Resource_Msg = "No Message Found";
    /**
     * @param bundlePath
     * @return
     */
    private static ResourceBundle getBundle(String bundlePath) {
        Locale locale =
            FacesContext.getCurrentInstance().getViewRoot().getLocale();
        return BundleFactory.getBundle(bundlePath, locale);
    }


    /**
     * @param bundlePath
     * @param messageKey
     * @return
     */
    public static String getStringFromBundle(String bundlePath,
                                             String messageKey) {
        ResourceBundle rsBundle = getBundle(bundlePath);
        String bundleKeyValue;
        try {
            bundleKeyValue = rsBundle.getString(messageKey);
        } catch (MissingResourceException mrExp) {
            bundleKeyValue = Missing_Resource_Msg;
        }
        return bundleKeyValue;
    }

    /**
     * @param bundlePath
     * @param messageKey
     * @param tokenMap
     * @return
     */
    public static String getStringFromBundle(String bundlePath,
                                             String messageKey,
                                             Map<String, Object> tokenMap) {
        ResourceBundle rsBundle = getBundle(bundlePath);
        String message;
        try {
            message = rsBundle.getString(messageKey);
        } catch (MissingResourceException mrExp) {
            message = Missing_Resource_Msg;
        }

        if (tokenMap != null && !tokenMap.isEmpty() &&
            !Missing_Resource_Msg.equalsIgnoreCase(message))
            message = NamedMessageFormat.formatMsg(message, tokenMap);
        return message;
    }

3. Now in you managedBean you can change your validation exception code like this : 
    private static final String bundlePath =
        "test.rc.com.ViewControllerBundle";
Map tokenMap = new HashMap();
// Add a token with Key as token or parameter Name and value is the parameter Value
tokenMap.put("EMAIL_ADDRESS_TOKEN",getEmailAddress());
String errorMessage = ADFUtils.getStringFromBundle(bundlePath,
                                  "EMAIL_ADDRESS_INVALID", tokenMap);
// errorMessage String is retrieved from Resource Bundle and passing parameter in Message
if (!matcher.matches()) {
            throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    errorMessage ,null );

 
That's it.. We are done ....Enjoy