Pages

Thursday, December 18, 2014

Recover Missing Firefox icon..

Multiple times ...firefox seems to loose it's icon... and it looks real bad. I did some google and found this link : http://www.heerengandhi.com/2009/07/29/firefox-icon-went-missing-in-windows-7-heres-a-fix/comment-page-1/

Just copy paste of the instructions for my reference..and anyone else reading.

Follow these directions:
  1. Close all folder windows that are currently open.
  2. Launch Task Manager using the CTRL+SHIFT+ESC key sequence, or by running taskmgr.exe
  3. In the Process tab, right-click on the Explorer.exe process and select End Process
  4. Click the End process button when asked for confirmation.
  5. From the File menu of Task Manager, select New Task (Run…)
  6. Type CMD.EXE, and click OK
  7. In the Command Prompt window, type the commands one by one and press ENTER after each command:
    CD /d %userprofile%\AppData\Local
    DEL IconCache.db /a
    EXIT
  8. In Task Manager, click File, select New Task (Run…)
  9. Type EXPLORER.EXE, and click OK.

Your icons should be as good as new!

Handling Ok Cancel action on Uncommited warning popup

Handling Ok Cancel action on Uncommited warning popup

There are couple of post which covers how to show uncommitted data warning popup. So I will not go in details for that, rather we will cover how to handle ok cancel action on uncommited data warning popup.

Few references for, how to show  uncommitted data warning popup : 
http://www.oracle.com/technetwork/testcontent/unsaveddatawarning-096556.html
http://www.awasthiashish.com/2012/10/uncommitedunsaved-data-warnig-on-page.html

Select af:document from page structure and go to property inspector, now set UncommitedDataWarning to on.

Before starting with implementation, I would like to refer the information found on OTN forum : 
https://community.oracle.com/message/10982006#10982006

