简体   繁体   中英

Getting syntax error (XML Config) in MySQL using Log4j2

I am currently working on my Spring project to create simple library portal (just for education purposes). And now I am struggling with logging some actions into MySQL database using Log4j2 JDBCAppender.

To do that, I have created table in my database, using query:

CREATE TABLE user_logs (
  `id` int(12) NOT NULL AUTO_INCREMENT,
  `level` varchar(10) NOT NULL,
  `dated` TIMESTAMP NOT  NULL DEFAULT CURRENT_TIMESTAMP,
  `username` varchar(64) NOT NULL,
  `field` varchar(60) NOT NULL,
  `from` varchar(1000) NOT NULL DEFAULT '',
  `to` varchar(1000) NOT NULL DEFAULT '',
  `message` varchar(500) NOT NULL,

   PRIMARY KEY (`id`),

   KEY `user` (`username`),
   CONSTRAINT `FK_USERNAME` FOREIGN KEY (`username`)
   REFERENCES `user` (`username`)
   ON DELETE NO ACTION ON UPDATE NO ACTION

)ENGINE=InnoDB DEFAULT CHARSET=utf8;

In database I want to store information what field was modified, from which and to which value it was changed. Also logs will contain information for which user there was a change.

Then I created Log4j2 XML config file:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration name="ChangesLogs">
<Appenders>

    <Console name="consoleAppender" target="SYSTEM_OUT">
        <PatternLayout pattern="%d | %level | %logger | %m" />
    </Console>

    <JDBC name="userAppenderDB" tableName="user_logs">
        <ConnectionFactory class="com.wkrzywiec.spring.library.config.LogsConnectionFactory" method="getDatabaseConnection" />
        <Column name="level" pattern="%level"/>
        <Column name="username" pattern="%X{username}"/>
        <Column name="field" pattern="%X{field}"/>
        <Column name="from" pattern="%X{from}"/>
        <Column name="to" pattern="%X{to}"/>
        <Column name="message" pattern="%message"/>
    </JDBC>
</Appenders>

<Loggers>
    <Root level="debug">
        <AppenderRef ref="consoleAppender" />
    </Root>

    <Logger name="userLoggerDB" >
        <AppenderRef ref="consoleAppender" />
        <AppenderRef ref="userAppenderDB" />
    </Logger>

</Loggers>

And class for JDBCAppender connection pool:

package com.wkrzywiec.spring.library.config;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.springframework.stereotype.Component;

@Component
public class LogsConnectionFactory {

    private static interface Singleton {
        final LogsConnectionFactory INSTANCE = new LogsConnectionFactory();
    }

    private final DataSource dataSource;

    private String datasourceURL = "jdbc:mysql://localhost:3306/library_db?autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC";

    private String userName = "library-spring";

    private String pass = "library-spring";

    private LogsConnectionFactory() {

        Properties properties = new Properties();
        properties.setProperty("user", userName);
        properties.setProperty("password", pass);

        GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>();
        DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
                datasourceURL, properties);

        new PoolableConnectionFactory(connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED);

        this.dataSource = new PoolingDataSource(pool);
    }

    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }

}

And finally when I am saving new user using below code in my service class:

@Override
public void saveReaderUser(UserDTO user) {
    com.wkrzywiec.spring.library.entity.User userEntity = convertUserDTOtoUserEntity(user);
    userDAO.saveUser(userEntity);

    ThreadContext.put("username", user.getUsername());
    ThreadContext.put("field", "ALL");
    ThreadContext.put("from", "");
    ThreadContext.put("to", user.toString());
    userLogger.info("New user");
    ThreadContext.clearAll();
}

I've got this error (just to make it clear, this error is only for adding logs, user is successfully saved in db):

Caused by: java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.cj.core.util.Util.handleNewInstance(Util.java:185)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:168)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:175)
    at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:636)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1734)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchInternal(PreparedStatement.java:1217)
    at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:1009)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.commitAndClose(JdbcDatabaseManager.java:172)
    ... 59 more

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:536)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:115)
    at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
    at com.mysql.cj.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1826)
    at com.mysql.cj.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2034)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1712)
    ... 64 more

2018-03-04 10:07:44,726 http-bio-8080-exec-7 ERROR An exception occurred processing Appender userAppenderDB org.apache.logging.log4j.core.appender.AppenderLoggingException: Failed to commit transaction logging event or flushing buffer.
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.commitAndClose(JdbcDatabaseManager.java:177)
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager.write(AbstractDatabaseManager.java:174)
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.append(AbstractDatabaseAppender.java:108)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:156)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:129)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:120)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:84)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:448)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:433)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:403)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:63)
    at org.apache.logging.log4j.core.Logger.logMessage(Logger.java:146)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2163)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2118)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2101)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:1995)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1967)
    at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1304)
    at com.wkrzywiec.spring.library.service.LibraryUserDetailService.saveReaderUser(LibraryUserDetailService.java:86)
    at com.wkrzywiec.spring.library.controller.LoginController.processRegisterForm(LoginController.java:58)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:871)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:777)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:881)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:209)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:94)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:502)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1132)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:684)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:283)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

Caused by: java.sql.BatchUpdateException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.cj.core.util.Util.handleNewInstance(Util.java:185)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:168)
    at com.mysql.cj.core.util.Util.getInstance(Util.java:175)
    at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:636)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1734)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchInternal(PreparedStatement.java:1217)
    at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:1009)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:297)
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.commitAndClose(JdbcDatabaseManager.java:172)
    ... 59 more

Caused by: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from,to,message) VALUES ('INFO','wojtek21','ALL','','UserDTO [username=wojtek21,' at line 1
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:536)
    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:513)
    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:115)
    at com.mysql.cj.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:1983)
    at com.mysql.cj.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1826)
    at com.mysql.cj.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2034)
    at com.mysql.cj.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1712)
    ... 64 more

I've tried many things to solve it (checking typo, other configs, data types in sql table, etc), but with no success. From the error message it looks like that it is a problem with SQL insert query, but I don't know how to fix it as it is generated by Log4j2. Do you know what I am doing wrong?

I would really appreciate your support.

Thanks a lot!

from is a SQL keyword. Don't use that as a column name.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM