View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements. See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache license, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License. You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the license for the specific language governing permissions and
15   * limitations under the license.
16   */
17  package org.apache.logging.log4j.core.appender.db.jpa;
18  
19  import java.util.Map;
20  import javax.persistence.MappedSuperclass;
21  import javax.persistence.Transient;
22  
23  import org.apache.logging.log4j.Level;
24  import org.apache.logging.log4j.Marker;
25  import org.apache.logging.log4j.ThreadContext;
26  import org.apache.logging.log4j.core.LogEvent;
27  import org.apache.logging.log4j.message.Message;
28  
29  /**
30   * Users of the JPA appender MUST extend this class, using JPA annotations on the concrete class and all of its
31   * accessor methods (as needed) to map them to the proper table and columns. Accessors you do not want persisted should
32   * be annotated with {@link Transient @Transient}. All accessors should call {@link #getWrappedEvent()} and delegate the
33   * call to the underlying event. Users may want to instead extend {@link BasicLogEventEntity}, which takes care of all
34   * of this for you.<br>
35   * <br>
36   * The concrete class must have two constructors: a public no-arg constructor to convince the JPA provider that it's a
37   * valid entity, and a public constructor that takes a single {@link LogEvent event} and passes it to the parent class
38   * with {@link #AbstractLogEventWrapperEntity(LogEvent) super(event)}. Furthermore, the concrete class must be annotated
39   * {@link javax.persistence.Entity @Entity} and {@link javax.persistence.Table @Table} and must implement a fully
40   * mutable ID property annotated with {@link javax.persistence.Id @Id} and
41   * {@link javax.persistence.GeneratedValue @GeneratedValue} to tell the JPA provider how to calculate an ID for new
42   * events.<br>
43   * <br>
44   * Many of the return types of {@link LogEvent} methods (e.g., {@link StackTraceElement}, {@link Message},
45   * {@link Marker}, {@link Throwable}, {@link ThreadContext.ContextStack}, and {@link Map Map&lt;String, String&gt}) will
46   * not be recognized by the JPA provider. In conjunction with {@link javax.persistence.Convert @Convert}, you can use
47   * the converters in the {@link org.apache.logging.log4j.core.appender.db.jpa.converter} package to convert these
48   * types to database columns. If you want to retrieve log events from the database, you can create a true POJO entity
49   * and also use these converters for extracting persisted values.<br>
50   * <br>
51   * The mutator methods in this class not specified in {@link LogEvent} are no-op methods, implemented to satisfy the JPA
52   * requirement that accessor methods have matching mutator methods. If you create additional accessor methods, you must
53   * likewise create matching no-op mutator methods.
54   *
55   * @see BasicLogEventEntity
56   */
57  @MappedSuperclass
58  public abstract class AbstractLogEventWrapperEntity implements LogEvent {
59      private static final long serialVersionUID = 1L;
60  
61      private final LogEvent wrappedEvent;
62  
63      /**
64       * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
65       * signature. The no-argument constructor is required for a standards-compliant JPA provider to accept this as an
66       * entity.
67       */
68      @SuppressWarnings("unused")
69      protected AbstractLogEventWrapperEntity() {
70          this(null);
71      }
72  
73      /**
74       * Instantiates this base class. All concrete implementations must have a constructor matching this constructor's
75       * signature. This constructor is used for wrapping this entity around a logged event.
76       * 
77       * @param wrappedEvent The underlying event from which information is obtained.
78       */
79      protected AbstractLogEventWrapperEntity(final LogEvent wrappedEvent) {
80          this.wrappedEvent = wrappedEvent;
81      }
82  
83      /**
84       * All eventual accessor methods must call this method and delegate the method call to the underlying wrapped event.
85       * Annotated {@link @Transient} so as not to be included in the persisted entity.
86       * 
87       * @return The underlying event from which information is obtained.
88       */
89      @Transient
90      protected final LogEvent getWrappedEvent() {
91          return this.wrappedEvent;
92      }
93  
94      /**
95       * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
96       *
97       * @param level Ignored.
98       */
99      @SuppressWarnings("unused")
100     public void setLevel(final Level level) {
101         // this entity is write-only
102     }
103 
104     /**
105      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
106      *
107      * @param loggerName Ignored.
108      */
109     @SuppressWarnings("unused")
110     public void setLoggerName(final String loggerName) {
111         // this entity is write-only
112     }
113 
114     /**
115      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
116      *
117      * @param source Ignored.
118      */
119     @SuppressWarnings("unused")
120     public void setSource(final StackTraceElement source) {
121         // this entity is write-only
122     }
123 
124     /**
125      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
126      *
127      * @param message Ignored.
128      */
129     @SuppressWarnings("unused")
130     public void setMessage(final Message message) {
131         // this entity is write-only
132     }
133 
134     /**
135      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
136      *
137      * @param marker Ignored.
138      */
139     @SuppressWarnings("unused")
140     public void setMarker(final Marker marker) {
141         // this entity is write-only
142     }
143 
144     /**
145      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
146      *
147      * @param threadName Ignored.
148      */
149     @SuppressWarnings("unused")
150     public void setThreadName(final String threadName) {
151         // this entity is write-only
152     }
153 
154     /**
155      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
156      *
157      * @param millis Ignored.
158      */
159     @SuppressWarnings("unused")
160     public void setMillis(final long millis) {
161         // this entity is write-only
162     }
163 
164     /**
165      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
166      *
167      * @param throwable Ignored.
168      */
169     @SuppressWarnings("unused")
170     public void setThrown(final Throwable throwable) {
171         // this entity is write-only
172     }
173 
174     /**
175      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
176      *
177      * @param contextMap Ignored.
178      */
179     @SuppressWarnings("unused")
180     public void setContextMap(final Map<String, String> contextMap) {
181         // this entity is write-only
182     }
183 
184     /**
185      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
186      *
187      * @param contextStack Ignored.
188      */
189     @SuppressWarnings("unused")
190     public void setContextStack(final ThreadContext.ContextStack contextStack) {
191         // this entity is write-only
192     }
193 
194     /**
195      * A no-op mutator to satisfy JPA requirements, as this entity is write-only.
196      *
197      * @param fqcn Ignored.
198      */
199     @SuppressWarnings("unused")
200     public void setFQCN(final String fqcn) {
201         // this entity is write-only
202     }
203 
204     /**
205      * Indicates whether the source of the logging request is required downstream. Annotated {@link Transient @Transient} so as
206      * not to be included in the persisted entity.
207      *
208      * @return whether the source of the logging request is required downstream.
209      */
210     @Override
211     @Transient
212     public final boolean isIncludeLocation() {
213         return this.getWrappedEvent().isIncludeLocation();
214     }
215 
216     @Override
217     public final void setIncludeLocation(final boolean locationRequired) {
218         this.getWrappedEvent().setIncludeLocation(locationRequired);
219     }
220 
221     /**
222      * Indicates whether this event is the last one in a batch. Annotated {@link Transient @Transient} so as not to be included
223      * in the persisted entity.
224      *
225      * @return whether this event is the last one in a batch.
226      */
227     @Override
228     @Transient
229     public final boolean isEndOfBatch() {
230         return this.getWrappedEvent().isEndOfBatch();
231     }
232 
233     @Override
234     public final void setEndOfBatch(final boolean endOfBatch) {
235         this.getWrappedEvent().setEndOfBatch(endOfBatch);
236     }
237 }