From looking at the design specs, uncommitted data warning is a combination of ADF view and ADFc functionality. Good news is that - at least by the specs - a dirty transaction in a region should be automatically detected. The class that handles the uncommitted data warning is AdfcDirtyPageHandler. This class is registered in a text file "oracle.adf.view.rich.context.DirtyPageHandler". So if this works as with how you change the ADFc exception handler, then its by a file with this name in the application META-INF/service folder (the latter doesn't exist by default). Note that "AdfcDirtyPageHandler" is in an internal package, which means its not supported to extend it. However, the default abstract class is DirtyPageHandler and this is in a public package. 
From the Java docs:
META_INF/services-based application-scoped object for tracking whether navigation will result in data loss.  Only a single implementation may be registered per application. Registering multiple implementations will result in an IllegalStateException at applciation initialization. If no implementation is registered, a default implementation will be used. That implementation will always return false from isDataDirty and will do nothing in response to a trackNavigation call.
Maybe worth filing an ER to get a public listener / hook into this instead of dealing with your own implementation. Will file one

To handle ok cancel action on uncommitted data warning popup : 

1. Create a text file with name "oracle.adf.view.rich.context.DirtyPageHandler" under folder structure :
    TestApp/.adf/META-INF/services/



2. Create a java class CustomDirtyPageHandler which extends "AdfcDirtyPageHandler".

public class CustomDirtyPageHandler extends AdfcDirtyPageHandler 

3. Update the file "oracle.adf.view.rich.context.DirtyPageHandler" created in step1 with the name of custom handler ( full package path ).




4. Now you are good to write your logic in CustomDirtyPageHandler java class.  In sample code below, Rollback is executed on OK action. Make sure that Rollback binding is available in pageDef of jspx.


Ignore the below warning/error : 





Enjoy!!!


Wednesday, December 17, 2014

Scroll to top on Commit or Rollback

Scroll to top on Commit or Rollback

This post is about scrolling to some component on user action. Mostly when user click save or cancel, a message is displayed on top of the page. At the same time, it is required to scroll the page to top and show message to the user... rather user scrolling up to see what happened. 

Implementation is simple : 

1. Need a javascript method to scroll.

2. Next step is just to invoke this javascript method at the end of your commit call.


Enjoy!!

Calling JavaScript from ManagedBean

Calling JavaScript from ManagedBean

Often there are requirements to call the invoke javascript from actionListener to set focus or scroll etc. Here goes the code to invoke javascript : 


Enjoy !!!

Monday, November 24, 2014

Invoke Bindings from PageTemplate PageDef

Invoke Bindings from PageTemplate PageDef

There are scenarios when certain method binding in pageTemplate's pageDef needs to be invoked from some button Action in page. Here are the details :

1. For page based on the pageTemplate, there will be reference of pageTemplate's PageDef created in page's pageDef.



2.  Now in order to access bindings in pageTemplate's pageDef, refer below code. Enjoy!!!

Thursday, November 20, 2014

Show exceptions caught in Managed Beans

There are couple of scenarios when some exception is caught while executing some logic in managed bean. The post is about how to show those exceptions to user and when it is required to do it explicitly.

For most of the scenarios, ADFm Error Handlers shows the message. But in case when some exception occurs in managedBean, it can be caught and reported to ADFm Error Handler using below code.

BindingContext bctx = BindingContext.getCurrent();
   ((DCBindingContainer)bctx.getCurrentBindingsEntry()).reportException(ex);

Note : Using the ADF model error handling for displaying exceptions thrown in managed beans require the current ADF Faces page to have an associated PageDef file (which is the case if the page or view contains ADF bound components).

Sample App is uploaded here. Following scenarios are covered  :

Scenario Description Button Text in Sample App Requires Explicit Handling to show messaage to User
1 Drag and Drop AM Method on Page as command Button throwJboExceptionFromAM No
2 Call AM method in Bean method through bindings Call throwJboExceptionFromAM in Bean through Bindings No. By default, all exception are handled by ADFm Error Handler when calling AMMethod through bindings. When you check for exception in operationBinding and report it expliclity .. It is basically duplicating the message
3 throw an exception in ActionListener ThrowingExceptionInActionListener Yes. See the button in section Handled and it's actionListener. How the exception is reported .


Enjoy !!!

Friday, November 14, 2014

Setting Button Action from ActionListener

Control the button Action based on the logic inside ActionListener 

 This post talks about how to control the button Action based on the logic inside ActionListener. Lets say there is a commandButton "Go to View2" on pageFragment "View1" . On Click of this button conditionally a navigation is required. Here goes the code :

That's all ..enjoy.


Tuesday, November 11, 2014

SelectBooleanCheckbox with [Y, N] values using a custom converter

How to show selectBooleanCheckbox with [Y,N} values using a custom converter.

So first we need a converter which converts [Y,N] to [true, false] and viceversa. Here goes the converter code :-


Converter needs to be declared in faces-config.xml ..

Next goes the code snippet showing usage of our converter in selectBooleanCheckbox.


Enjoy!!

Wednesday, October 15, 2014

Retain current row after Rollback or refresh

It is very common requirement to retain the current row on rollback or after executing VO. To retain the current Row, first get the current Row key and then call rollback. Now you have the rowKey to set the currentRow again.

Tuesday, September 30, 2014

Show Faces Message using JavaScript in ADF Faces

How to show faces Message using javaScript in ADF Faces


I have read this on Ashish Awasthi's blog. So if you want to read full detail sample refer to his blog.

For reference purpose, I am putting two lines of code here :

// Clear all validation message 
AdfPage.PAGE.clearAllMessages();

//Invoke FacesMessage
AdfPage.PAGE.addMessage('it1', new AdfFacesMessage(AdfFacesMessage.TYPE_ERROR, "Invalid Value", "Enter Characters Only"));


Other valid types are : TYPE_ERROR, TYPE_INFO, TYPE_WARNING, TYPE_FATAL .

Enjoy !!

Friday, September 26, 2014

WebProxy - Log Request and Response xml to console

How to view the request and response xml for a webservice call made using webProxy.


To see the soap request and response we can set a JAX-WS parameter. 
"-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true"  ,this will dump the data in your console output.

Edit the Run/Debug Profile for the project and then run it . See the screenshot for more details : 





You can also write a SOAP logging handler ....will be covered in future posts.

Enjoy...

Tuesday, September 9, 2014

Groovy : Posted Attribute Value using groovy

How to get the posted attributeValue using Groovy .

 To expose old value of entity objects, follow steps below :

1.  Create transient attribute "OLD_SALARY" in Entity Object.
2. Make sure that "Persistent" and "Derived From SQL Expression" properties are turned off.
3. Set the "Value Type" to Expression and enter the following Groovy expression into the Value field:

adf.object.getPostedAttribute(adf.object.getAttributeIndexOf(model.EmployeesImpl.SALARY))

That's it... Now  old salary attribute holds the value of salary retrieved from database. If required same attribute can be used in viewObject ...

Enjoy.

Tuesday, August 5, 2014

Uploading Large Files to UCM - af:inputFile Component

This post covers uploading large files to UCM using inputFile Component.

JDeveloper Version : Studio Edition Version 11.1.1.7.0

Recently I was working with af:inputFile Component trying to upload files to UCM. I hit an issue when trying to upload files larger than 2MB. I am going to share my findings :

1. InputFile component gets stuck if trying to upload large file... and it doesn't even allow to select other small file once it is stuck. I searched google and found this :

Andrejusb Blog - Oracle UCM 11g uploading large files


Set this parameter "org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE" = 20971520 in  web.xml for upload up to 20 MB.{ maximum file upload size to 20971520 bytes, or divided by 1024 and one more time by 1024 - 20 MB }

2. Now again question is - what happens after that 20MB file ... inputFile Component gets stuck. Further digging found that it is component bug and patch is available.

Dowload and apply Patch : 15931140 

Enjoy !!

Wednesday, May 28, 2014

Error Message html formatting

How to apply HTML formatting to error message

In my earlier post, I explained how to show error messages programmatically. This post covers how to apply HTML formatting to error messages. Credits to Ashish Awasthi's blog for this one. 




Enjoy...

Monday, March 31, 2014

Showing Error Message programmatically

How to show error message programmatically


ADF Faces uses the standard JSF messaging API. JSF supports a built-in framework for messaging by allowing FacesMessage instances to be added to the FacesContext object using the addMessage(java.lang.String clientId, FacesMessage message) method. 

Error Message can be shown inline using af:messages and setting inline property to false.

Code to show error Message :

Following types of error messages can be shown : 


Component-Level Message : 
These messages are associated to a specific component based on the clientID parameter passed to addMessage method. 

Global-Level Message : 
These messages are not associated to any component and null is passed for clientID parameter to addMessage method. 

Sample app can be download from here Enjoy !!!

Tuesday, March 18, 2014

ADF Logging Explained Chapter 4

ADF Logging Explained Chapter 4

In this post, we tried to cover the commonly used methods of ADFLogger class.

Now I create ADFLogger instance and try to log a message using belowCode : 

private static ADFLogger logger = ADFLogger.createADFLogger(TestLoggerTFBean.class);
logger.log("Logging Message1");

After running the application, I set the LogLevel of my custom ADFLogger to Warning. Now lets see the logged message ...it's not there. Why ? We created ADFLogger instance... logged the message ... set the LogLevel ... and no message Logged. 

Almost all logging methods internally does a check isLoggable before logging. The above logger.log method checks isLoggable(ADFLoggerLevel.TRACE) and which return false because our custom ADFLogger's LogLevel is Warning. 

Lesson Learnt : Information about internal LogLevel check is required before using any log method.

Well not to worry... other log methods are straight forward. Here are some examples : 

logger.severe(String msg)  - This checks isLoggable against Level.Severe.
logger.fine(String msg)  - This checks isLoggable against Level.Fine.
logger.log(Level level, String msg) - This check isLoggable against inputParameter level before logging.


That's it. Enjoy logging.

If you want more than this, please go Adventures in Logging index by Duncan Mills. 

Monday, March 10, 2014

ADF Logging Explained Chapter 3

ADF Logging Explained Chapter 3

This post illustrates ADFLogger initialization concepts.

First thing you create the ADF Logger instance using below code  :

  private static ADFLogger logger = ADFLogger.createADFLogger(TestLoggerTFBean.class);

Log Level for newly Created Instance

I ask you a very simple question : Say you have not done any additional change to Oracle Diagnostic Logging. That is it looks like this :


Now What is the logLevel for the above ADFLogger instance "logger" ?

Answer is LogLevel is null.

How isLoggable(Level level) check works on logger instance with LogLevel null ?


Ahh...Now we know that LogLevel is null for a newly created ADFLogger instance when it is not configured in OracleDiagnostic Logging.  Wondering what will happen to code comparing LogLevel before logging any info ?  Like :

        if(logger.isLoggable(ADFLogger.INTERNAL_ERROR)){
            logger.log("loggingBtnAction logger.isLoggable(ADFLogger.INTERNAL_ERROR) -> logger.log ");
        }

Well ADFLogger is based on java.util.logging.Logger and isLoggable method works on class variable levelValue [ private volatile int levelValue ] defined in java.util.logging.Logger . When a new ADFLogger instance is created, levelValue variable is update using the below logic :
So if LogLevel for logger is null it means that logLevel is inherited from the parent. As the logger build a tree, it picks the logLevel of parent till it reaches the logger which returns a level not null.

From java.util.logging.Logger
private volatile int levelValue;  // current effective level value

Thanks to Timo Hahn for clarifying this on https://community.oracle.com/thread/3524267




Thursday, March 6, 2014

ADF Logging Explained Chapter 2

Logging in ADF Application

 
For ADF Logging Explained Chapter 1, click here. This post describes Logging Levels.

Why there is need to learn Logging levels ?
When adding logger to Oracle Diagnostic Logging, there is option to define the loggingLevel for that Logger. Switching the logging Level in Oracle Diagnostic Logging for our custom Logger, you can control the level of details logged. Too much of logging can also cause performance issue. Decision of logging an information is taken based on the intValue comparision ( more details explained in later section ).


 A logging Level is defined using name,intValue and resourceBundleName. The resource bundle name to be used in localizing the level name so for now we will focus on name and intValue. There are some predefined Levels mentioned in java.util.logging.Level class.
 
LOG LEVEL NAME INT VALUE
OFF OFF INTEGER.MAX_VALUE
SEVERE SEVERE 1000
WARNING WARNING 900
INFO INFO 800
CONFIG CONFIG 700
FINE FINE 500
FINER FINER 400
FINEST FINEST 300
ALL ALL Integer.MIN_VALUE
 
Other logging Level types are custom levels defined using java.util.logging.Level with new name and API. 

Logging Levels defined in ADFLogger :

LOG LEVEL NAME INT VALUE
INTERNAL_ERROR INTERNAL_ERROR 1100
ERROR SEVERE 1000
WARNING WARNING 900
NOTIFICATION INFO 800
TRACE FINE 500
 
Other Logging Levels :
A) ODL Log Level
B) JAVA Log Level
C) Weblogic Server

 
 Here is detailed list of different logging levels and there comparision :



