You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2018/01/27 18:46:37 UTC
[3/6] logging-log4j2 git commit: [LOG4J2-2188] Split off JPA support
into a new module log4j-jpa.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ThrowableAttributeConverter.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ThrowableAttributeConverter.java b/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ThrowableAttributeConverter.java
new file mode 100644
index 0000000..bbec319
--- /dev/null
+++ b/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ThrowableAttributeConverter.java
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+
+import org.apache.logging.log4j.util.LoaderUtil;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * A JPA 2.1 attribute converter for {@link Throwable}s in {@link org.apache.logging.log4j.core.LogEvent}s. This
+ * converter is capable of converting both to and from {@link String}s.
+ */
+@Converter(autoApply = false)
+public class ThrowableAttributeConverter implements AttributeConverter<Throwable, String> {
+ private static final int CAUSED_BY_STRING_LENGTH = 10;
+
+ private static final Field THROWABLE_CAUSE;
+
+ private static final Field THROWABLE_MESSAGE;
+
+ static {
+ try {
+ THROWABLE_CAUSE = Throwable.class.getDeclaredField("cause");
+ THROWABLE_CAUSE.setAccessible(true);
+ THROWABLE_MESSAGE = Throwable.class.getDeclaredField("detailMessage");
+ THROWABLE_MESSAGE.setAccessible(true);
+ } catch (final NoSuchFieldException e) {
+ throw new IllegalStateException("Something is wrong with java.lang.Throwable.", e);
+ }
+ }
+
+ @Override
+ public String convertToDatabaseColumn(final Throwable throwable) {
+ if (throwable == null) {
+ return null;
+ }
+
+ final StringBuilder builder = new StringBuilder();
+ this.convertThrowable(builder, throwable);
+ return builder.toString();
+ }
+
+ private void convertThrowable(final StringBuilder builder, final Throwable throwable) {
+ builder.append(throwable.toString()).append('\n');
+ for (final StackTraceElement element : throwable.getStackTrace()) {
+ builder.append("\tat ").append(element).append('\n');
+ }
+ if (throwable.getCause() != null) {
+ builder.append("Caused by ");
+ this.convertThrowable(builder, throwable.getCause());
+ }
+ }
+
+ @Override
+ public Throwable convertToEntityAttribute(final String s) {
+ if (Strings.isEmpty(s)) {
+ return null;
+ }
+
+ final List<String> lines = Arrays.asList(s.split("(\n|\r\n)"));
+ return this.convertString(lines.listIterator(), false);
+ }
+
+ private Throwable convertString(final ListIterator<String> lines, final boolean removeCausedBy) {
+ String firstLine = lines.next();
+ if (removeCausedBy) {
+ firstLine = firstLine.substring(CAUSED_BY_STRING_LENGTH);
+ }
+ final int colon = firstLine.indexOf(":");
+ String throwableClassName;
+ String message = null;
+ if (colon > 1) {
+ throwableClassName = firstLine.substring(0, colon);
+ if (firstLine.length() > colon + 1) {
+ message = firstLine.substring(colon + 1).trim();
+ }
+ } else {
+ throwableClassName = firstLine;
+ }
+
+ final List<StackTraceElement> stackTrace = new ArrayList<>();
+ Throwable cause = null;
+ while (lines.hasNext()) {
+ final String line = lines.next();
+
+ if (line.startsWith("Caused by ")) {
+ lines.previous();
+ cause = convertString(lines, true);
+ break;
+ }
+
+ stackTrace.add(
+ StackTraceElementAttributeConverter.convertString(line.trim().substring(3).trim())
+ );
+ }
+
+ return this.getThrowable(throwableClassName, message, cause,
+ stackTrace.toArray(new StackTraceElement[stackTrace.size()]));
+ }
+
+ private Throwable getThrowable(final String throwableClassName, final String message, final Throwable cause,
+ final StackTraceElement[] stackTrace) {
+ try {
+ @SuppressWarnings("unchecked")
+ final Class<Throwable> throwableClass = (Class<Throwable>) LoaderUtil.loadClass(throwableClassName);
+
+ if (!Throwable.class.isAssignableFrom(throwableClass)) {
+ return null;
+ }
+
+ Throwable throwable;
+ if (message != null && cause != null) {
+ throwable = this.getThrowable(throwableClass, message, cause);
+ if (throwable == null) {
+ throwable = this.getThrowable(throwableClass, cause);
+ if (throwable == null) {
+ throwable = this.getThrowable(throwableClass, message);
+ if (throwable == null) {
+ throwable = this.getThrowable(throwableClass);
+ if (throwable != null) {
+ THROWABLE_MESSAGE.set(throwable, message);
+ THROWABLE_CAUSE.set(throwable, cause);
+ }
+ } else {
+ THROWABLE_CAUSE.set(throwable, cause);
+ }
+ } else {
+ THROWABLE_MESSAGE.set(throwable, message);
+ }
+ }
+ } else if (cause != null) {
+ throwable = this.getThrowable(throwableClass, cause);
+ if (throwable == null) {
+ throwable = this.getThrowable(throwableClass);
+ if (throwable != null) {
+ THROWABLE_CAUSE.set(throwable, cause);
+ }
+ }
+ } else if (message != null) {
+ throwable = this.getThrowable(throwableClass, message);
+ if (throwable == null) {
+ throwable = this.getThrowable(throwableClass);
+ if (throwable != null) {
+ THROWABLE_MESSAGE.set(throwable, cause);
+ }
+ }
+ } else {
+ throwable = this.getThrowable(throwableClass);
+ }
+
+ if (throwable == null) {
+ return null;
+ }
+ throwable.setStackTrace(stackTrace);
+ return throwable;
+ } catch (final Exception e) {
+ return null;
+ }
+ }
+
+ private Throwable getThrowable(final Class<Throwable> throwableClass, final String message, final Throwable cause) {
+ try {
+ @SuppressWarnings("unchecked")
+ final
+ Constructor<Throwable>[] constructors = (Constructor<Throwable>[]) throwableClass.getConstructors();
+ for (final Constructor<Throwable> constructor : constructors) {
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ if (parameterTypes.length == 2) {
+ if (String.class == parameterTypes[0] && Throwable.class.isAssignableFrom(parameterTypes[1])) {
+ return constructor.newInstance(message, cause);
+ } else if (String.class == parameterTypes[1] &&
+ Throwable.class.isAssignableFrom(parameterTypes[0])) {
+ return constructor.newInstance(cause, message);
+ }
+ }
+ }
+ return null;
+ } catch (final Exception e) {
+ return null;
+ }
+ }
+
+ private Throwable getThrowable(final Class<Throwable> throwableClass, final Throwable cause) {
+ try {
+ @SuppressWarnings("unchecked")
+ final
+ Constructor<Throwable>[] constructors = (Constructor<Throwable>[]) throwableClass.getConstructors();
+ for (final Constructor<Throwable> constructor : constructors) {
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ if (parameterTypes.length == 1 && Throwable.class.isAssignableFrom(parameterTypes[0])) {
+ return constructor.newInstance(cause);
+ }
+ }
+ return null;
+ } catch (final Exception e) {
+ return null;
+ }
+ }
+
+ private Throwable getThrowable(final Class<Throwable> throwableClass, final String message) {
+ try {
+ return throwableClass.getConstructor(String.class).newInstance(message);
+ } catch (final Exception e) {
+ return null;
+ }
+ }
+
+ private Throwable getThrowable(final Class<Throwable> throwableClass) {
+ try {
+ return throwableClass.newInstance();
+ } catch (final Exception e) {
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/package-info.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/package-info.java b/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/package-info.java
new file mode 100644
index 0000000..2245fa7
--- /dev/null
+++ b/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/package-info.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+// Lines too long...
+//CHECKSTYLE:OFF
+/**
+ * The converters in this package implement the JPA 2.1 mechanism for converting non-standard types to and from
+ * database fields. Most of these types are capable of two-way conversion and can be used to both persist and retrieve
+ * entities. The
+ * {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapAttributeConverter ContextMapAttributeConverter}
+ * and {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackAttributeConverter ContextStackAttributeConverter}
+ * only support persistence and not retrieval, persisting the type as a simple string. You can use the
+ * {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter ContextMapJsonAttributeConverter}
+ * and {@link org.apache.logging.log4j.core.appender.db.jpa.converter.ContextStackJsonAttributeConverter ContextStackJsonAttributeConverter}
+ * instead, which require the Jackson Data Processor dependency to also be on your class path.
+ */
+//CHECKSTYLE:ON
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/package-info.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/package-info.java b/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/package-info.java
new file mode 100644
index 0000000..3434faa
--- /dev/null
+++ b/log4j-jpa/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+/**
+ * The JPA Appender supports writing log events to a relational database using the Java Persistence API. You will need
+ * a JDBC driver on your classpath for the database you wish to log to. You will also need the Java Persistence API 2.1
+ * and your JPA provider of choice on the class path; these Maven dependencies are optional and will not automatically
+ * be added to your classpath.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa;
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/site/manual/index.md
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/site/manual/index.md b/log4j-jpa/src/site/manual/index.md
new file mode 100644
index 0000000..235dfb8
--- /dev/null
+++ b/log4j-jpa/src/site/manual/index.md
@@ -0,0 +1,33 @@
+<!-- vim: set syn=markdown : -->
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+# Log4j Java Persistence API module
+
+As of Log4j 2.11.0, JPA support has moved from the existing module logj-core to the new module log4j-jpa.
+
+## Requirements
+
+This module was introduced in Log4j 2.11.0 and requires the javax.persistence API.
+
+Some features may require optional
+[dependencies](../runtime-dependencies.html). These dependencies are specified in the
+documentation for those features.
+
+Some Log4j features require external dependencies.
+See the [Dependency Tree](dependencies.html#Dependency_Tree)
+for the exact list of JAR files needed for these features.
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/site/site.xml
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/site/site.xml b/log4j-jpa/src/site/site.xml
new file mode 100644
index 0000000..6d4cddc
--- /dev/null
+++ b/log4j-jpa/src/site/site.xml
@@ -0,0 +1,52 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project name="Log4j Core"
+ xmlns="http://maven.apache.org/DECORATION/1.4.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/DECORATION/1.4.0 http://maven.apache.org/xsd/decoration-1.4.0.xsd">
+ <body>
+ <links>
+ <item name="Apache" href="http://www.apache.org/" />
+ <item name="Logging Services" href="http://logging.apache.org/"/>
+ <item name="Log4j" href="../index.html"/>
+ </links>
+
+ <!-- Component-specific reports -->
+ <menu ref="reports"/>
+
+ <!-- Overall Project Info -->
+ <menu name="Log4j Project Information" img="icon-info-sign">
+ <item name="Dependencies" href="../dependencies.html" />
+ <item name="Dependency Convergence" href="../dependency-convergence.html" />
+ <item name="Dependency Management" href="../dependency-management.html" />
+ <item name="Project Team" href="../team-list.html" />
+ <item name="Mailing Lists" href="../mail-lists.html" />
+ <item name="Issue Tracking" href="../issue-tracking.html" />
+ <item name="Project License" href="../license.html" />
+ <item name="Source Repository" href="../source-repository.html" />
+ <item name="Project Summary" href="../project-summary.html" />
+ </menu>
+
+ <menu name="Log4j Project Reports" img="icon-cog">
+ <item name="Changes Report" href="../changes-report.html" />
+ <item name="JIRA Report" href="../jira-report.html" />
+ <item name="Surefire Report" href="../surefire-report.html" />
+ <item name="RAT Report" href="../rat-report.html" />
+ </menu>
+ </body>
+</project>
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractJpaAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractJpaAppenderTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractJpaAppenderTest.java
new file mode 100644
index 0000000..6ff3c14
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractJpaAppenderTest.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.LoggerContext;
+import org.apache.logging.log4j.core.config.ConfigurationFactory;
+import org.apache.logging.log4j.core.config.DefaultConfiguration;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.apache.logging.log4j.util.PropertiesUtil;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public abstract class AbstractJpaAppenderTest {
+ private final String databaseType;
+ private Connection connection;
+
+ public AbstractJpaAppenderTest(final String databaseType) {
+ this.databaseType = databaseType;
+ }
+
+ protected abstract Connection setUpConnection() throws SQLException;
+
+ public void setUp(final String configFileName) throws SQLException {
+ this.connection = this.setUpConnection();
+
+ System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY,
+ "org/apache/logging/log4j/core/appender/db/jpa/" + configFileName);
+ PropertiesUtil.getProperties().reload();
+ final LoggerContext context = LoggerContext.getContext(false);
+ if (context.getConfiguration() instanceof DefaultConfiguration) {
+ context.reconfigure();
+ }
+ StatusLogger.getLogger().reset();
+ }
+
+ public void tearDown() throws SQLException {
+ final LoggerContext context = LoggerContext.getContext(false);
+ try {
+ String appenderName = "databaseAppender";
+ final Appender appender = context.getConfiguration().getAppender(appenderName);
+ assertNotNull("The appender '" + appenderName + "' should not be null.", appender);
+ assertTrue("The appender should be a JpaAppender.", appender instanceof JpaAppender);
+ ((JpaAppender) appender).getManager().close();
+ } finally {
+ System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
+ PropertiesUtil.getProperties().reload();
+ context.reconfigure();
+ StatusLogger.getLogger().reset();
+
+ try (Statement statement = this.connection.createStatement();) {
+ statement.execute("SHUTDOWN");
+ }
+
+ this.connection.close();
+ }
+ }
+
+ @Test
+ public void testBaseJpaEntityAppender() throws SQLException {
+ try {
+ this.setUp("log4j2-" + this.databaseType + "-jpa-base.xml");
+
+ final RuntimeException exception = new RuntimeException("Hello, world!");
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ final PrintWriter writer = new PrintWriter(outputStream);
+ exception.printStackTrace(writer);
+ writer.close();
+ final String stackTrace = outputStream.toString().replace("\r\n", "\n");
+
+ final long millis = System.currentTimeMillis();
+
+ final Logger logger1 = LogManager.getLogger(this.getClass().getName() + ".testBaseJpaEntityAppender");
+ final Logger logger2 = LogManager.getLogger(this.getClass().getName() + ".testBaseJpaEntityAppenderAgain");
+ logger1.info("Test my message 01.");
+ logger1.error("This is another message 02.", exception);
+ logger2.warn("A final warning has been issued.");
+
+ final Statement statement = this.connection.createStatement();
+ final ResultSet resultSet = statement.executeQuery("SELECT * FROM jpaBaseLogEntry ORDER BY id");
+
+ assertTrue("There should be at least one row.", resultSet.next());
+
+ long date = resultSet.getTimestamp("eventDate").getTime();
+ assertTrue("The date should be later than pre-logging (1).", date >= millis);
+ assertTrue("The date should be earlier than now (1).", date <= System.currentTimeMillis());
+ assertEquals("The level column is not correct (1).", "INFO", resultSet.getString("level"));
+ assertEquals("The logger column is not correct (1).", logger1.getName(), resultSet.getString("logger"));
+ assertEquals("The message column is not correct (1).", "Test my message 01.",
+ resultSet.getString("message"));
+ assertNull("The exception column is not correct (1).", resultSet.getString("exception"));
+
+ assertTrue("There should be at least two rows.", resultSet.next());
+
+ date = resultSet.getTimestamp("eventDate").getTime();
+ assertTrue("The date should be later than pre-logging (2).", date >= millis);
+ assertTrue("The date should be earlier than now (2).", date <= System.currentTimeMillis());
+ assertEquals("The level column is not correct (2).", "ERROR", resultSet.getString("level"));
+ assertEquals("The logger column is not correct (2).", logger1.getName(), resultSet.getString("logger"));
+ assertEquals("The message column is not correct (2).", "This is another message 02.",
+ resultSet.getString("message"));
+ assertEquals("The exception column is not correct (2).", stackTrace, resultSet.getString("exception"));
+
+ assertTrue("There should be three rows.", resultSet.next());
+
+ date = resultSet.getTimestamp("eventDate").getTime();
+ assertTrue("The date should be later than pre-logging (3).", date >= millis);
+ assertTrue("The date should be earlier than now (3).", date <= System.currentTimeMillis());
+ assertEquals("The level column is not correct (3).", "WARN", resultSet.getString("level"));
+ assertEquals("The logger column is not correct (3).", logger2.getName(), resultSet.getString("logger"));
+ assertEquals("The message column is not correct (3).", "A final warning has been issued.",
+ resultSet.getString("message"));
+ assertNull("The exception column is not correct (3).", resultSet.getString("exception"));
+
+ assertFalse("There should not be four rows.", resultSet.next());
+ } finally {
+ this.tearDown();
+ }
+ }
+
+ @Test
+ public void testBasicJpaEntityAppender() throws SQLException {
+ try {
+ this.setUp("log4j2-" + this.databaseType + "-jpa-basic.xml");
+
+ final Error exception = new Error("Goodbye, cruel world!");
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ final PrintWriter writer = new PrintWriter(outputStream);
+ exception.printStackTrace(writer);
+ writer.close();
+ final String stackTrace = outputStream.toString().replace("\r\n", "\n");
+
+ final long millis = System.currentTimeMillis();
+
+ final Logger logger1 = LogManager.getLogger(this.getClass().getName() + ".testBasicJpaEntityAppender");
+ final Logger logger2 = LogManager.getLogger(this.getClass().getName() + ".testBasicJpaEntityAppenderAgain");
+ logger1.debug("Test my debug 01.");
+ logger1.warn("This is another warning 02.", exception);
+ logger2.fatal("A fatal warning has been issued.");
+
+ final Statement statement = this.connection.createStatement();
+ final ResultSet resultSet = statement.executeQuery("SELECT * FROM jpaBasicLogEntry ORDER BY id");
+
+ assertTrue("There should be at least one row.", resultSet.next());
+
+ long date = resultSet.getLong("timemillis");
+ assertTrue("The date should be later than pre-logging (1).", date >= millis);
+ assertTrue("The date should be earlier than now (1).", date <= System.currentTimeMillis());
+ assertEquals("The level column is not correct (1).", "DEBUG", resultSet.getString("level"));
+ assertEquals("The logger column is not correct (1).", logger1.getName(), resultSet.getString("loggerName"));
+ assertEquals("The message column is not correct (1).", "Test my debug 01.",
+ resultSet.getString("message"));
+ assertNull("The exception column is not correct (1).", resultSet.getString("thrown"));
+
+ assertTrue("There should be at least two rows.", resultSet.next());
+
+ date = resultSet.getLong("timemillis");
+ assertTrue("The date should be later than pre-logging (2).", date >= millis);
+ assertTrue("The date should be earlier than now (2).", date <= System.currentTimeMillis());
+ assertEquals("The level column is not correct (2).", "WARN", resultSet.getString("level"));
+ assertEquals("The logger column is not correct (2).", logger1.getName(), resultSet.getString("loggerName"));
+ assertEquals("The message column is not correct (2).", "This is another warning 02.",
+ resultSet.getString("message"));
+ assertEquals("The exception column is not correct (2).", stackTrace, resultSet.getString("thrown"));
+
+ assertTrue("There should be three rows.", resultSet.next());
+
+ date = resultSet.getLong("timemillis");
+ assertTrue("The date should be later than pre-logging (3).", date >= millis);
+ assertTrue("The date should be earlier than now (3).", date <= System.currentTimeMillis());
+ assertEquals("The level column is not correct (3).", "FATAL", resultSet.getString("level"));
+ assertEquals("The logger column is not correct (3).", logger2.getName(), resultSet.getString("loggerName"));
+ assertEquals("The message column is not correct (3).", "A fatal warning has been issued.",
+ resultSet.getString("message"));
+ assertNull("The exception column is not correct (3).", resultSet.getString("thrown"));
+
+ assertFalse("There should not be four rows.", resultSet.next());
+ } finally {
+ this.tearDown();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
new file mode 100644
index 0000000..055dd03
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaH2AppenderTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.experimental.categories.Category;
+
+@Category(Appenders.Jpa.class)
+public class JpaH2AppenderTest extends AbstractJpaAppenderTest {
+ private static final String USER_ID = "sa";
+ private static final String PASSWORD = Strings.EMPTY;
+
+ public JpaH2AppenderTest() {
+ super("h2");
+ }
+
+ @Override
+ protected Connection setUpConnection() throws SQLException {
+ final Connection connection = DriverManager.getConnection("jdbc:h2:mem:Log4j", USER_ID, PASSWORD);
+
+ try (Statement statement = connection.createStatement()) {
+ statement.executeUpdate("CREATE TABLE jpaBaseLogEntry ( "
+ + "id INTEGER IDENTITY, eventDate DATETIME, level NVARCHAR(10), logger NVARCHAR(255), "
+ + "message NVARCHAR(1024), exception NVARCHAR(1048576)" + " )");
+ }
+
+ try (Statement statement = connection.createStatement()) {
+ statement.executeUpdate("CREATE TABLE jpaBasicLogEntry ( "
+ + "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, level NVARCHAR(10), loggerName NVARCHAR(255), "
+ + "message NVARCHAR(1024), thrown NVARCHAR(1048576), contextMapJson NVARCHAR(1048576),"
+ + "loggerFQCN NVARCHAR(1024), contextStack NVARCHAR(1048576), marker NVARCHAR(255), source NVARCHAR(2048),"
+ + "threadId BIGINT, threadName NVARCHAR(255), threadPriority INTEGER" + " )");
+ }
+
+ return connection;
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHsqldbAppenderTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHsqldbAppenderTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHsqldbAppenderTest.java
new file mode 100644
index 0000000..3e22d96
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/JpaHsqldbAppenderTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.util.Strings;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class JpaHsqldbAppenderTest extends AbstractJpaAppenderTest {
+ private static final String USER_ID = "sa";
+ private static final String PASSWORD = Strings.EMPTY;
+
+ public JpaHsqldbAppenderTest() {
+ super("hsqldb");
+ }
+
+ @Override
+ protected Connection setUpConnection() throws SQLException {
+ final Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:Log4j", USER_ID, PASSWORD);
+
+ try (Statement statement = connection.createStatement()) {
+ statement.executeUpdate("CREATE TABLE jpaBaseLogEntry ( "
+ + "id INTEGER IDENTITY, eventDate DATETIME, level VARCHAR(10), logger VARCHAR(255), "
+ + "message VARCHAR(1024), exception VARCHAR(1048576)" + " )");
+ }
+
+ try (Statement statement = connection.createStatement()) {
+ statement.executeUpdate("CREATE TABLE jpaBasicLogEntry ( "
+ + "id INTEGER IDENTITY, timemillis BIGINT, nanoTime BIGINT, level VARCHAR(10), loggerName VARCHAR(255), "
+ + "message VARCHAR(1024), thrown VARCHAR(1048576), contextMapJson VARCHAR(1048576),"
+ + "loggerFQCN VARCHAR(1024), contextStack VARCHAR(1048576), marker VARCHAR(255), source VARCHAR(2048),"
+ + "threadId BIGINT, threadName NVARCHAR(255), threadPriority INTEGER" + " )");
+ }
+
+ return connection;
+ }
+
+ @Test
+ public void testNoEntityClassName() {
+ final JpaAppender appender = JpaAppender.createAppender("name", null, null, null, null, "jpaAppenderTestUnit");
+
+ assertNull("The appender should be null.", appender);
+ }
+
+ @Test
+ public void testNoPersistenceUnitName() {
+ final JpaAppender appender = JpaAppender.createAppender("name", null, null, null, TestBaseEntity.class.getName(),
+ null);
+
+ assertNull("The appender should be null.", appender);
+ }
+
+ @Test
+ public void testBadEntityClassName() {
+ final JpaAppender appender = JpaAppender.createAppender("name", null, null, null, "com.foo.Bar",
+ "jpaAppenderTestUnit");
+
+ assertNull("The appender should be null.", appender);
+ }
+
+ @Test
+ public void testNonLogEventEntity() {
+ final JpaAppender appender = JpaAppender.createAppender("name", null, null, null, Object.class.getName(),
+ "jpaAppenderTestUnit");
+
+ assertNull("The appender should be null.", appender);
+ }
+
+ @Test
+ public void testBadConstructorEntity01() {
+ final JpaAppender appender = JpaAppender.createAppender("name", null, null, null,
+ BadConstructorEntity1.class.getName(), "jpaAppenderTestUnit");
+
+ assertNull("The appender should be null.", appender);
+ }
+
+ @Test
+ public void testBadConstructorEntity02() {
+ final JpaAppender appender = JpaAppender.createAppender("name", null, null, null,
+ BadConstructorEntity2.class.getName(), "jpaAppenderTestUnit");
+
+ assertNull("The appender should be null.", appender);
+ }
+
+ @SuppressWarnings("unused")
+ public static class BadConstructorEntity1 extends TestBaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ public BadConstructorEntity1(final LogEvent wrappedEvent) {
+ super(wrappedEvent);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ public static class BadConstructorEntity2 extends TestBaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ public BadConstructorEntity2() {
+ super(null);
+ }
+
+ public BadConstructorEntity2(final LogEvent wrappedEvent, final String badParameter) {
+ super(wrappedEvent);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/LogEventEntityTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/LogEventEntityTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/LogEventEntityTest.java
new file mode 100644
index 0000000..ed59b53
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/LogEventEntityTest.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+
+package org.apache.logging.log4j.core.appender.db.jpa;
+
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext.ContextStack;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.message.Message;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LogEventEntityTest {
+
+ @Test
+ public void testToImmutable_AbstractLogEventWrapperEntity() {
+ final LogEvent logEvent = new AbstractLogEventWrapperEntity() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Map<String, String> getContextMap() {
+ return null;
+ }
+
+ @Override
+ public ContextStack getContextStack() {
+ return null;
+ }
+
+ @Override
+ public Level getLevel() {
+ return null;
+ }
+
+ @Override
+ public String getLoggerFqcn() {
+ return null;
+ }
+
+ @Override
+ public String getLoggerName() {
+ return null;
+ }
+
+ @Override
+ public Marker getMarker() {
+ return null;
+ }
+
+ @Override
+ public Message getMessage() {
+ return null;
+ }
+
+ @Override
+ public long getNanoTime() {
+ return 0;
+ }
+
+ @Override
+ public StackTraceElement getSource() {
+ return null;
+ }
+
+ @Override
+ public long getThreadId() {
+ return 0;
+ }
+
+ @Override
+ public String getThreadName() {
+ return null;
+ }
+
+ @Override
+ public int getThreadPriority() {
+ return 0;
+ }
+
+ @Override
+ public Throwable getThrown() {
+ return null;
+ }
+
+ @Override
+ public ThrowableProxy getThrownProxy() {
+ return null;
+ }
+
+ @Override
+ public long getTimeMillis() {
+ return 0;
+ }
+ };
+ Assert.assertNotSame(logEvent, logEvent.toImmutable());
+ }
+
+ @Test
+ public void testToImmutable_TestBaseEntity() {
+ final LogEvent logEvent = new TestBaseEntity();
+ Assert.assertNotSame(logEvent, logEvent.toImmutable());
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
new file mode 100644
index 0000000..5d4473e
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBaseEntity.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa;
+
+import java.util.Date;
+import java.util.Map;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.db.jpa.converter.LevelAttributeConverter;
+import org.apache.logging.log4j.core.appender.db.jpa.converter.MessageAttributeConverter;
+import org.apache.logging.log4j.core.appender.db.jpa.converter.ThrowableAttributeConverter;
+import org.apache.logging.log4j.core.impl.ThrowableProxy;
+import org.apache.logging.log4j.message.Message;
+
+@Entity
+@Table(name = "jpaBaseLogEntry")
+public class TestBaseEntity extends AbstractLogEventWrapperEntity {
+ private static final long serialVersionUID = 1L;
+
+ private long id = 0L;
+
+ public TestBaseEntity() {
+ super();
+ }
+
+ public TestBaseEntity(final LogEvent wrappedEvent) {
+ super(wrappedEvent);
+ }
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ public long getId() {
+ return this.id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "eventDate")
+ public Date getEventDate() {
+ return new Date(this.getTimeMillis());
+ }
+
+ public void setEventDate(final Date date) {
+ // this entity is write-only
+ }
+
+ @Override
+ @Convert(converter = LevelAttributeConverter.class)
+ @Column(name = "level")
+ public Level getLevel() {
+ return this.getWrappedEvent().getLevel();
+ }
+
+ @Override
+ @Basic
+ @Column(name = "logger")
+ public String getLoggerName() {
+ return this.getWrappedEvent().getLoggerName();
+ }
+
+ @Override
+ @Transient
+ public StackTraceElement getSource() {
+ return this.getWrappedEvent().getSource();
+ }
+
+ @Override
+ @Convert(converter = MessageAttributeConverter.class)
+ @Column(name = "message")
+ public Message getMessage() {
+ return this.getWrappedEvent().getMessage();
+ }
+
+ @Override
+ @Transient
+ public Marker getMarker() {
+ return this.getWrappedEvent().getMarker();
+ }
+
+ @Override
+ @Transient
+ public long getThreadId() {
+ return this.getWrappedEvent().getThreadId();
+ }
+
+ @Override
+ @Transient
+ public String getThreadName() {
+ return this.getWrappedEvent().getThreadName();
+ }
+
+ @Override
+ @Transient
+ public int getThreadPriority() {
+ return this.getWrappedEvent().getThreadPriority();
+ }
+
+ @Override
+ @Transient
+ public long getTimeMillis() {
+ return this.getWrappedEvent().getTimeMillis();
+ }
+
+ @Override
+ @Transient
+ public long getNanoTime() {
+ return this.getWrappedEvent().getNanoTime();
+ }
+
+ @Override
+ @Convert(converter = ThrowableAttributeConverter.class)
+ @Column(name = "exception")
+ public Throwable getThrown() {
+ return this.getWrappedEvent().getThrown();
+ }
+
+ @Override
+ @Transient
+ public ThrowableProxy getThrownProxy() {
+ return this.getWrappedEvent().getThrownProxy();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Override
+ @Transient
+ public Map<String, String> getContextMap() {
+ return this.getWrappedEvent().getContextMap();
+ }
+
+ @Override
+ @Transient
+ public ReadOnlyStringMap getContextData() {
+ return this.getWrappedEvent().getContextData();
+ }
+
+ @Override
+ @Transient
+ public ThreadContext.ContextStack getContextStack() {
+ return this.getWrappedEvent().getContextStack();
+ }
+
+ @Override
+ @Transient
+ public String getLoggerFqcn() {
+ return this.getWrappedEvent().getLoggerFqcn();
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBasicEntity.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBasicEntity.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBasicEntity.java
new file mode 100644
index 0000000..b804078
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/TestBasicEntity.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa;
+
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.db.jpa.converter.ContextMapJsonAttributeConverter;
+
+@Entity
+@Table(name = "jpaBasicLogEntry")
+@SuppressWarnings("unused")
+public class TestBasicEntity extends BasicLogEventEntity {
+ private static final long serialVersionUID = 1L;
+
+ private long id = 0L;
+
+ public TestBasicEntity() {
+ super();
+ }
+
+ public TestBasicEntity(final LogEvent wrapped) {
+ super(wrapped);
+ }
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "id")
+ public long getId() {
+ return this.id;
+ }
+
+ public void setId(final long id) {
+ this.id = id;
+ }
+
+ @Override
+ @Convert(converter = ContextMapJsonAttributeConverter.class)
+ @Column(name = "contextMapJson")
+ public Map<String, String> getContextMap() {
+ return super.getContextMap();
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverterTest.java
new file mode 100644
index 0000000..41306a1
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverterTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+import org.apache.logging.log4j.util.StringMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class ContextDataAttributeConverterTest {
+ private ContextDataAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new ContextDataAttributeConverter();
+ }
+
+ @Test
+ public void testConvertToDatabaseColumn01() {
+ final StringMap map = new SortedArrayStringMap();
+ map.putValue("test1", "another1");
+ map.putValue("key2", "value2");
+
+ assertEquals("The converted value is not correct.", map.toString(),
+ this.converter.convertToDatabaseColumn(map));
+ }
+
+ @Test
+ public void testConvertToDatabaseColumn02() {
+ final StringMap map = new SortedArrayStringMap();
+ map.putValue("someKey", "coolValue");
+ map.putValue("anotherKey", "testValue");
+ map.putValue("myKey", "yourValue");
+
+ assertEquals("The converted value is not correct.", map.toString(),
+ this.converter.convertToDatabaseColumn(map));
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testConvertToEntityAttribute() {
+ this.converter.convertToEntityAttribute(null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverterTest.java
new file mode 100644
index 0000000..161a23e
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverterTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+import org.apache.logging.log4j.util.StringMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class ContextDataJsonAttributeConverterTest {
+ private ContextDataJsonAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new ContextDataJsonAttributeConverter();
+ }
+
+ @Test
+ public void testConvert01() {
+ final StringMap map = new SortedArrayStringMap();
+ map.putValue("test1", "another1");
+ map.putValue("key2", "value2");
+
+ final String converted = this.converter.convertToDatabaseColumn(map);
+
+ assertNotNull("The converted value should not be null.", converted);
+
+ final ReadOnlyStringMap reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", map, reversed);
+ }
+
+ @Test
+ public void testConvert02() {
+ final StringMap map = new SortedArrayStringMap();
+ map.putValue("someKey", "coolValue");
+ map.putValue("anotherKey", "testValue");
+ map.putValue("myKey", "yourValue");
+
+ final String converted = this.converter.convertToDatabaseColumn(map);
+
+ assertNotNull("The converted value should not be null.", converted);
+
+ final ReadOnlyStringMap reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", map, reversed);
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test
+ public void testConvertNullOrBlankToEntityAttribute() {
+ assertNull("The converted attribute should be null (1).", this.converter.convertToEntityAttribute(null));
+ assertNull("The converted attribute should be null (2).", this.converter.convertToEntityAttribute(""));
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapAttributeConverterTest.java
new file mode 100644
index 0000000..e755d7f
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapAttributeConverterTest.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class ContextMapAttributeConverterTest {
+ private ContextMapAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new ContextMapAttributeConverter();
+ }
+
+ @Test
+ public void testConvertToDatabaseColumn01() {
+ final Map<String, String> map = new HashMap<>();
+ map.put("test1", "another1");
+ map.put("key2", "value2");
+
+ assertEquals("The converted value is not correct.", map.toString(),
+ this.converter.convertToDatabaseColumn(map));
+ }
+
+ @Test
+ public void testConvertToDatabaseColumn02() {
+ final Map<String, String> map = new HashMap<>();
+ map.put("someKey", "coolValue");
+ map.put("anotherKey", "testValue");
+ map.put("myKey", "yourValue");
+
+ assertEquals("The converted value is not correct.", map.toString(),
+ this.converter.convertToDatabaseColumn(map));
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testConvertToEntityAttribute() {
+ this.converter.convertToEntityAttribute(null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverterTest.java
new file mode 100644
index 0000000..07af863
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextMapJsonAttributeConverterTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class ContextMapJsonAttributeConverterTest {
+ private ContextMapJsonAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new ContextMapJsonAttributeConverter();
+ }
+
+ @Test
+ public void testConvert01() {
+ final Map<String, String> map = new HashMap<>();
+ map.put("test1", "another1");
+ map.put("key2", "value2");
+
+ final String converted = this.converter.convertToDatabaseColumn(map);
+
+ assertNotNull("The converted value should not be null.", converted);
+
+ final Map<String, String> reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", map, reversed);
+ }
+
+ @Test
+ public void testConvert02() {
+ final Map<String, String> map = new HashMap<>();
+ map.put("someKey", "coolValue");
+ map.put("anotherKey", "testValue");
+ map.put("myKey", "yourValue");
+
+ final String converted = this.converter.convertToDatabaseColumn(map);
+
+ assertNotNull("The converted value should not be null.", converted);
+
+ final Map<String, String> reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", map, reversed);
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test
+ public void testConvertNullOrBlankToEntityAttribute() {
+ assertNull("The converted attribute should be null (1).", this.converter.convertToEntityAttribute(null));
+ assertNull("The converted attribute should be null (2).", this.converter.convertToEntityAttribute(""));
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackAttributeConverterTest.java
new file mode 100644
index 0000000..57ae0a7
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackAttributeConverterTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import java.util.Arrays;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.spi.MutableThreadContextStack;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class ContextStackAttributeConverterTest {
+ private ContextStackAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new ContextStackAttributeConverter();
+ }
+
+ @Test
+ public void testConvertToDatabaseColumn01() {
+ final ThreadContext.ContextStack stack = new MutableThreadContextStack(
+ Arrays.asList("value1", "another2"));
+
+ assertEquals("The converted value is not correct.", "value1\nanother2",
+ this.converter.convertToDatabaseColumn(stack));
+ }
+
+ @Test
+ public void testConvertToDatabaseColumn02() {
+ final ThreadContext.ContextStack stack = new MutableThreadContextStack(
+ Arrays.asList("key1", "value2", "my3"));
+
+ assertEquals("The converted value is not correct.",
+ "key1\nvalue2\nmy3",
+ this.converter.convertToDatabaseColumn(stack));
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test(expected = UnsupportedOperationException.class)
+ public void testConvertToEntityAttribute() {
+ this.converter.convertToEntityAttribute(null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackJsonAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackJsonAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackJsonAttributeConverterTest.java
new file mode 100644
index 0000000..0fae006
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextStackJsonAttributeConverterTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.Arrays;
+
+import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.junit.ThreadContextStackRule;
+import org.apache.logging.log4j.spi.MutableThreadContextStack;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(Appenders.Jpa.class)
+public class ContextStackJsonAttributeConverterTest {
+ private ContextStackJsonAttributeConverter converter;
+
+ @Rule
+ public final ThreadContextStackRule threadContextRule = new ThreadContextStackRule();
+
+ @Before
+ public void setUp() {
+ this.converter = new ContextStackJsonAttributeConverter();
+ }
+
+ @Test
+ public void testConvert01() {
+ final ThreadContext.ContextStack stack = new MutableThreadContextStack(
+ Arrays.asList("value1", "another2"));
+
+ final String converted = this.converter.convertToDatabaseColumn(stack);
+
+ assertNotNull("The converted value should not be null.", converted);
+
+ final ThreadContext.ContextStack reversed = this.converter
+ .convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", stack.asList(),
+ reversed.asList());
+ }
+
+ @Test
+ public void testConvert02() {
+ final ThreadContext.ContextStack stack = new MutableThreadContextStack(
+ Arrays.asList("key1", "value2", "my3"));
+
+ final String converted = this.converter.convertToDatabaseColumn(stack);
+
+ assertNotNull("The converted value should not be null.", converted);
+
+ final ThreadContext.ContextStack reversed = this.converter
+ .convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", stack.asList(),
+ reversed.asList());
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test
+ public void testConvertNullOrBlankToEntityAttribute() {
+ assertNull("The converted attribute should be null (1).", this.converter.convertToEntityAttribute(null));
+ assertNull("The converted attribute should be null (2).", this.converter.convertToEntityAttribute(""));
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MarkerAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MarkerAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MarkerAttributeConverterTest.java
new file mode 100644
index 0000000..334bf1e
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MarkerAttributeConverterTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.MarkerManager;
+import org.apache.logging.log4j.categories.Appenders;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class MarkerAttributeConverterTest {
+ private MarkerAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new MarkerAttributeConverter();
+ }
+
+ @Test
+ public void testConvert01() {
+ final Marker marker = MarkerManager.getMarker("testConvert01");
+
+ final String converted = this.converter.convertToDatabaseColumn(marker);
+
+ assertNotNull("The converted value should not be null.", converted);
+ assertEquals("The converted value is not correct.", "testConvert01", converted);
+
+ final Marker reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", "testConvert01", marker.getName());
+ }
+
+ @Test
+ public void testConvert02() {
+ Marker marker = MarkerManager.getMarker("anotherConvert02").setParents(MarkerManager.getMarker("finalConvert03"));
+ marker = MarkerManager.getMarker("testConvert02").setParents(marker);
+
+ final String converted = this.converter.convertToDatabaseColumn(marker);
+
+ assertNotNull("The converted value should not be null.", converted);
+ assertEquals("The converted value is not correct.", "testConvert02[ anotherConvert02[ finalConvert03 ] ]",
+ converted);
+
+ final Marker reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", "testConvert02", marker.getName());
+ final Marker[] parents = marker.getParents();
+ assertNotNull("The first parent should not be null.", parents);
+ assertNotNull("The first parent should not be null.", parents[0]);
+ assertEquals("The first parent is not correct.", "anotherConvert02", parents[0].getName());
+ assertNotNull("The second parent should not be null.", parents[0].getParents());
+ assertNotNull("The second parent should not be null.", parents[0].getParents()[0]);
+ assertEquals("The second parent is not correct.", "finalConvert03", parents[0].getParents()[0].getName());
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test
+ public void testConvertNullOrBlankToEntityAttribute() {
+ assertNull("The converted attribute should be null (1).", this.converter.convertToEntityAttribute(null));
+ assertNull("The converted attribute should be null (2).", this.converter.convertToEntityAttribute(""));
+ }
+}
http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/df10e02a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MessageAttributeConverterTest.java
----------------------------------------------------------------------
diff --git a/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MessageAttributeConverterTest.java b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MessageAttributeConverterTest.java
new file mode 100644
index 0000000..e665dd6
--- /dev/null
+++ b/log4j-jpa/src/test/java/org/apache/logging/log4j/core/appender/db/jpa/converter/MessageAttributeConverterTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.appender.db.jpa.converter;
+
+import org.apache.logging.log4j.categories.Appenders;
+import org.apache.logging.log4j.message.Message;
+import org.apache.logging.log4j.status.StatusLogger;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import static org.junit.Assert.*;
+
+@Category(Appenders.Jpa.class)
+public class MessageAttributeConverterTest {
+ private static final StatusLogger LOGGER = StatusLogger.getLogger();
+
+ private MessageAttributeConverter converter;
+
+ @Before
+ public void setUp() {
+ this.converter = new MessageAttributeConverter();
+ }
+
+ @Test
+ public void testConvert01() {
+ final Message message = LOGGER.getMessageFactory().newMessage("Message #{} said [{}].", 3, "Hello");
+
+ final String converted = this.converter.convertToDatabaseColumn(message);
+
+ assertNotNull("The converted value should not be null.", converted);
+ assertEquals("The converted value is not correct.", "Message #3 said [Hello].", converted);
+
+ final Message reversed = this.converter.convertToEntityAttribute(converted);
+
+ assertNotNull("The reversed value should not be null.", reversed);
+ assertEquals("The reversed value is not correct.", "Message #3 said [Hello].", reversed.getFormattedMessage());
+ }
+
+ @Test
+ public void testConvertNullToDatabaseColumn() {
+ assertNull("The converted value should be null.", this.converter.convertToDatabaseColumn(null));
+ }
+
+ @Test
+ public void testConvertNullOrBlankToEntityAttribute() {
+ assertNull("The converted attribute should be null (1).", this.converter.convertToEntityAttribute(null));
+ assertNull("The converted attribute should be null (2).", this.converter.convertToEntityAttribute(""));
+ }
+}