当我使用JDBCAppender设置log4j时,Grails会抛出ClassNotFoundException

时间:2014-12-15 17:15:32

标签: grails jdbc log4j classnotfoundexception appender

上下文

我正在尝试使用Grails 2.4.3上的JDBCAppender设置log4j,我尝试使用H2,MySQL和PostgreSQL,但它会为每个驱动程序抛出一个ClassNotFoundException异常。

log4j JDBCAppender的配置:

我测试了用户和密码凭据信息,我的意思是,我可以通过Datasource.groovy文件连接到这些数据库。

用H2测试1:

log4j = {
    appenders {
        jdbc name: "db",
            databaseURL: "jdbc:h2:mem:devDb;MVCC=TRUE;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE",
            user: "sa",
            password: "",
            driverClassName: "org.h2.Driver",
            sql: "INSERT INTO event_log (log_date, log_message) VALUES ('%d{yyyy.MM.dd HH:mm:ss}', '[%-5p]. Category: %c. Message: %m. User: %X{sessionUserName} DU:[%X{sessionUserDU}]');"
    }

root {
    info 'grails.app.controller','db'
}

}

Postgres的Test2:

log4j = {
    appenders {
        jdbc name: "db",
            URL: "jdbc:postgresql://localhost/grailsTestDB",
            user: "userDB",
            password: "*******",
            driver: "org.postgresql.Driver",
            layout: pattern(conversionPattern: "[%t] %-5p %c{2} %x - %m%n - %X{username}'"),
            sql: "INSERT INTO event_log (accion,nivel,req,logString,usuario) VALUES('%c{2} %x','%-5p','[%t]','%m%n','%X{username}');"
    }

root {
    info 'grails.app.controller','db'
}

}

使用MySQL的Test3:

下一个代码来自Grails 1.3.8应用程序,在该应用程序中,此代码可以正常工作。

log4j = {
    appenders {
        appender new JDBCAppender(
            name: "db",
            databaseURL: "jdbc:mysql://dbdevsie.db.hostname.com/dbdevsie",
            driver: "com.mysql.jdbc.Driver",
            user: "dbdevsie231",
            password: "********",
            layout: pattern(conversionPattern: "[%t] %-5p %c{2} %x - %m%n - %X{username}'"),
            sql: "INSERT INTO activity_log (accion,nivel,req,logString,usuario) VALUES('%c{2} %x','%-5p','[%t]','%m%n','%X{username}');"
    )
}

root {
    info 'grails.app.controller','db'
}

}

Buildconfig.groovy依赖项设置:

dependencies {
    runtime 'mysql:mysql-connector-java:5.1.29'
    runtime 'org.postgresql:postgresql:9.3-1101-jdbc41'
    test "org.grails:grails-datastore-test-support:1.0-grails-2.4"
}

测试结果:

当我测试h2时,它会抛出com.mysql.jdbc.Driver异常。

当我测试Mysql时,会抛出sun.jdbc.odbc.JdbcOdbcDriver异常。

当我测试Postgresql时,它会抛出org.postgresql.Driver异常。

| Error log4j:ERROR Failed to load driver
| Error java.lang.ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver
| Error     at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
| Error     at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
| Error     at java.security.AccessController.doPrivileged(Native Method)
| Error     at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
| Error     at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
| Error     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
| Error     at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
| Error     at java.lang.Class.forName0(Native Method)
| Error     at java.lang.Class.forName(Class.java:191)
| Error     at org.apache.log4j.jdbc.JDBCAppender.setDriver(JDBCAppender.java:391)
| Error     at org.apache.log4j.jdbc.JDBCAppender.getConnection(JDBCAppender.java:248)
| Error     at org.apache.log4j.jdbc.JDBCAppender.execute(JDBCAppender.java:215)
| Error     at org.apache.log4j.jdbc.JDBCAppender.flushBuffer(JDBCAppender.java:289)
| Error     at org.apache.log4j.jdbc.JDBCAppender.append(JDBCAppender.java:186)
| Error     at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)    

其他评论

我还测试下载log4j 1.2.17,PostgreSQL 9.3和MySQL 5.1.34 jar文件并将它们放在lib文件夹中,但我的结果相同。

有人可以帮我解决这个问题吗?

提前感谢。

更新

此问题在Mac OS中显示,但我在linux中运行相同的代码并且没有问题。

  • OS X Yosemite版本10.10.1
  • Java 1.7.0_71

2 个答案:

答案 0 :(得分:1)

使用DSL而不是实例化内联的appender是正确的;当您的代码在Config.groovy中运行时,依赖关系和类路径尚未得到解决,因此您需要一些方法来延迟appender的实际初始化,直到发生这种情况并且DSL配置是一个不错的选择。

我有这个工作,但有不同的失败。在我的情况下,H2和MySQL在早期可靠地崩溃了我的1.7 JVM,但是当我切换到1.8时它起作用,现在它甚至在删除了几乎所有东西之后也工作在1.7。尝试通过注释掉这些配置更改来独立解析依赖项,然后在启用它们的情况下重新启动。这也可能是由于分叉 - 我几乎总是通过删除BuildConfig.groovy中的整个grails.project.fork块来禁用它 - 如果没有其他工作,看看是否有帮助。

这就是我在Config.groovy中所拥有的:

log4j.main = {

   appenders {
      jdbc name: 'jdbcAppender', driver: 'com.mysql.jdbc.Driver', user: '...',
           password: '...', URL: 'jdbc:mysql://localhost/<dbname>',
           layout: pattern(conversionPattern:
                "insert into logs(log_date, logger, log_level, message) " +
                "values('%d{yyyy-MM-dd HH:mm:ss}','%c','%p','%m')")
   }

   root {
      info 'stdout', 'jdbcAppender'
   }

   error 'org.codehaus.groovy.grails',
         'org.springframework',
         'org.hibernate',
         'net.sf.ehcache.hibernate'
}

我创建了这个表来登录:

create table logs (
   log_date datetime not null,
   log_level varchar(10) not null,
   logger varchar(100) not null,
   message varchar(1000) not null
) ENGINE=InnoDB;

答案 1 :(得分:0)

我们使用了一个解决方法,其中我们使用了dataSource作为jdbc appender

在Datasource.groovy中添加日志数据源:

dataSource_log {
    url = "jdbc:sqlserver://DBServer:1433;databaseName=Logs;integratedSecurity=true" 
    dialect = "org.hibernate.dialect.SQLServerDialect" 
    driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver" 
}

然后覆盖JDBCAppender获取其连接的位置

public class DataSourceAppender extends JDBCAppender {
    SessionFactory sessionFactory;
    protected java.sql.Connection getConnection() throws java.sql.SQLException {
        SessionImplementor imp = (SessionImplementor) sessionFactory.getCurrentSession();
        return imp.getJdbcConnectionAccess().obtainConnection();
    }
}

在Bootstrap.groovy中将此自定义appender添加到log4j:

def grailsApplication
def sessionFactory_log

def init = { servletContext ->
    def sqlAppender = new DataSourceAppender(
            grailsApplication.config.dataSourceAppender
    )
    sqlAppender.sessionFactory = sessionFactory_log
    Logger.getRootLogger().addAppender(sqlAppender)
}

虽然愿意看到真正的解决方案。