ODLWebLogic ServerJava
OFFOFF2147483647 - OFF
INCIDENT_ERROR:1(EMERGENCY)1100
INCIDENT_ERROR:4EMERGENCY1090
INCIDENT_ERROR:14ALERT1060
INCIDENT_ERROR:24CRITICAL1030
ERROR:1(ERROR)1000 - SEVERE
ERROR:7ERROR980
WARNING:1WARNING900 - WARNING
WARNING:7NOTICE880
NOTIFICATION:1INFO800 - INFO
NOTIFICATION:16(DEBUG)700 - CONFIG
TRACE:1(DEBUG)500 - FINE
TRACE:1DEBUG495
TRACE:16(TRACE)400 - FINER
TRACE:32(TRACE)300 - FINEST
TRACE:32TRACE295



Now you know about different available logging Level Types and their values. It is very much clear from the level names ALL and OFF that more and more detailed logging will happen with decrease in logging level int Value.





 

ADF Logging Explained Chapter 1

Logging in ADF Application


This post talks about using ADFLogger in adf application. The ADFLogger is a logging mechanism which is built into the ADF framework. It is built on top of java.util.logging API.

Using ADFLogger :

To start with you need to define the ADFLogger instance in your class ... something like below code :


public class TestLoggerTFBean {
    public TestLoggerTFBean() {
        super();
    }
    private static  ADFLogger logger = ADFLogger.createADFLogger(TestLoggerTFBean.class);

There are additional methods available in ADFLogger API to create ADFLogger instance. For other methods please refer to ADFLogger JAVA API.

Where to View Available Loggers :

Run your integratedWeblogic server and choose "Configure Oracle Diagnostic Loggin" from Actions. You will able to see all available loggers in the logging.xml file.


Registering your ADFLogger :

You can register your logger by clicking green plus "+" icon in right on logging.xml. You can choose to add transient (discarded at the end of session ) logger or persistent (stored in logging.xml) logger.

OR

When you run your application, you might notice that logger gets registered as when it is initialised.
 
In the sample app provided, there are two taskflows : 1) noLogger-tf 2)testLogger-tf . An ADFLogger instance in created in pageFlowScope managed bean for testLogger-tf. Running the TestLoggerPage.jspx loads the noLogger-tf ( Not ADFLogger instance created yet ). If you notice registered loggers, our custom logger "TestLoggerBean " is still not registered.
 
Click the button to navigate to testLogger-tf taskflow. Click button "Do Some Logging" to log something. Now again check available loggers and our custom logger is available.

 
 
 
 
 
 
 

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