You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by "Awasthi, Anand" <AA...@dstbs.com> on 2013/01/07 17:42:53 UTC

custom Appender throwing error

Hi,

I have written custom  JDBCAppender to write log messages to database. I have Hello World type program to test JDBCAppender.  When I run the program, I get following error:


2013-01-07 11:37:28,753 ERROR appenders contains an invalid element or attribute "JDBCAppender"


Here is my log4j2.xml :


<?xml version="1.0" encoding="UTF-8"?>
<configuration status="trace">
  <appenders>
    <JDBCAppender name="jdbc" driver="com.mysql.jdbc.Driver"
              url="jdbc:localhost:testdb" userName="root" password=""/>
  </appenders>
  <loggers>
    <root level="trace">
      <appender-ref ref="jdbc"/>
    </root>
  </loggers>
</configuration>



And JDBCAppender code is below:

@Plugin(name = "JDBCAppender", type = "Core", elementType = "appender", printObject = true)
public final class JDBCAppender extends AbstractAppender {

                private final  Connection con;
                private final String sql;

    @SuppressWarnings("unchecked")
                private JDBCAppender(String name, Filter filter, @SuppressWarnings("rawtypes") Layout layout, Connection con, String sql, boolean handleExceptions) {
                                super(name, filter, layout, handleExceptions);
                                this.con = con;
                                this.sql = sql;
}

    public void append(LogEvent event) {
        try {

        Statement stmt = con.createStatement();
            stmt.execute(sql);
            con.commit();
            con.close();
        } catch (Exception ex) {
            throw new AppenderRuntimeException(ex);
        }
    }

    @PluginFactory
    public static JDBCAppender createAppender(@PluginAttr("url") String databaseURL,
                                                  @PluginAttr("driver") String driverName,
                                                  @PluginAttr("userName") String databaseUser,
                                                  @PluginAttr("password") String databasePassword,
                                                  @PluginElement("sql") String sql,
                                                  @SuppressWarnings("rawtypes") @PluginElement("layout") Layout layout,
                                                  @PluginElement("filter") Filter filter,
                                                  @PluginAttr("suppressExceptions") String suppress) {

        String name = "JDBC Connection Info " + databaseURL;
        boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
        Connection con = null;
        if (!DriverManager.getDrivers().hasMoreElements())
                     setDriver(driverName);
         if (con == null) {
           try {
                                                con = DriverManager.getConnection(databaseURL, databaseUser,          databasePassword);
                                } catch (SQLException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                }
         }

        if (con == null) {
            return null;
        }
        if (layout == null) {
            layout = SerializedLayout.createLayout();
        }
        return new JDBCAppender(name, filter, layout, con, sql, handleExceptions);
    }

    public static void setDriver(String driverClass) {
      try {
        Class.forName(driverClass);
      } catch (Exception e) {

      }
    }

}

Is there any other API changes or configuration needed to get Customer Appender work ?



Thanks
Anand






Re: custom Appender throwing error

Posted by Ralph Goers <ra...@dslextreme.com>.
Your JDBCAppender PluginFactory method should have a "name" parameter.  You should pass that without modification to the JDBCAppender constructor.  Your JDBCAppender should create a JDBCManager which does most of the heavy lifting.  You want to give it the name that contains the connection info.  The JDBCManager is shared across Appender instances. This allows reconfiguration without having the JDBC connection shut down.

Ralph

On Jan 7, 2013, at 10:58 AM, Awasthi, Anand wrote:

