You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by am...@apache.org on 2009/11/20 15:16:32 UTC

svn commit: r882564 - in /cxf/trunk: rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/ rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/ systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/ systests/jaxrs/src/...

Author: amichalec
Date: Fri Nov 20 14:16:31 2009
New Revision: 882564

URL: http://svn.apache.org/viewvc?rev=882564&view=rev
Log:
Spring integration of ATOM push-style logger; Log record JAXB namespace setup.

Added:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngineConfigurator.java
    cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushSpringTest.java
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/beans.xml
    cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/web.xml
Modified:
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogLevel.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecord.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecordsList.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushBean.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngine.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushHandler.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/LoggingThread.java
    cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/package-info.java

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogLevel.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogLevel.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogLevel.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogLevel.java Fri Nov 20 14:16:31 2009
@@ -38,29 +38,52 @@
  */
 @XmlEnum
 public enum LogLevel {
+    ALL,
     FATAL,
     ERROR,
     WARN,
     INFO,
     DEBUG,
-    TRACE;
-    
+    TRACE,
+    OFF;
+
+    @XmlTransient
+    private static Map<Level, LogLevel> fromJul = new HashMap<Level, LogLevel>();
+
     @XmlTransient
-    private static Map<Level, LogLevel> julLogLevels = new HashMap<Level, LogLevel>();
+    private static Map<LogLevel, Level> toJul = new HashMap<LogLevel, Level>();
 
-    static {
-        julLogLevels.put(Level.SEVERE, LogLevel.ERROR);
-        julLogLevels.put(Level.WARNING, LogLevel.WARN);
-        julLogLevels.put(Level.INFO, LogLevel.INFO);
-        julLogLevels.put(Level.FINE, LogLevel.DEBUG);
-        julLogLevels.put(Level.FINER, LogLevel.DEBUG);
-        julLogLevels.put(Level.FINEST, LogLevel.TRACE);
+    static {        
+        fromJul.put(Level.ALL, LogLevel.ALL);
+        fromJul.put(Level.SEVERE, LogLevel.ERROR);
+        fromJul.put(Level.WARNING, LogLevel.WARN);
+        fromJul.put(Level.INFO, LogLevel.INFO);
+        fromJul.put(Level.FINE, LogLevel.DEBUG);
+        fromJul.put(Level.FINER, LogLevel.DEBUG);
+        fromJul.put(Level.FINEST, LogLevel.TRACE);
+        fromJul.put(Level.OFF, LogLevel.OFF);
+
+        toJul.put(LogLevel.ALL, Level.ALL);
+        toJul.put(LogLevel.FATAL, Level.SEVERE);
+        toJul.put(LogLevel.ERROR, Level.SEVERE);
+        toJul.put(LogLevel.WARN, Level.WARNING);
+        toJul.put(LogLevel.INFO, Level.INFO);
+        toJul.put(LogLevel.DEBUG, Level.FINE);
+        toJul.put(LogLevel.TRACE, Level.FINEST);
+        toJul.put(LogLevel.OFF, Level.OFF);
     }
-    
+
     /**
      * Creates this enum from JUL {@link Level}.
      */
     public static LogLevel fromJUL(Level level) {
-        return julLogLevels.get(level);
+        return fromJul.get(level);
+    }
+
+    /**
+     * Creates this JUL {@link Level} from this enum.
+     */
+    public static Level toJUL(LogLevel level) {
+        return toJul.get(level);
     }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecord.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecord.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecord.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecord.java Fri Nov 20 14:16:31 2009
@@ -39,7 +39,7 @@
  * LogRecord are never null; if some attributes are not set (e.g. logger name, or rendered cause taken from
  * Throwable) empty strings are returned.
  */
-@XmlRootElement
+@XmlRootElement(namespace = "http://cxf.apache.org/jaxrs/log")
 public class LogRecord {
 
     private Date eventTimestamp = new Date();
@@ -77,7 +77,7 @@
         return record;
     }
 
-    @XmlElement
+    @XmlElement(namespace = "http://cxf.apache.org/jaxrs/log")
     public Date getEventTimestamp() {
         return eventTimestamp;
     }
@@ -87,7 +87,7 @@
         this.eventTimestamp = eventTimestamp;
     }
 
-    @XmlElement
+    @XmlElement(namespace = "http://cxf.apache.org/jaxrs/log")
     public LogLevel getLevel() {
         return level;
     }
@@ -100,7 +100,7 @@
     /**
      * Formatted message with parameters filled in.
      */
-    @XmlElement
+    @XmlElement(namespace = "http://cxf.apache.org/jaxrs/log")
     public String getMessage() {
         return message;
     }
@@ -110,7 +110,7 @@
         this.message = renderedMessage;
     }
 
