Tuesday, July 9, 2013

Use ADF logger in ADF application


Description: 


Oracle has provided a logging mechanism in ADF, so that a developer can use this logging feature to test the ADF applications. It's basically a thin wrapper around the java.util.Logging APIs with a few simple methods and, most importantly some specific features integrated into both JDeveloper and Enterprise Manager. It's preferable to use this built-in logger for these reasons, plus it can help you avoid the kind of class-loading issues if one uses some random version of something like Log4J.
Oracle Fusion Middleware components create diagnostic log files in the Oracle Diagnostic Logging (ODL) format. Log file naming and the format of the contents of log files conform to an Oracle standard. By default, the diagnostic messages are in text format.
You can also set up the Java logger to display Java diagnostic messages. Whichever logging format you choose, you can set several levels of logging to control the level and number of messages that are displayed.
You configure the logging session by editing the logging.xml file using the overview editor for Oracle Diagnostic Logging Configuration. You can set the logging level for both persistent and transient loggers and declare handlers for each logger. Logging configuration can be set at any time, even while the application is running in JDeveloper.

After you have created a log, you can view and filter the log messages with the Oracle Diagnostic Log Analyzer. This tool allows you to set filters for different log levels, define message time frames, and search on message text.

Configuration Steps :

Open logging.xml file :


  • In the Application Server Navigator, right-click IntegratedWebLogicServer and choose Configure Oracle Diagnostic Logging for server name.



  • Or, from the Log window Action menu, select Configure Oracle Diagnostic Logging.






  • In the overview editor, click the Overview tab, select ODL Log Levels or Java Log Levels for the logger types you want to view.



  • So what we see here is a hierarchy of all the packages in the running app server. Notice that some of the icons are green, these are packages or classes that have a presence in the logging.xml already and some are yellow. These latter groups are transient, that is, we can temporarily set up logging on that package or class for the duration of the application server, but once the application server shuts down, the entire logging configuration will be reverted. You'll notice the checkbox at the top of this screen that is labeled Hide Transient Loggers if you want to see persistent loggers only, select Hide Transient Loggers.

Setting up logging level: 

  • You can use the overview editor for Oracle Diagnostic Logging Configuration to configure the logging levels specified in the logging.xml file. The file can be configured before and while the application is running in Integrated WebLogic Server. The changes will apply without the need to restart the server.
  • When Integrated WebLogic Server is running, you can define both persistent and transient loggers. When the Integrated WebLogic Server is not running, you only can define persistent loggers. The transient loggers will last only for the session and will not be entered in logging.xml. If the server is not running, you must explicitly save the configuration changes to logging.xml for the updates to take effect in the next server run.



  • To set level of a package or class just expand the corresponding package or class, go to the level column drop down the list and select the required level.
  •  Now this class or package will show this level of message. If a package has a level set then all the sub package and classes under that package will show the same level of messages.

Add new logger :
  • To add a logger.
    1. If the server is running, click the add icon dropdown menu, and choose add persistent logger or add transient logger . If the server is not running, click Add to add a persistent logger. You cannot add a transient logger.
    2. In the Add Logger dialog, enter a logger name.
    3. Select the logging level.
    4. Click OK.
  • As well as the logging levels it is also possible to configure the handlers. In logging, the handler is the thing that takes your log message and does something with it - prints it to the console, writes it to a file etc. If you select the root logger in the editor here you will see that it defines three handlers listed in the Handler Declaration section of the screen at the bottom of the editor:
    • odl-handler
    • wls-domain
    • console
  • The first two would be the default for a standalone WLS instance, but the console we've automatically added for you in the case of the embedded WLS so that you will be able to see the output of your carefully placed logging commands in the log window of the IDE.
Logging.xml file

These changes are done from JDeveloper IDE in logging,xml file, which resides in following location:

C:\Documents and Settings\username\ApplicationData\JDeveloper\latest_system_ folder\DefaultDomain\config\fmwconfig\servers\DefaultServer


These customizations in xml file looks like :

