1

We are getting ready to move our JSF 2 (MyFaces with Facelets pages) application to Production soon. Currently our console logs (SystemOut.log on WebSphere v8) are filling up with vast amounts of these kinds of messages:

[3/26/13 16:42:33:744 CDT] 00000031 HtmlImageRend W   Component UIGraphic Form:errorIconSave has no attribute alt or attribute resolves to null. Path to component {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /view/groupagreement/products/volumebased/VolumeBasedProducts.xhtml][Class: javax.faces.component.html.HtmlBody,Id: commonLayoutId][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id1364021679_785179b][Class: javax.faces.component.html.HtmlForm,Id: Form][Class: javax.faces.component.html.HtmlBody,Id: j_id363369746_1d362e8b][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id363369746_1d362e61][Class: org.richfaces.component.UIRegion,Id: j_id363369746_1d362e4a][Class: org.richfaces.component.UIPopupPanel,Id: confirmationPopUpForWayFinder][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id363369746_1d362ffd][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id363369746_1d362fbc][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id363369746_1d362f9a][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id363369746_1d362f70][Class: javax.faces.component.html.HtmlGraphicImage,Id: errorIconSave]}
[3/26/13 16:42:33:746 CDT] 00000031 HtmlResponseW W   HTML nesting warning on closing div: element td rendered by component : {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /view/groupagreement/products/volumebased/VolumeBasedProducts.xhtml][Class: javax.faces.component.html.HtmlBody,Id: commonLayoutId][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id1364021679_785179b]} not explicitly closed

We feel this excessive logging may be hurting performance. While we understand that we should have coded our application propertly to html spec, it was delivered by an offshore vendor and we did not have as much control over the quality of the code as we'd like. At this point we probably don't have time to fix all the xhtml files (adding alt attribute to images, etc.).

Is there any way we can disable this logging? For example a web.xml context param? I could not find anything in MyFaces documentation.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Michael Lucas
  • 733
  • 1
  • 8
  • 23
  • I should note, we are using slf4j with log4j implementation. To get control over MyFaces logging, do we need to redirect java.util.logging to slf4j as per some of the answers in [this myfaces question](http://stackoverflow.com/questions/8012595/tomcat-logging-with-slf4j-and-log4j)? – Michael Lucas Mar 26 '13 at 22:04
  • On further investigation, it seems that SLF4J's jul-to-slf4j bridge is not what we want, because it impacts performance even when logging statements are turned off. (see the [performance note here](http://www.slf4j.org/legacy.html#jul-to-slf4j)) – Michael Lucas Mar 27 '13 at 16:08

2 Answers2

2

I was able to solve this myself.

I looked into the source code for the MyFaces components that were generating these warnings (e.g. grepcode source link for HtmlResponseWriterImpl). From the source it's pretty obvious that there is no other configuration parameter being checked before printing these warnings. But of course the java.util.logging levels are being checked. So the solution is simply to configure java.util.logging (aka jul or jdk logging) to suppress warnings from these components.

I could have tried to configure the jdk logging configuration file in our WebSphere instance, but this is a much more difficult change to deploy & manage in our production environment (shared infrastructure, locked down servers). So I ended up using a java solution - a class that I register as a Spring bean, whose init method changes the logging level of the logger names it's provided:

<bean id="setJdkLoggingToSevere" class="ca.mycompany.myapp.util.JdkLoggingLevelConfigurer" init-method="init">
    <property name="level" value="SEVERE" />
    <property name="loggerNames">
        <list>
            <value>org.apache.myfaces.shared.renderkit.html.HtmlResponseWriterImpl</value>
            <value>org.apache.myfaces.renderkit.html.HtmlImageRenderer</value>
            <value>org.apache.myfaces.renderkit.html.ext.HtmlImageRenderer</value>
            <value>org.apache.myfaces.shared.renderkit.html.HtmlImageRendererBase</value>
            <value>org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlImageRendererBase</value>
            <value>org.apache.myfaces.renderkit.html.HtmlLabelRenderer</value>
            <value>org.apache.myfaces.renderkit.html.HtmlGridRenderer</value>
            <value>org.apache.myfaces.renderkit.html.ext.HtmlGridRenderer</value>
            <value>org.apache.myfaces.shared.renderkit.html.HtmlGridRendererBase</value>
            <value>org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlGridRendererBase</value>
            <value>org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils</value>
            <value>org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils</value>
        </list>
    </property>
</bean>

Here's the relevant method from my JdkLoggingLevelConfigurer class (note myLogger is a slf4j logger, since slf4j is my application's logging framework):

public void init() {
    if (this.getLoggerNames() != null) {

        Level level = Level.parse(this.getLevel());

        for (String loggerName : loggerNames) {
            Logger logger = Logger.getLogger(loggerName);
            if (logger != null) {
                myLogger.info("setting jdk logging for {} to {}", loggerName, level);
                logger.setLevel(level);
                this.loggers.add(logger);
            }
            else {
                myLogger.warn("unable to set jdk logging for {} to {} because logger was null",
                        loggerName, this.getLevel());
            }
        }
    }
}

With the above in place, we no longer see the warning messages. And if I missed any myfaces components that do emit warnings (I initially did miss some), they can easily be added to the spring configuration.

Michael Lucas
  • 733
  • 1
  • 8
  • 23
0

In HtmlImageRendererBase the JUL logger is used, so simply add a file logging.properties to your classpath including the following line:

org.apache.myfaces.shared.renderkit.html.HtmlImageRendererBase.level = SEVERE
Florian Sager
  • 660
  • 8
  • 14
  • On a shared server "adding a file to the classpath" is not necessarily as simple as it sounds. Would it work to include the file in my WAR's WEB-INF/classes directory? If so, that would not conflict with other applications on the server, and would be a good solution. (Of course I would need to add several lines to the logging.properties -- many Renderer classes as per my solution below.) – Michael Lucas Oct 08 '13 at 14:16
  • Ok, understood: in my environment it's sufficient to add this entry to the logging.properties in WEB-INF/classes - but I can't tell if this would work in a shared server. – Florian Sager Oct 09 '13 at 15:11