-    @XmlElement
+    @XmlElement(namespace = "http://cxf.apache.org/jaxrs/log")
     public String getLoggerName() {
         return loggerName;
     }
@@ -120,7 +120,7 @@
         this.loggerName = loggerName;
     }
 
-    @XmlElement
+    @XmlElement(namespace = "http://cxf.apache.org/jaxrs/log")
     public String getThreadName() {
         return threadName;
     }
@@ -133,7 +133,7 @@
     /**
      * Full stack trace of {@link Throwable} associated with log record.
      */
-    @XmlElement
+    @XmlElement(namespace = "http://cxf.apache.org/jaxrs/log")
     public String getThrowable() {
         return throwable;
     }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecordsList.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecordsList.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecordsList.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/LogRecordsList.java Fri Nov 20 14:16:31 2009
@@ -33,12 +33,12 @@
 /**
  * List of {@link LogRecord}s. Necessary wrapper for {@link List} used in JAXB context.
  */
-@XmlRootElement(namespace = "zzz")
+@XmlRootElement(namespace = "http://cxf.apache.org/jaxrs/log")
 public class LogRecordsList {
 
     private List<LogRecord> logRecords = new ArrayList<LogRecord>();
-    
-    @XmlElement(name = "logRecord", namespace = "zzz")
+
+    @XmlElement(name = "logRecord", namespace = "http://cxf.apache.org/jaxrs/log")
     public List<LogRecord> getLogRecords() {
         return logRecords;
     }
@@ -47,7 +47,7 @@
         Validate.notNull(logRecords, "logRecords is null");
         this.logRecords = logRecords;
     }