<loggers>
      <logger name="oracle.adf" level="INFO"/>
      <logger name="oracle.adf.faces" level="FINE"/>
      <logger name="oracle.adf.controller" level="INFO"/>
      <logger name="oracle.bc4j" level="INFO"/>
      <logger name="oracle.adf.portal" level="INFO"/>
      <logger name="oracle.vcr" level="INFO"/>
      <logger name="oracle.portlet" level="INFO"/>
      <logger name="oracle.adfinternal" level="INFO"/>
      <logger name="oracle.adfdt" level="INFO"/>
      <logger name="oracle.adfdtinternal" level="INFO"/>
</loggers>

Use of ADF Logger


  • Using logger for model configuration :
  1. In the Application Navigator, double-click the user interface project.
  2. In the Project Properties dialog, click the Run/Debug/Profile node and create a new run configuration.
  3. In the Run Configurations list, double-click the new run configuration to edit its properties.
  4. In the Edit Run Configuration dialog, for Launch Settings, enter the following Java options for the default virtual machine: 
  5. -Djbo.debugoutput=adflogger
  6. This option will now pick the settings from logging.xml file.

  • Using Logger for java classes
    • First define the logger itself - usually a static variable in a particular class - for example one of your managed beans:
    private static ADFLogger _logger = 
                ADFLogger.createADFLogger(MainPageBackingBean.class); 
    
    • • Next, throughout your code you can sprinkle logging statements at various levels which are (I hope) fairly self explanitory, for example in this constructor:
    public MainPageBackingBean() {
            super();
            _logger.info("Creating a new instance");
            if (BindingContext.getCurrent() == null) {
                _logger.warning("Injected Data-Binding Reference is null");
            } else {
                try {
                    doSomethingComplex();
                } catch
                weirdAppException waex;
                {
                    _logger.severe("Unexpected exception doing complex thing",
                                   waex);
                }
            }
        }
    
    
    • As you can see we generally just pass a String message to the logger, although in the error case we can pass a throwable exception as well. You can also grab your Strings from a resource bundle, rather than hardcoding them. This probably makes sense for error messages but may be overkill for programmers eyes only messages. To grab the resource bundle you simply call the getFormattedMessage() function on the logger, or you can also get hold of the resource bundle that it references using getResourceBundle().
    _logger.severe(_logger.getFormattedMessage("errors.db_connection")); 
    
    • Where the resource bundle contains something like:
    errors.db_connection=Unable to establish connection with database!
    
    • You can pass parameters to inject into the resource string as well
    • The final thing to mention in this posting was the use of guard conditions. Although logging calls themselves are cheap if logging is not enabled, you may actually need to do quite a lot of work to prepare the stuff you want to log. For example, I have a standardized method that I use as a Task Flow Initializer to dump out the contents of the PageFlowScope for that taskflow. That's a pretty expensive operation so you want to bypass that whole thing if you know that every single log message within it will be ignored.
    • Therefore you can use the isLoggable() method to wrap the whole thing. Here's the example:
    public void diagnosticInitializer() {
            //Only do the work if we need to
            if (_logger.isLoggable(Level.INFO)) {
                AdfFacesContext actx = AdfFacesContext.getCurrentInstance();
                FacesContext fctx = FacesContext.getCurrentInstance();
                //Gather key information to dump
                String windowName =  actx.getWindowIdProvider().getCurrentWindowId(fctx);
                String viewPort = ControllerState.getInstance().getCurrentViewPort().getClientId();
                Map pageflowScopeMap = actx.getPageFlowScope();
    
                _logger.info("TaskFlow Diagnostics for " + viewPort);
    
                if (!pageflowScopeMap.isEmpty()) {
                    Iterator mapIter = pageflowScopeMap.entrySet().iterator();
                    while (mapIter.hasNext()) {
                        Map.Entry entry = (Map.Entry)mapIter.next();
                        String varKey = entry.getKey().toString();
                        Object varValue = entry.getValue();
                        String varClass = "n/a";
                        if (varValue != null){
                            varClass = varValue.getClass().getName();
                        }
                        StringBuilder bldr = new StringBuilder();
                        Formatter formatter = new Formatter(bldr, Locale.US);
                        formatter.format("Key:\"%s\" Value:\"%s\" Type:[%s]", varKey, varValue, varClass);                    
                        _logger.info(bldr.toString());
                    }
                } else {
                    _logger.info("No PageFlowScope associated with this TaskFlow instance");
                }
            }
        }