> Thanks Ralph, that error is gone but now I get following errors:
>  
> ERROR JDBC contains an invalid element or attribute "name"
> ERROR Unable to locate appender jdbc for logger
>  
> When I look at other appenders they all have name attribute in appender element so I am not sure why I am getting error message
>  
>  
> If I remove the attribute name="jdbc" then I get only following error:
> ERROR Unable to locate appender JDBC for logger
>  
>  
> Here is my updated log4j2.xml
>  
> <?xml version="1.0" encoding="UTF-8"?>
> <configuration status="trace" packages="com.dstbs.logging.log4j2.appender">
>   <appenders >
>     <JDBC name="jdbc" driver="com.mysql.jdbc.Driver"
>               url="jdbc:mysql://localhost/academic" userName="root" password="" sql="insert into exam (name, year, course, affiliation_id) values ('class XX', '2015' , 'high school', '1')"/>
>   </appenders>
>   <loggers>
>     <root level="trace">
>       <appender-ref ref="jdbc"/>
>     </root>
>   </loggers>
> </configuration>
>  
>  
> Here is what a typical console looks like
>  
>  
> 2013-01-07 13:55:10,530 DEBUG Generated plugins in 0.002802471 seconds
> 2013-01-07 13:55:10,545 DEBUG Calling createAppender on class com.dstbs.logging.log4j2.appender.JDBCAppender for element JDBC with params(url="jdbc:mysql://localhost/academic", driver="com.mysql.jdbc.Driver", userName="root", password="", sql="insert into exam (name, year, course, affiliation_id) values ('class XX', '2015' , 'high school', '1')", null, null, suppressExceptions="null")
> 2013-01-07 13:55:10,717 DEBUG Calling createAppenders on class org.apache.logging.log4j.core.config.plugins.AppendersPlugin for element appenders with params(appenders={JDBC Connection Info jdbc:mysql://localhost/academic})
> 2013-01-07 13:55:10,717 DEBUG Generated plugins in 0.000925918 seconds
> 2013-01-07 13:55:10,733 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.config.AppenderRef for element appender-ref with params(ref="JDBC", level="null", null)
> 2013-01-07 13:55:10,733 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.LoggerConfig$RootLogger for element root with params(additivity="null", level="trace", appender-ref={org.apache.logging.log4j.core.config.AppenderRef@a9ae05}, properties={}, Configuration(C:\Log4j 2.x-workspace\LOG4J2\bin\log4j2.xml), null)
> 2013-01-07 13:55:10,733 DEBUG Calling createLoggers on class org.apache.logging.log4j.core.config.plugins.LoggersPlugin for element loggers with params(loggers={root})
> 2013-01-07 13:55:10,733 ERROR Unable to locate appender JDBC for logger
> 2013-01-07 13:55:10,733 DEBUG Reconfiguration completed
>  
>  
>  
> Thanks
> Anand
>  
> From: Ralph Goers [mailto:ralph.goers@dslextreme.com] 
> Sent: Monday, January 07, 2013 12:31 PM
> To: Log4J Developers List
> Subject: Re: custom Appender throwing error
>  
> Your plugin probably hasn't been loaded.  You need to either add the package your plugin is part of to the packages attribute of the configuration element (see  http://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax) or follow the Plugin Preloading instructions at http://logging.apache.org/log4j/2.x/manual/plugins.html
>  
> Ralph
>  
> On Jan 7, 2013, at 8:42 AM, Awasthi, Anand wrote:
> 
> 
> Hi,
>  
> I have written custom  JDBCAppender to write log messages to database. I have Hello World type program to test JDBCAppender.  When I run the program, I get following error:
>  
>  
> 2013-01-07 11:37:28,753 ERROR appenders contains an invalid element or attribute "JDBCAppender"
>  
>  
> Here is my log4j2.xml :
>  
>  
> <?xml version="1.0" encoding="UTF-8"?>
> <configuration status="trace">
>   <appenders>
>     <JDBCAppender name="jdbc" driver="com.mysql.jdbc.Driver"
>               url="jdbc:localhost:testdb" userName="root" password=""/>
>   </appenders>
>   <loggers>
>     <root level="trace">
>       <appender-ref ref="jdbc"/>
>     </root>
>   </loggers>
> </configuration>
>  
>  
>  
> And JDBCAppender code is below:
>  
> @Plugin(name = "JDBCAppender", type = "Core", elementType = "appender", printObject = true)
> public final class JDBCAppender extends AbstractAppender {
>  
>                 private final  Connection con;
>                 private final String sql;
>  
>     @SuppressWarnings("unchecked")
>                 private JDBCAppender(String name, Filter filter, @SuppressWarnings("rawtypes") Layout layout, Connection con, String sql, boolean handleExceptions) {
>                                 super(name, filter, layout, handleExceptions);
>                                 this.con = con;
>                                 this.sql = sql;
> }
>  
>     public void append(LogEvent event) {
>         try {
>    
>         Statement stmt = con.createStatement();
>             stmt.execute(sql);
>             con.commit();
>             con.close();
>         } catch (Exception ex) {
>             throw new AppenderRuntimeException(ex);
>         }
>     }
>  
>     @PluginFactory
>     public static JDBCAppender createAppender(@PluginAttr("url") String databaseURL,
>                                                   @PluginAttr("driver") String driverName,
>                                                   @PluginAttr("userName") String databaseUser,
>                                                   @PluginAttr("password") String databasePassword,
>                                                   @PluginElement("sql") String sql,
>                                                   @SuppressWarnings("rawtypes") @PluginElement("layout") Layout layout,
>                                                   @PluginElement("filter") Filter filter,
>                                                   @PluginAttr("suppressExceptions") String suppress) {
>  
>         String name = "JDBC Connection Info " + databaseURL;
>         boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
>         Connection con = null;
>         if (!DriverManager.getDrivers().hasMoreElements())
>                      setDriver(driverName);
>          if (con == null) {
>            try {
>                                                 con = DriverManager.getConnection(databaseURL, databaseUser,          databasePassword);
>                                 } catch (SQLException e) {
>                                                 // TODO Auto-generated catch block
>                                                 e.printStackTrace();
>                                 }
>          }
>        
>         if (con == null) {
>             return null;
>         }
>         if (layout == null) {
>             layout = SerializedLayout.createLayout();
>         }
>         return new JDBCAppender(name, filter, layout, con, sql, handleExceptions);
>     }
>    
>     public static void setDriver(String driverClass) {
>       try {
>         Class.forName(driverClass);
>       } catch (Exception e) {
>         
>       }
>     }
>  
> }
>  
> Is there any other API changes or configuration needed to get Customer Appender work ?
>  
>  
>  
> Thanks
> Anand
>  
>  
>  
>  


RE: custom Appender throwing error

Posted by "Awasthi, Anand" <AA...@dstbs.com>.
Thanks Ralph, that error is gone but now I get following errors:

ERROR JDBC contains an invalid element or attribute "name"
ERROR Unable to locate appender jdbc for logger

When I look at other appenders they all have name attribute in appender element so I am not sure why I am getting error message


If I remove the attribute name="jdbc" then I get only following error:
ERROR Unable to locate appender JDBC for logger


Here is my updated log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration status="trace" packages="com.dstbs.logging.log4j2.appender">
  <appenders >
    <JDBC name="jdbc" driver="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost/academic" userName="root" password="" sql="insert into exam (name, year, course, affiliation_id) values ('class XX', '2015' , 'high school', '1')"/>
  </appenders>
  <loggers>
    <root level="trace">
      <appender-ref ref="jdbc"/>
    </root>
  </loggers>
</configuration>


Here is what a typical console looks like


2013-01-07 13:55:10,530 DEBUG Generated plugins in 0.002802471 seconds
2013-01-07 13:55:10,545 DEBUG Calling createAppender on class com.dstbs.logging.log4j2.appender.JDBCAppender for element JDBC with params(url="jdbc:mysql://localhost/academic", driver="com.mysql.jdbc.Driver", userName="root", password="", sql="insert into exam (name, year, course, affiliation_id) values ('class XX', '2015' , 'high school', '1')", null, null, suppressExceptions="null")
2013-01-07 13:55:10,717 DEBUG Calling createAppenders on class org.apache.logging.log4j.core.config.plugins.AppendersPlugin for element appenders with params(appenders={JDBC Connection Info jdbc:mysql://localhost/academic})
2013-01-07 13:55:10,717 DEBUG Generated plugins in 0.000925918 seconds
2013-01-07 13:55:10,733 DEBUG Calling createAppenderRef on class org.apache.logging.log4j.core.config.AppenderRef for element appender-ref with params(ref="JDBC", level="null", null)
2013-01-07 13:55:10,733 DEBUG Calling createLogger on class org.apache.logging.log4j.core.config.LoggerConfig$RootLogger for element root with params(additivity="null", level="trace", appender-ref={org.apache.logging.log4j.core.config.AppenderRef@a9ae05}, properties={}, Configuration(C:\Log4j 2.x-workspace\LOG4J2\bin\log4j2.xml), null)
2013-01-07 13:55:10,733 DEBUG Calling createLoggers on class org.apache.logging.log4j.core.config.plugins.LoggersPlugin for element loggers with params(loggers={root})
2013-01-07 13:55:10,733 ERROR Unable to locate appender JDBC for logger
2013-01-07 13:55:10,733 DEBUG Reconfiguration completed



Thanks
Anand

From: Ralph Goers [mailto:ralph.goers@dslextreme.com]
Sent: Monday, January 07, 2013 12:31 PM
To: Log4J Developers List
Subject: Re: custom Appender throwing error

Your plugin probably hasn't been loaded.  You need to either add the package your plugin is part of to the packages attribute of the configuration element (see  http://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax) or follow the Plugin Preloading instructions at http://logging.apache.org/log4j/2.x/manual/plugins.html

Ralph

On Jan 7, 2013, at 8:42 AM, Awasthi, Anand wrote:


Hi,

I have written custom  JDBCAppender to write log messages to database. I have Hello World type program to test JDBCAppender.  When I run the program, I get following error:


2013-01-07 11:37:28,753 ERROR appenders contains an invalid element or attribute "JDBCAppender"


Here is my log4j2.xml :


<?xml version="1.0" encoding="UTF-8"?>
<configuration status="trace">
  <appenders>
    <JDBCAppender name="jdbc" driver="com.mysql.jdbc.Driver"
              url="jdbc:localhost:testdb" userName="root" password=""/>
  </appenders>
  <loggers>
    <root level="trace">
      <appender-ref ref="jdbc"/>
    </root>
  </loggers>
</configuration>



And JDBCAppender code is below:

@Plugin(name = "JDBCAppender", type = "Core", elementType = "appender", printObject = true)
public final class JDBCAppender extends AbstractAppender {

                private final  Connection con;
                private final String sql;

    @SuppressWarnings("unchecked")
                private JDBCAppender(String name, Filter filter, @SuppressWarnings("rawtypes") Layout layout, Connection con, String sql, boolean handleExceptions) {
                                super(name, filter, layout, handleExceptions);
                                this.con = con;
                                this.sql = sql;
}

    public void append(LogEvent event) {
        try {

        Statement stmt = con.createStatement();
            stmt.execute(sql);
            con.commit();
            con.close();
        } catch (Exception ex) {
            throw new AppenderRuntimeException(ex);
        }
    }

    @PluginFactory
    public static JDBCAppender createAppender(@PluginAttr("url") String databaseURL,
                                                  @PluginAttr("driver") String driverName,
                                                  @PluginAttr("userName") String databaseUser,
                                                  @PluginAttr("password") String databasePassword,
                                                  @PluginElement("sql") String sql,
                                                  @SuppressWarnings("rawtypes") @PluginElement("layout") Layout layout,
                                                  @PluginElement("filter") Filter filter,
                                                  @PluginAttr("suppressExceptions") String suppress) {

        String name = "JDBC Connection Info " + databaseURL;
        boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
        Connection con = null;
        if (!DriverManager.getDrivers().hasMoreElements())
                     setDriver(driverName);
         if (con == null) {
           try {
                                                con = DriverManager.getConnection(databaseURL, databaseUser,          databasePassword);
                                } catch (SQLException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                }
         }

        if (con == null) {
            return null;
        }
        if (layout == null) {
            layout = SerializedLayout.createLayout();
        }
        return new JDBCAppender(name, filter, layout, con, sql, handleExceptions);
    }

    public static void setDriver(String driverClass) {
      try {
        Class.forName(driverClass);
      } catch (Exception e) {

      }
    }

}

Is there any other API changes or configuration needed to get Customer Appender work ?



Thanks
Anand







Re: custom Appender throwing error

Posted by Ralph Goers <ra...@dslextreme.com>.
Your plugin probably hasn't been loaded.  You need to either add the package your plugin is part of to the packages attribute of the configuration element (see  http://logging.apache.org/log4j/2.x/manual/configuration.html#ConfigurationSyntax) or follow the Plugin Preloading instructions at http://logging.apache.org/log4j/2.x/manual/plugins.html

Ralph

On Jan 7, 2013, at 8:42 AM, Awasthi, Anand wrote:

> Hi,
>  
> I have written custom  JDBCAppender to write log messages to database. I have Hello World type program to test JDBCAppender.  When I run the program, I get following error:
>  
>  
> 2013-01-07 11:37:28,753 ERROR appenders contains an invalid element or attribute "JDBCAppender"
>  
>  
> Here is my log4j2.xml :
>  
>  
> <?xml version="1.0" encoding="UTF-8"?>
> <configuration status="trace">
>   <appenders>
>     <JDBCAppender name="jdbc" driver="com.mysql.jdbc.Driver"
>               url="jdbc:localhost:testdb" userName="root" password=""/>
>   </appenders>
>   <loggers>
>     <root level="trace">
>       <appender-ref ref="jdbc"/>
>     </root>
>   </loggers>
> </configuration>
>  
>  
>  
> And JDBCAppender code is below:
>  
> @Plugin(name = "JDBCAppender", type = "Core", elementType = "appender", printObject = true)
> public final class JDBCAppender extends AbstractAppender {
>  
>                 private final  Connection con;
>                 private final String sql;
>  
>     @SuppressWarnings("unchecked")
>                 private JDBCAppender(String name, Filter filter, @SuppressWarnings("rawtypes") Layout layout, Connection con, String sql, boolean handleExceptions) {
>                                 super(name, filter, layout, handleExceptions);
>                                 this.con = con;
>                                 this.sql = sql;
> }
>  
>     public void append(LogEvent event) {
>         try {
>    
>         Statement stmt = con.createStatement();
>             stmt.execute(sql);
>             con.commit();
>             con.close();
>         } catch (Exception ex) {
>             throw new AppenderRuntimeException(ex);
>         }
>     }
>  
>     @PluginFactory
>     public static JDBCAppender createAppender(@PluginAttr("url") String databaseURL,
>                                                   @PluginAttr("driver") String driverName,
>                                                   @PluginAttr("userName") String databaseUser,
>                                                   @PluginAttr("password") String databasePassword,
>                                                   @PluginElement("sql") String sql,
>                                                   @SuppressWarnings("rawtypes") @PluginElement("layout") Layout layout,
>                                                   @PluginElement("filter") Filter filter,
>                                                   @PluginAttr("suppressExceptions") String suppress) {
>  
>         String name = "JDBC Connection Info " + databaseURL;
>         boolean handleExceptions = suppress == null ? true : Boolean.valueOf(suppress);
>         Connection con = null;
>         if (!DriverManager.getDrivers().hasMoreElements())
>                      setDriver(driverName);
>          if (con == null) {
>            try {
>                                                 con = DriverManager.getConnection(databaseURL, databaseUser,          databasePassword);
>                                 } catch (SQLException e) {
>                                                 // TODO Auto-generated catch block
>                                                 e.printStackTrace();
>                                 }
>          }
>        
>         if (con == null) {
>             return null;
>         }
>         if (layout == null) {
>             layout = SerializedLayout.createLayout();
>         }
>         return new JDBCAppender(name, filter, layout, con, sql, handleExceptions);
>     }
>    
>     public static void setDriver(String driverClass) {
>       try {
>         Class.forName(driverClass);
>       } catch (Exception e) {
>         
>       }
>     }
>  
> }
>  
> Is there any other API changes or configuration needed to get Customer Appender work ?
>  
>  
>  
> Thanks
> Anand
>  
>  
>