-    
+
     @Override
     public boolean equals(Object obj) {
         return EqualsBuilder.reflectionEquals(obj, this);
@@ -61,5 +61,5 @@
     @Override
     public String toString() {
         return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
-    }    
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushBean.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushBean.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushBean.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushBean.java Fri Nov 20 14:16:31 2009
@@ -18,6 +18,234 @@
  */
 package org.apache.cxf.jaxrs.ext.logging.atom;
 
-public class AtomPushBean {
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
 
+import org.apache.commons.lang.Validate;
+import org.apache.cxf.jaxrs.ext.logging.LogLevel;
+
+/**
+ * Bean used to configure {@link AtomPushHandler JUL handler} with Spring instead of properties file. Next to
+ * configuration of handler, Spring bean offers simple configuration of associated loggers that share ATOM
+ * push-style handler.
+ * <p>
+ * General rules:
+ * <ul>
+ * <li>When {@link #setDeliverer(Deliverer) deliverer} property is not set explicitly, URL must be set to
+ * create default deliverer.</li>
+ * <li>When {@link #setConverter(Converter) converter} property is not set explicitly, default converter is
+ * created.</li>
+ * <li>When {@link #setLoggers(String) loggers} property is used, it overrides pair of
+ * {@link #setLogger(String) logger} and {@link #setLevel(String) level} properties; and vice versa.</li>
+ * <li>When logger is not set, handler is attached to root logger (named ""); when level is not set for
+ * logger, default "INFO" level is used.</li>
+ * <li>When {@link #setBatchSize(String) batchSize} property is not set or set to wrong value, default batch
+ * size of "1" is used.</li>
+ * <li>When deliverer property is NOT set, use of "retryXxx" properties causes creation of retrying default
+ * deliverer.</li>
+ * </ul>
+ * Examples:
+ * <p>
+ * ATOM push handler with registered with root logger for all levels or log events, pushing one feed per event
+ * to specified URL, using default delivery and conversion methods:
+ * 
+ * <pre>
+ *   &lt;bean class=&quot;org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean&quot; 
+ *     init-method=&quot;init&quot;&gt;
+ *       &lt;property name=&quot;url&quot; value=&quot;http://localhost:9080/feed&quot;/&gt;
+ *       &lt;property name=&quot;level&quot; value=&quot;ALL&quot; /&gt;
+ *   &lt;/bean&gt;
+ * </pre>
+ * 
+ * ATOM push handler registered with multiple loggers and listening for different levels (see
+ * {@link #setLoggers(String) loggers} property description for syntax details). Custom deliverer will take
+ * care of feeds, each of which carries batch of 10 log events:
+ * 
+ * <pre>
+ *   &lt;bean id=&quot;soapDeliverer&quot; ...
+ *   ...
+ *   &lt;bean class=&quot;org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean&quot; 
+ *     init-method=&quot;init&quot;&gt;
+ *       &lt;property name=&quot;deliverer&quot;&gt;
+ *           &lt;ref bean=&quot;soapDeliverer&quot;/&gt;
+ *       &lt;/property&gt;
+ *       &lt;property name=&quot;loggers&quot; value=&quot;
+ *           org.apache.cxf:DEBUG,
+ *           org.apache.cxf.jaxrs,
+ *           org.apache.cxf.bus:ERROR&quot; /&gt;
+ *       &lt;property name=&quot;batchSize&quot; value=&quot;10&quot; /&gt;
+ *   &lt;/bean&gt;
+ * </pre>
+ */
+public final class AtomPushBean {
+
+    private AtomPushEngineConfigurator conf = new AtomPushEngineConfigurator();
+    private List<LoggerLevel> loggers = new ArrayList<LoggerLevel>();
+    private boolean initialized;
+
+    /**
+     * Creates unconfigured and uninitialized bean. To configure setters must be used, then {@link #init()}
+     * must be called.
+     */
+    public AtomPushBean() {
+        initSingleLogger();
+    }
+
+    private void initSingleLogger() {
+        loggers = new ArrayList<LoggerLevel>();
+        loggers.add(new LoggerLevel("", "INFO"));
+    }
+
+    /**
+     * Set URL used when custom deliverer is not set (default deliverer is being created).
+     */
+    public void setUrl(String url) {
+        checkInit();
+        Validate.notNull(url, "url is null");
+        conf.setUrl(url);
+    }
+
+    /**
+     * Set initialized deliverer.
+     */
+    public void setDeliverer(Deliverer deliverer) {
+        checkInit();
+        Validate.notNull(deliverer, "deliverer is null");
+        conf.setDeliverer(deliverer);
+    }
+
+    /**
+     * Set initialized converter.
+     */
+    public void setConverter(Converter converter) {
+        checkInit();
+        Validate.notNull(converter, "converter is null");
+        conf.setConverter(converter);
+    }
+
+    /**
+     * Set one or more loggers and levels descriptor. <br>
+     * Parsed input syntax is:
+     * 
+     * <pre>
+     * loggers   := &lt;logger&gt;(&lt;separator&gt;&lt;logger&gt;)*
+     * logger    := &lt;name&gt;[&quot;:&quot;&lt;level&gt;]
+     * separator := &quot;,&quot; | &quot; &quot; | &quot;\n&quot;
+     * </pre>
+     * 
+     * Examples:
+     * <p>
+     * Two loggers and two levels: <br>
+     * <tt>org.apache.cxf:INFO, org.apache.cxf.jaxrs:DEBUG</tt>
+     * <p>
+     * Three loggers, first with default "INFO" level: <br>
+     * <tt>org.apache.cxf, org.apache.cxf.jaxrs:DEBUG, namedLogger:ERROR</tt><br>
+     * <p>
+     * One logger with default "INFO" level: <br>
+     * <tt>org.apache.cxf</tt><br>
+     */
+    public void setLoggers(String loggers) {
+        checkInit();
+        Validate.notNull(loggers, "loggers is null");
+        parseLoggers(loggers);
+    }
+
+    /**
+     * Name of logger to associate with ATOM push handler; empty string for root logger.
+     */
+    public void setLogger(String logger) {
+        checkInit();
+        Validate.notNull(logger, "logger is null");
+        if (loggers.size() != 1) {
+            initSingleLogger();
+        }
+        loggers.get(0).setLogger(logger);
+    }
+
+    /**
+     * Name of level that logger will use publishing log events to ATOM push handler; empty string for default
+     * "INFO" level.
+     */
+    public void setLevel(String level) {
+        checkInit();
+        Validate.notNull(level, "level is null");
+        if (loggers.size() != 1) {
+            initSingleLogger();
+        }
+        loggers.get(0).setLevel(level);
+    }
+
+    /**
+     * Size of batch; empty string for default one element batch.
+     */
+    public void setBatchSize(String batchSize) {
+        checkInit();
+        Validate.notNull(batchSize, "batchSize is null");
+        conf.setBatchSize(batchSize);
+    }
+
+    /**
+     * Initializes bean; creates ATOM push handler based on current properties state, and attaches handler to
+     * logger(s).
+     */
+    public void init() {
+        checkInit();
+        initialized = true;
+        Handler h = new AtomPushHandler(conf.createEngine());
+        for (int i = 0; i < loggers.size(); i++) {
+            Logger l = Logger.getLogger(loggers.get(i).getLogger());
+            l.addHandler(h);
+            l.setLevel(LogLevel.toJUL(LogLevel.valueOf(loggers.get(i).getLevel())));
+        }
+    }
+
+    private void checkInit() {
+        if (initialized) {
+            throw new IllegalStateException("Bean is already initialized");
+        }
+    }
+
+    private void parseLoggers(String param) {
+        loggers = new ArrayList<LoggerLevel>();
+        StringTokenizer st1 = new StringTokenizer(param, ", \t\n\r\f");
+        while (st1.hasMoreTokens()) {
+            String tok = st1.nextToken();
+            int idx = tok.indexOf(":");
+            if (idx != -1) {
+                loggers.add(new LoggerLevel(tok.substring(0, idx), tok.substring(idx + 1, tok.length())));
+            } else {
+                loggers.add(new LoggerLevel(tok, "INFO"));
+            }
+        }
+    }
+
+    private static class LoggerLevel {
+        private String logger;
+        private String level;
+
+        public LoggerLevel(String logger, String level) {
+            this.logger = logger;
+            this.level = level;
+        }
+
+        public String getLogger() {
+            return logger;
+        }
+
+        public void setLogger(String logger) {
+            this.logger = logger;
+        }
+
+        public String getLevel() {
+            return level;
+        }
+
+        public void setLevel(String level) {
+            this.level = level;
+        }
+
+    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngine.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngine.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngine.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngine.java Fri Nov 20 14:16:31 2009
@@ -28,7 +28,7 @@
 import org.apache.cxf.jaxrs.ext.logging.LogRecord;
 
 /**
- * ATOM push-style realization class. Engine enqueues log records as they are {@link #publish(LogRecord)
+ * Package private ATOM push-style engine. Engine enqueues log records as they are {@link #publish(LogRecord)
  * published}. After queue size exceeds {@link #getBatchSize() batch size} processing of collection of these
  * records (in size of batch size) is triggered.
  * <p>
@@ -44,7 +44,7 @@
  * reliable deliverer or use wrapping {@link RetryingDeliverer}.
  */
 // TODO add internal diagnostics - log messages somewhere except for logger :D
-public class AtomPushEngine {
+final class AtomPushEngine {
     private List<LogRecord> queue = new ArrayList<LogRecord>();
     private ExecutorService executor = Executors.newSingleThreadExecutor();
     private int batchSize = 1;

Added: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngineConfigurator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngineConfigurator.java?rev=882564&view=auto
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngineConfigurator.java (added)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushEngineConfigurator.java Fri Nov 20 14:16:31 2009
@@ -0,0 +1,161 @@
+/**
+ * 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.cxf.jaxrs.ext.logging.atom;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * Package private interpreter of incomplete input of engine configuration. Used commonly by
+ * {@link AtomPushHandler properties file} and {@link AtomPushBean spring} configuration schemes.
+ */
+// TODO extract 'general rules' of interpretation in handler and bean and put here
+final class AtomPushEngineConfigurator {
+
+    private Deliverer deliverer;
+    private Converter converter;
+    private String delivererClass;
+    private String converterClass;
+    private String batchSize;
+    private String delivererUrl;
+    private String retryTimeout;
+    private String retryPauseType;
+    private String retryPauseTime;
+
+    public void setUrl(String url) {
+        this.delivererUrl = url;
+    }
+
+    public void setRetryTimeout(String retryTimeout) {
+        this.retryTimeout = retryTimeout;
+    }
+
+    public void setRetryPauseType(String retryPauseType) {
+        this.retryPauseType = retryPauseType;
+    }
+
+    public void setRetryPauseTime(String retryPauseTime) {
+        this.retryPauseTime = retryPauseTime;
+    }
+
+    public void setBatchSize(String batchSize) {
+        this.batchSize = batchSize;
+    }
+
+    public void setDeliverer(Deliverer deliverer) {
+        this.deliverer = deliverer;
+    }
+
+    public void setConverter(Converter converter) {
+        this.converter = converter;
+    }
+
+    public void setDelivererClass(String delivererClass) {
+        this.delivererClass = delivererClass;
+    }
+
+    public void setConverterClass(String converterClass) {
+        this.converterClass = converterClass;
+    }
+
+    public AtomPushEngine createEngine() {
+        Deliverer d = deliverer;
+        Converter c = converter;
+        int batch = 1;
+        if (d == null) {
+            if (delivererUrl != null) {
+                if (delivererClass != null) {
+                    d = createDeliverer(delivererClass, delivererUrl);
+                } else {
+                    d = new WebClientDeliverer(delivererUrl);
+                }
+            } else {
+                throw new IllegalStateException("Either url, deliverer or "
+                                                + "deliverer class with url must be setup");
+            }
+        }
+        if (c == null) {
+            if (converterClass != null) {
+                c = createConverter(converterClass);
+            } else {
+                c = new ContentSingleEntryConverter();
+            }
+        }
+        batch = parseInt(batchSize, 1, 1);
+        if (retryPauseType != null) {
+            int timeout = parseInt(retryTimeout, 0, 0);
+            int pause = parseInt(retryPauseTime, 1, 30);
+            boolean linear = !retryPauseType.equalsIgnoreCase("exponential");
+            d = new RetryingDeliverer(d, timeout, pause, linear);
+        }
+        AtomPushEngine engine = new AtomPushEngine();
+        engine.setDeliverer(d);
+        engine.setConverter(c);
+        engine.setBatchSize(batch);
+        return engine;
+    }
+
+    private Deliverer createDeliverer(String clazz, String url) {
+        try {
+            Constructor<?> ctor = loadClass(clazz).getConstructor(String.class);
+            return (Deliverer)ctor.newInstance(url);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    private Converter createConverter(String clazz) {
+        try {
+            Constructor<?> ctor = loadClass(clazz).getConstructor();
+            return (Converter)ctor.newInstance();
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+    }
+
+    private Class<?> loadClass(String clazz) throws ClassNotFoundException {
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        try {
+            return cl.loadClass(clazz);
+        } catch (ClassNotFoundException e) {
+            try {
+                // clazz could be shorted (stripped package name) retry
+                String clazz2 = getClass().getPackage().getName() + "." + clazz;
+                return cl.loadClass(clazz2);
+            } catch (Exception e1) {
+                throw new ClassNotFoundException(e.getMessage() + " or " + e1.getMessage());
+            }
+        }
+    }
+
+    private int parseInt(String property, int defaultValue) {
+        try {
+            return Integer.parseInt(property);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
+    private int parseInt(String property, int lessThan, int defaultValue) {
+        int ret = parseInt(property, defaultValue);
+        if (ret < lessThan) {
+            ret = defaultValue;
+        }
+        return ret;
+    }
+}

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushHandler.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushHandler.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/AtomPushHandler.java Fri Nov 20 14:16:31 2009
@@ -18,7 +18,6 @@
  */
 package org.apache.cxf.jaxrs.ext.logging.atom;
 
-import java.lang.reflect.Constructor;
 import java.util.logging.Handler;
 import java.util.logging.LogManager;
 
@@ -73,7 +72,7 @@
  */
 public final class AtomPushHandler extends Handler {
 
-    private AtomPushEngine engine = new AtomPushEngine();
+    private AtomPushEngine engine;
     private boolean lazyConfig;
 
     /**
@@ -93,11 +92,21 @@
      * @param deliverer deliverer pushing ATOM elements to client
      */
     public AtomPushHandler(int batchSize, Converter converter, Deliverer deliverer) {
+        engine = new AtomPushEngine();
         engine.setBatchSize(batchSize);
         engine.setConverter(converter);
         engine.setDeliverer(deliverer);
     }
 
+    /**
+     * Creates handler using (package private).
+     * 
+     * @param engine configured engine.
+     */
+    AtomPushHandler(AtomPushEngine engine) {
+        this.engine = engine;
+    }
+
     @Override
     public synchronized void publish(java.util.logging.LogRecord record) {
         if (LoggingThread.isSilent()) {
@@ -107,7 +116,7 @@
         try {
             if (lazyConfig) {
                 lazyConfig = false;
-                configure();
+                configure2();
             }
             LogRecord rec = LogRecord.fromJUL(record);
             engine.publish(rec);
@@ -132,84 +141,97 @@
      * does not allow to iterate over configuration properties to make interpretation automated (e.g. using
      * commons-beanutils)
      */
-    private void configure() {
+    // private void configure() {
+    // LogManager manager = LogManager.getLogManager();
+    // String cname = getClass().getName();
+    // String url = manager.getProperty(cname + ".url");
+    // if (url == null) {
+    // // cannot proceed
+    // return;
+    // }
+    // String deliverer = manager.getProperty(cname + ".deliverer");
+    // if (deliverer != null) {
+    // engine.setDeliverer(createDeliverer(deliverer, url));
+    // } else {
+    // // default
+    // engine.setDeliverer(new WebClientDeliverer(url));
+    // }
+    // String converter = manager.getProperty(cname + ".converter");
+    // if (converter != null) {
+    // engine.setConverter(createConverter(converter));
+    // } else {
+    // // default
+    // engine.setConverter(new ContentSingleEntryConverter());
+    // }
+    // engine.setBatchSize(toInt(manager.getProperty(cname + ".batchSize"), 1, 1));
+    // String retryType = manager.getProperty(cname + ".retry.pause");
+    // if (retryType != null) {
+    // int timeout = toInt(manager.getProperty(cname + ".retry.timeout"), 0, 0);
+    // int pause = toInt(manager.getProperty(cname + ".retry.pause.time"), 1, 30);
+    // boolean linear = !retryType.equalsIgnoreCase("exponential");
+    // Deliverer wrapped = new RetryingDeliverer(engine.getDeliverer(), timeout, pause, linear);
+    // engine.setDeliverer(wrapped);
+    // }
+    // }
+    private void configure2() {
         LogManager manager = LogManager.getLogManager();
         String cname = getClass().getName();
-        String url = manager.getProperty(cname + ".url");
-        if (url == null) {
-            // cannot proceed
-            return;
-        }
-        String deliverer = manager.getProperty(cname + ".deliverer");
-        if (deliverer != null) {
-            engine.setDeliverer(createDeliverer(deliverer, url));
-        } else {
-            // default
-            engine.setDeliverer(new WebClientDeliverer(url));
-        }
-        String converter = manager.getProperty(cname + ".converter");
-        if (converter != null) {
-            engine.setConverter(createConverter(converter));
-        } else {
-            // default
-            engine.setConverter(new ContentSingleEntryConverter());
-        }
-        engine.setBatchSize(toInt(manager.getProperty(cname + ".batchSize"), 1, 1));
-        String retryType = manager.getProperty(cname + ".retry.pause");
-        if (retryType != null) {
-            int timeout = toInt(manager.getProperty(cname + ".retry.timeout"), 0, 0);
-            int pause = toInt(manager.getProperty(cname + ".retry.pause.time"), 1, 30);
-            boolean linear = !retryType.equalsIgnoreCase("exponential");
-            Deliverer wrapped = new RetryingDeliverer(engine.getDeliverer(), timeout, pause, linear);
-            engine.setDeliverer(wrapped);
-        }
-    }
-
-    private int toInt(String property, int defaultValue) {
-        try {
-            return Integer.parseInt(property);
-        } catch (NumberFormatException e) {
-            return defaultValue;
-        }
-    }
-
-    private int toInt(String property, int lessThan, int defaultValue) {
-        int ret = toInt(property, defaultValue);
-        if (ret < lessThan) {
-            ret = defaultValue;
-        }
-        return ret;
-    }
-
-    private Deliverer createDeliverer(String clazz, String url) {
-        try {
-            Constructor<?> ctor = loadClass(clazz).getConstructor(String.class);
-            return (Deliverer)ctor.newInstance(url);
-        } catch (Exception e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    private Converter createConverter(String clazz) {
-        try {
-            Constructor<?> ctor = loadClass(clazz).getConstructor();
-            return (Converter)ctor.newInstance();
-        } catch (Exception e) {
-            throw new IllegalArgumentException(e);
-        }
-    }
-
-    private Class<?> loadClass(String clazz) throws ClassNotFoundException {
-        try {
-            return getClass().getClassLoader().loadClass(clazz);
-        } catch (ClassNotFoundException e) {
-            try {
-                // clazz could be shorted (stripped package name) retry
-                String clazz2 = getClass().getPackage().getName() + "." + clazz;
-                return getClass().getClassLoader().loadClass(clazz2);
-            } catch (Exception e1) {
-                throw new ClassNotFoundException(e.getMessage() + " or " + e1.getMessage());
-            }
-        }
-    }
+        AtomPushEngineConfigurator conf = new AtomPushEngineConfigurator();
+        conf.setUrl(manager.getProperty(cname + ".url"));
+        conf.setDelivererClass(manager.getProperty(cname + ".deliverer"));
+        conf.setConverterClass(manager.getProperty(cname + ".converter"));
+        conf.setBatchSize(manager.getProperty(cname + ".batchSize"));
+        conf.setRetryPauseType(manager.getProperty(cname + ".retry.pause"));
+        conf.setRetryPauseTime(manager.getProperty(cname + ".retry.pause.time"));
+        conf.setRetryTimeout(manager.getProperty(cname + ".retry.timeout"));
+        engine = conf.createEngine();
+    }
+
+//    private int toInt(String property, int defaultValue) {
+//        try {
+//            return Integer.parseInt(property);
+//        } catch (NumberFormatException e) {
+//            return defaultValue;
+//        }
+//    }
+//
+//    private int toInt(String property, int lessThan, int defaultValue) {
+//        int ret = toInt(property, defaultValue);
+//        if (ret < lessThan) {
+//            ret = defaultValue;
+//        }
+//        return ret;
+//    }
+//
+//    private Deliverer createDeliverer(String clazz, String url) {
+//        try {
+//            Constructor<?> ctor = loadClass(clazz).getConstructor(String.class);
+//            return (Deliverer)ctor.newInstance(url);
+//        } catch (Exception e) {
+//            throw new IllegalArgumentException(e);
+//        }
+//    }
+//
+//    private Converter createConverter(String clazz) {
+//        try {
+//            Constructor<?> ctor = loadClass(clazz).getConstructor();
+//            return (Converter)ctor.newInstance();
+//        } catch (Exception e) {
+//            throw new IllegalArgumentException(e);
+//        }
+//    }
+//
+//    private Class<?> loadClass(String clazz) throws ClassNotFoundException {
+//        try {
+//            return getClass().getClassLoader().loadClass(clazz);
+//        } catch (ClassNotFoundException e) {
+//            try {
+//                // clazz could be shorted (stripped package name) retry
+//                String clazz2 = getClass().getPackage().getName() + "." + clazz;
+//                return getClass().getClassLoader().loadClass(clazz2);
+//            } catch (Exception e1) {
+//                throw new ClassNotFoundException(e.getMessage() + " or " + e1.getMessage());
+//            }
+//        }
+//    }
 }

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/LoggingThread.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/LoggingThread.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/LoggingThread.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/atom/LoggingThread.java Fri Nov 20 14:16:31 2009
@@ -26,7 +26,7 @@
  * Other approach than using thread local storage would be scanning of stack trace of current thread to see if
  * root of call comes from same package as package of handler - it's less effective so TLS is using here.
  */
-public final class LoggingThread {
+final class LoggingThread {
 
     private static ThreadLocal<LoggingThread> threadLocal = new ThreadLocal<LoggingThread>() {
         @Override

Modified: cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/package-info.java
URL: http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/package-info.java?rev=882564&r1=882563&r2=882564&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/package-info.java (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/ext/logging/package-info.java Fri Nov 20 14:16:31 2009
@@ -24,5 +24,8 @@
  * to this implementation applying <a href="www.slf4j.org">SLF4J</a> 
  * that JAXRS already depends on.
  */
+@javax.xml.bind.annotation.XmlSchema(xmlns = {
+        @javax.xml.bind.annotation.XmlNs(namespaceURI = "http://cxf.apache.org/jaxrs/log", prefix = "log")
+            })
 package org.apache.cxf.jaxrs.ext.logging;
 

Added: cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushSpringTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushSpringTest.java?rev=882564&view=auto
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushSpringTest.java (added)
+++ cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/JAXRSLoggingAtomPushSpringTest.java Fri Nov 20 14:16:31 2009
@@ -0,0 +1,110 @@
+/**
+ * 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.cxf.systest.jaxrs;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.abdera.model.Feed;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.testutil.common.AbstractClientServerTestBase;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class JAXRSLoggingAtomPushSpringTest extends AbstractClientServerTestBase {
+
+    private static List<Feed> retrieved = new ArrayList<Feed>();
+
+    @BeforeClass
+    public static void beforeClass() throws Exception {
+        // must be 'in-process' to communicate with inner class in single JVM
+        // and to spawn class SpringServer w/o using main() method
+        launchServer(SpringServer.class, true);
+    }
+
+    @Ignore
+    public static class SpringServer extends AbstractSpringServer {
+        public SpringServer() {
+            super("/jaxrs_logging_atompush");
+        }
+    }
+
+    @Before
+    public void before() {
+        retrieved.clear();
+    }
+
+    @Ignore
+    @Path("/")
+    public static class Resource {
+        private static final Logger LOG1 = LogUtils.getL7dLogger(Resource.class);
+        private static final Logger LOG2 = LogUtils.getL7dLogger(Resource.class, null, "namedLogger");
+
+        @GET
+        @Path("/log")
+        public void doLogging() {
+            LOG1.severe("severe message");
+            LOG1.warning("warning message");
+            LOG1.info("info message");
+            LogRecord r = new LogRecord(Level.FINE, "fine message");
+            r.setThrown(new IllegalArgumentException("tadaam"));
+            LOG1.log(r);
+            r = new LogRecord(Level.FINER, "finer message with {0} and {1}");
+            r.setParameters(new Object[] {
+                "param1", "param2"
+            });
+            r.setLoggerName("faky-logger");
+            LOG1.log(r);
+            LOG1.finest("finest message");
+
+            // for LOG2 only 'warning' and above messages should be logged
+            LOG2.severe("severe message");
+            LOG2.info("info message - should not pass!");
+            LOG2.finer("finer message - should not pass!");
+        }
+
+        // 2. ATOM push handler should populate logs here
+        @POST
+        @Path("/feed")
+        public void consume(Feed feed) {
+            // System.out.println(feed);
+            retrieved.add(feed);
+        }
+
+    }
+
+    @Test
+    public void testLogEvents() throws Exception {
+        WebClient wc = WebClient.create("http://localhost:9080");
+        wc.path("/log").get();
+        Thread.sleep(1000);
+        assertEquals(7, retrieved.size());
+    }
+}

Added: cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/beans.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/beans.xml?rev=882564&view=auto
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/beans.xml (added)
+++ cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/beans.xml Fri Nov 20 14:16:31 2009
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+	<!--
+		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.
+	-->
+	<!-- START SNIPPET: beans -->
+	<!--
+		beans xmlns="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns:simple="http://cxf.apache.org/simple" xsi:schemaLocation="
+		http://www.springframework.org/schema/beans
+		http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://cxf.apache.org/simple http://cxf.apache.org/schemas/simple.xsd"
+	-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
+	xmlns:aop="http://www.springframework.org/schema/aop"
+	xsi:schemaLocation="
+http://www.springframework.org/schema/beans 
+http://www.springframework.org/schema/beans/spring-beans.xsd
+http://cxf.apache.org/jaxrs
+http://cxf.apache.org/schemas/jaxrs.xsd">
+
+	<import resource="classpath:META-INF/cxf/cxf.xml" />
+	<import resource="classpath:META-INF/cxf/cxf-extension-jaxrs-binding.xml" />
+	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
+
+	<bean class="org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean"
+		init-method="init">
+		<property name="url" value="http://localhost:9080/feed" />
+		<!-- Mind the '$' instead of '.' for inner classes! -->
+		<property name="loggers"
+			value="
+			org.apache.cxf.systest.jaxrs.JAXRSLoggingAtomPushSpringTest$Resource:ALL,
+			namedLogger:WARN" />
+	</bean>
+
+	<!--  
+	Other config samples:
+	
+	<bean class="org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean"
+		init-method="init">
+
+		<property name="url" value="http://localhost:9080/feed" />
+		<property name="level" value="ALL" />
+	</bean>
+
+	<bean id="soapDeliverer" ... />
+	<bean class="org.apache.cxf.jaxrs.ext.logging.atom.AtomPushBean"
+		init-method="init">
+		<property name="deliverer">
+			<ref bean="soapDeliverer" />
+		</property>
+		<property name="loggers"
+			value="
+			  org.apache.cxf:DEBUG,
+			  org.apache.cxf.jaxrs:ALL,
+			  org.apache.cxf.bus:WARNING" />
+		<property name="batchSize" value="10" />
+	</bean>
+ 	-->
+ 	
+	<jaxrs:server id="atomserver" address="/">
+		<jaxrs:serviceBeans>
+			<ref bean="atombean" />
+		</jaxrs:serviceBeans>
+		<jaxrs:providers>
+			<ref bean="feed" />
+			<ref bean="entry" />
+		</jaxrs:providers>
+	</jaxrs:server>
+
+	<!-- Mind the '$' instead of '.' for inner classes! -->
+	<bean id="atombean"
+		class="org.apache.cxf.systest.jaxrs.JAXRSLoggingAtomPushSpringTest$Resource" />
+	<bean id="feed" class="org.apache.cxf.jaxrs.provider.AtomFeedProvider" />
+	<bean id="entry" class="org.apache.cxf.jaxrs.provider.AtomEntryProvider" />
+
+</beans>
+	<!-- END SNIPPET: beans -->
+

Added: cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/web.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/web.xml?rev=882564&view=auto
==============================================================================
--- cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/web.xml (added)
+++ cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_logging_atompush/WEB-INF/web.xml Fri Nov 20 14:16:31 2009
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE web-app
+    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+    "http://java.sun.com/dtd/web-app_2_3.dtd">
+<!--
+	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.
+-->
+<!-- START SNIPPET: webxml -->
+<web-app>
+	<context-param>
+		<param-name>contextConfigLocation</param-name>
+		<param-value>WEB-INF/beans.xml</param-value>
+	</context-param>
+
+	<listener>
+		<listener-class>
+			org.springframework.web.context.ContextLoaderListener
+		</listener-class>
+	</listener>
+
+	<servlet>
+		<servlet-name>CXFServlet</servlet-name>
+		<display-name>CXF Servlet</display-name>
+		<servlet-class>
+			org.apache.cxf.transport.servlet.CXFServlet
+		</servlet-class>
+		<load-on-startup>1</load-on-startup>
+	</servlet>
+	
+	<servlet-mapping>
+		<servlet-name>CXFServlet</servlet-name>
+		<url-pattern>/*</url-pattern>
+	</servlet-mapping>
+	
+</web-app>
+<!-- END SNIPPET: webxml -->