wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jra...@apache.org
Subject svn commit: r1027154 - in /incubator/wink/trunk: wink-common/src/main/java/org/apache/wink/common/internal/application/ wink-common/src/main/java/org/apache/wink/common/internal/log/ wink-common/src/main/java/org/apache/wink/common/internal/registry/ w...
Date Mon, 25 Oct 2010 14:54:09 GMT
Author: jramos
Date: Mon Oct 25 14:54:08 2010
New Revision: 1027154

URL: http://svn.apache.org/viewvc?rev=1027154&view=rev
Log:
[WINK-323] Improve logging and serviceability for Providers

Added:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationExceptionAttribute.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/LogUtils.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/Providers.java
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/log/
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/log/LogUtilsTest.java
Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/utils/ProviderUtils.java
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/InvokeMethodHandler.java
    incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/serviceability/ServiceabilityTest.java

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationExceptionAttribute.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationExceptionAttribute.java?rev=1027154&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationExceptionAttribute.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationExceptionAttribute.java Mon Oct 25 14:54:08 2010
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.wink.common.internal.application;
+
+/**
+ * 
+ * This class is strictly a holder for debug message(s) that originate
+ * from JAX-RS applications, NOT Wink engine, so that we log it once and only
+ * once under DEBUG.
+ * 
+ * This class should be used as a key to RuntimeContext.setAttribute call.
+ * Such a call should be made in cases where exceptions are caught at the boundary
+ * between Wink engine and application code.
+ * 
+ * RequestProcessor should send the debugMsg to the logger, only once.
+ * 
+ * See DebugResourceThrowsExceptionTest.
+ *
+ */
+public class ApplicationExceptionAttribute {
+
+    private String debugMsg;
+    
+    public ApplicationExceptionAttribute(String debugMsg) {
+        this.debugMsg = debugMsg;
+    }
+    
+    public String getDebugMsg() {
+        return debugMsg;
+    }
+    
+}

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/LogUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/LogUtils.java?rev=1027154&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/LogUtils.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/LogUtils.java Mon Oct 25 14:54:08 2010
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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.wink.common.internal.log;
+
+public class LogUtils {
+
+    /**
+     * Get a string containing the exception and stack of the specified exception.
+     *
+     * @param e
+     * @return
+     */
+    public static String exceptionToDebugString(Throwable e) {
+        String text = e.getClass().getName() + ": " + e.getMessage() + System.getProperty("line.separator");
+        text += stackToDebugString(e);
+        return text;
+    }
+    
+    /**
+     * Get a string containing the stack of the specified exception.
+     * Careful: this method skips to the first "at" in the exception
+     * stack; it does NOT report the exception itself.
+     *
+     * @param e
+     * @return
+     */
+    public static String stackToDebugString(Throwable e) {
+        java.io.StringWriter sw = new java.io.StringWriter();
+        java.io.BufferedWriter bw = new java.io.BufferedWriter(sw);
+        java.io.PrintWriter pw = new java.io.PrintWriter(bw);
+        e.printStackTrace(pw);
+        pw.close();
+        String text = sw.getBuffer().toString();
+        // Jump past the throwable
+        text = "\t" + text.substring(text.indexOf("at "));
+        // stop at the servlet or filter, which is the entry point for Wink -- no need to log all the container or JVM stuff
+        // find line of entry:
+        int entryIndex = text.indexOf("at org.apache.wink.server.internal.servlet");
+        int endOfEntryLineIndex = text.indexOf(System.getProperty("line.separator"), entryIndex);
+        text = text.substring(0, endOfEntryLineIndex);
+        text = replace(text, "at ", "DEBUG_FRAME = ");
+        return text;
+    }
+
+    /**
+     * replace: Like String.replace except that the old and new items are strings.
+     *
+     * @param name string
+     * @param oldT old text to replace
+     * @param newT new text to use
+     * @return replacement string
+     */
+    private static final String replace(String name,
+                                       String oldT, String newT) {
+
+        if (name == null) return "";
+
+        // Create a string buffer that is twice initial length.
+        // This is a good starting point.
+        StringBuffer sb = new StringBuffer(name.length() * 2);
+
+        int len = oldT.length();
+        try {
+            int start = 0;
+            int i = name.indexOf(oldT, start);
+
+            while (i >= 0) {
+                sb.append(name.substring(start, i));
+                sb.append(newT);
+                start = i + len;
+                i = name.indexOf(oldT, start);
+            }
+            if (start < name.length()) {
+                sb.append(name.substring(start));
+            }
+        } catch (NullPointerException e) {
+            // nothing
+        }
+
+        return new String(sb);
+    }
+
+    
+}

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/Providers.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/Providers.java?rev=1027154&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/Providers.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/log/Providers.java Mon Oct 25 14:54:08 2010
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.wink.common.internal.log;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.MessageBodyWriter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Providers {
+
+    private static final Logger                logger = LoggerFactory.getLogger(Providers.class);
+
+    private Map<MessageBodyReader<?>, Boolean> mbrs   = null;
+    private Map<MessageBodyWriter<?>, Boolean> mbws   = null;
+
+    public void addMessageBodyReader(MessageBodyReader<?> reader, boolean result) {
+        if (this.mbrs == null) {
+            this.mbrs = new LinkedHashMap<MessageBodyReader<?>, Boolean>();
+        }
+        this.mbrs.put(reader, result);
+    }
+
+    public void addMessageBodyWriter(MessageBodyWriter<?> writer, boolean result) {
+        if (this.mbws == null) {
+            this.mbws = new LinkedHashMap<MessageBodyWriter<?>, Boolean>();
+        }
+        this.mbws.put(writer, result);
+    }
+
+    public void log() {
+        if (logger.isDebugEnabled()) {
+            if (this.mbrs != null && this.mbrs.size() > 0) {
+                String providerResults = "";
+                for (MessageBodyReader<?> mbr : this.mbrs.keySet()) {
+                    providerResults +=
+                        ("\n" + mbr.getClass().getCanonicalName() + ".isReadable() returned " + this.mbrs
+                            .get(mbr));
+                }
+                logger.debug(providerResults);
+            }
+
+            if (this.mbws != null && this.mbws.size() > 0) {
+                String providerResults = "";
+                for (MessageBodyWriter<?> mbw : this.mbws.keySet()) {
+                    providerResults +=
+                        ("\n" + mbw.getClass().getCanonicalName() + ".isWritable() returned " + this.mbws
+                            .get(mbw));
+                }
+                logger.debug(providerResults);
+            }
+        }
+    }
+}

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java?rev=1027154&r1=1027153&r2=1027154&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/registry/ProvidersRegistry.java Mon Oct 25 14:54:08 2010
@@ -26,6 +26,7 @@ import java.lang.reflect.Proxy;
 import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -49,10 +50,12 @@ import org.apache.wink.common.internal.a
 import org.apache.wink.common.internal.i18n.Messages;
 import org.apache.wink.common.internal.lifecycle.LifecycleManagersRegistry;
 import org.apache.wink.common.internal.lifecycle.ObjectFactory;
+import org.apache.wink.common.internal.log.Providers;
 import org.apache.wink.common.internal.utils.AnnotationUtils;
 import org.apache.wink.common.internal.utils.GenericsUtils;
 import org.apache.wink.common.internal.utils.MediaTypeUtils;
 import org.apache.wink.common.internal.utils.SoftConcurrentMap;
+import org.apache.wink.common.utils.ProviderUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -65,28 +68,28 @@ import org.slf4j.LoggerFactory;
  */
 public class ProvidersRegistry {
 
-    private static final Logger                                 logger             =
-                                                                                       LoggerFactory
-                                                                                           .getLogger(ProvidersRegistry.class);
-
-    private final ProducesMediaTypeMap<ContextResolver<?>>      contextResolvers   =
-                                                                                       new ProducesMediaTypeMap<ContextResolver<?>>(
-                                                                                                                                    ContextResolver.class);
+    private static final Logger                                         logger             =
+                                                                                               LoggerFactory
+                                                                                                   .getLogger(ProvidersRegistry.class);
+
+    private final ProducesMediaTypeMap<ContextResolver<?>>              contextResolvers   =
+                                                                                               new ProducesMediaTypeMap<ContextResolver<?>>(
+                                                                                                                                            ContextResolver.class);
     /*
      * need exception mappers to be volatile for publication purposes
      */
-    private volatile TreeSet<ObjectFactory<ExceptionMapper<?>>> exceptionMappers   =
-                                                                                       new TreeSet<ObjectFactory<ExceptionMapper<?>>>(
-                                                                                                                                      Collections
-                                                                                                                                          .reverseOrder());
-    private final ConsumesMediaTypeMap<MessageBodyReader<?>>    messageBodyReaders =
-                                                                                       new ConsumesMediaTypeMap<MessageBodyReader<?>>(
-                                                                                                                                      MessageBodyReader.class);
-    private final ProducesMediaTypeMap<MessageBodyWriter<?>>    messageBodyWriters =
-                                                                                       new ProducesMediaTypeMap<MessageBodyWriter<?>>(
-                                                                                                                                      MessageBodyWriter.class);
-    private final ApplicationValidator                          applicationValidator;
-    private final LifecycleManagersRegistry                     factoryFactoryRegistry;
+    private volatile TreeSet<PriorityObjectFactory<ExceptionMapper<?>>> exceptionMappers   =
+                                                                                               new TreeSet<PriorityObjectFactory<ExceptionMapper<?>>>(
+                                                                                                                                                      Collections
+                                                                                                                                                          .reverseOrder());
+    private final ConsumesMediaTypeMap<MessageBodyReader<?>>            messageBodyReaders =
+                                                                                               new ConsumesMediaTypeMap<MessageBodyReader<?>>(
+                                                                                                                                              MessageBodyReader.class);
+    private final ProducesMediaTypeMap<MessageBodyWriter<?>>            messageBodyWriters =
+                                                                                               new ProducesMediaTypeMap<MessageBodyWriter<?>>(
+                                                                                                                                              MessageBodyWriter.class);
+    private final ApplicationValidator                                  applicationValidator;
+    private final LifecycleManagersRegistry                             factoryFactoryRegistry;
 
     public ProvidersRegistry(LifecycleManagersRegistry factoryRegistry,
                              ApplicationValidator applicationValidator) {
@@ -139,10 +142,10 @@ public class ProvidersRegistry {
         }
         if (ExceptionMapper.class.isAssignableFrom(cls)) {
             logger.trace("Adding type {} to ExceptionMappers list", cls); //$NON-NLS-1$
-            TreeSet<ObjectFactory<ExceptionMapper<?>>> exceptionMappersCopy =
-                new TreeSet<ObjectFactory<ExceptionMapper<?>>>(Collections.reverseOrder());
+            TreeSet<PriorityObjectFactory<ExceptionMapper<?>>> exceptionMappersCopy =
+                new TreeSet<PriorityObjectFactory<ExceptionMapper<?>>>(Collections.reverseOrder());
             exceptionMappersCopy.addAll(exceptionMappers);
-            exceptionMappersCopy.add((ObjectFactory<ExceptionMapper<?>>)objectFactory);
+            exceptionMappersCopy.add((PriorityObjectFactory<ExceptionMapper<?>>)objectFactory);
             exceptionMappers = exceptionMappersCopy;
             retValue = true;
         }
@@ -173,6 +176,32 @@ public class ProvidersRegistry {
         return addProvider(provider, WinkApplication.DEFAULT_PRIORITY);
     }
 
+    public List<ProviderRecord<?>> getMessageBodyWriterRecords() {
+        return new ArrayList<ProviderRecord<?>>(messageBodyWriters.getProviderRecords());
+    }
+
+    public List<ProviderRecord<?>> getMessageBodyReaderRecords() {
+        return new ArrayList<ProviderRecord<?>>(messageBodyReaders.getProviderRecords());
+    }
+
+    public List<ProviderRecord<?>> getExceptionMapperRecords() {
+        ArrayList<ProviderRecord<?>> recordList = new ArrayList<ProviderRecord<?>>();
+
+        for (PriorityObjectFactory<ExceptionMapper<?>> factory : exceptionMappers) {
+            ProviderRecord<?> record =
+                new ProviderRecord<ExceptionMapper<?>>(factory.getInstanceClass(), null,
+                                                       ExceptionMapper.class,
+                                                       factory.isSystemProvider);
+            recordList.add(record);
+        }
+
+        return recordList;
+    }
+
+    public List<ProviderRecord<?>> getContextResolverRecords() {
+        return new ArrayList<ProviderRecord<?>>(contextResolvers.getProviderRecords());
+    }
+
     /**
      * Removes all providers in the registry.
      */
@@ -378,24 +407,20 @@ public class ProvidersRegistry {
             messageBodyReaders.getProvidersByMediaType(mediaType, type);
 
         logger.trace("Found possible MessageBodyReader ObjectFactories {}", factories); //$NON-NLS-1$
-        for (ObjectFactory<MessageBodyReader<?>> factory : factories) {
+        Providers providersLogger = new Providers();
+        MessageBodyReader<T> ret = null;
+        for (MediaTypeMap<MessageBodyReader<?>>.OFHolder<MessageBodyReader<?>> factory : factories) {
             MessageBodyReader<?> reader = factory.getInstance(runtimeContext);
-            if (logger.isTraceEnabled()) {
-                List<Annotation> anns = (annotations == null) ? null : Arrays.asList(annotations);
-                logger.trace("Calling {}.isReadable( {}, {}, {}, {} )", new Object[] {reader, type, //$NON-NLS-1$
-                    genericType, anns, mediaType});
-            }
-            if (reader.isReadable(type, genericType, annotations, mediaType)) {
-                if (logger.isTraceEnabled()) {
-                    List<Annotation> anns =
-                        (annotations == null) ? null : Arrays.asList(annotations);
-                    logger.trace("{}.isReadable( {}, {}, {}, {} ) returned true", new Object[] { //$NON-NLS-1$
-                                 reader, type, genericType, anns, mediaType});
-                }
-                return (MessageBodyReader<T>)reader;
+            if (isReadable(reader, type, genericType, annotations, mediaType, runtimeContext, factory.isSystemProvider)) {
+                ret = (MessageBodyReader<T>)reader;
+                providersLogger.addMessageBodyReader(reader, true);
+                break;
+            } else {
+                providersLogger.addMessageBodyReader(reader, false);
             }
         }
-        return null;
+        providersLogger.log();
+        return ret;
     }
 
     @SuppressWarnings("unchecked")
@@ -419,31 +444,32 @@ public class ProvidersRegistry {
         List<MediaTypeMap<MessageBodyWriter<?>>.OFHolder<MessageBodyWriter<?>>> writersFactories =
             messageBodyWriters.getProvidersByMediaType(mediaType, type);
         logger.trace("Found possible MessageBodyWriter ObjectFactories {}", writersFactories); //$NON-NLS-1$
-        for (ObjectFactory<MessageBodyWriter<?>> factory : writersFactories) {
+        Providers providersLogger = new Providers();
+        MessageBodyWriter<T> ret = null;
+        for (MediaTypeMap<MessageBodyWriter<?>>.OFHolder<MessageBodyWriter<?>> factory : writersFactories) {
             MessageBodyWriter<?> writer = factory.getInstance(runtimeContext);
-            if (logger.isTraceEnabled()) {
-                List<Annotation> anns = (annotations == null) ? null : Arrays.asList(annotations);
-                logger
-                    .trace("Calling {}.isWriteable( {}, {}, {}, {} )", new Object[] {writer, type, //$NON-NLS-1$
-                        genericType, anns, mediaType});
-            }
-            if (writer.isWriteable(type, genericType, annotations, mediaType)) {
+            if (isWriteable(writer, type, genericType, annotations, mediaType, runtimeContext, factory.isSystemProvider)) {
                 if (logger.isTraceEnabled()) {
                     List<Annotation> anns =
                         (annotations == null) ? null : Arrays.asList(annotations);
                     logger.trace("{}.isWriteable( {}, {}, {}, {} ) returned true", new Object[] { //$NON-NLS-1$
                                  writer, type, genericType, anns, mediaType});
                 }
-                return (MessageBodyWriter<T>)writer;
+                ret = (MessageBodyWriter<T>)writer;
+                providersLogger.addMessageBodyWriter(writer, true);
+                break;
+            } else {
+                providersLogger.addMessageBodyWriter(writer, false);
             }
         }
-        if (logger.isTraceEnabled()) {
+        if (ret == null && logger.isTraceEnabled()) {
             List<Annotation> anns = (annotations == null) ? null : Arrays.asList(annotations);
             logger
                 .trace("No MessageBodyWriter returned true for isWriteable( {}, {}, {}, {} )", new Object[] { //$NON-NLS-1$
                        type, genericType, anns, mediaType});
         }
-        return null;
+        providersLogger.log();
+        return ret;
     }
 
     public Set<MediaType> getMessageBodyReaderMediaTypesLimitByIsReadable(Class<?> type,
@@ -456,7 +482,7 @@ public class ProvidersRegistry {
         logger.trace("Found all MessageBodyReader ObjectFactories limited by class type {}", //$NON-NLS-1$
                      readerFactories);
         Annotation[] ann = new Annotation[0];
-        for (ObjectFactory<MessageBodyReader<?>> factory : readerFactories) {
+        for (MediaTypeMap<MessageBodyReader<?>>.OFHolder<MessageBodyReader<?>> factory : readerFactories) {
             MessageBodyReader<?> reader = factory.getInstance(runtimeContext);
             Consumes consumes = factory.getInstanceClass().getAnnotation(Consumes.class);
             String[] values = null;
@@ -467,12 +493,7 @@ public class ProvidersRegistry {
             }
             for (String v : values) {
                 MediaType mt = MediaType.valueOf(v);
-                if (logger.isTraceEnabled()) {
-                    List<Annotation> anns = (ann == null) ? null : Arrays.asList(ann);
-                    logger.trace("Calling {}.isReadable( {}, {}, {}, {} )", new Object[] {reader, //$NON-NLS-1$
-                        type, type, anns, mt});
-                }
-                if (reader.isReadable(type, type, ann, mt)) {
+                if (isReadable(reader, type, type, ann, mt, runtimeContext, factory.isSystemProvider)) {
                     logger.trace("Adding {} to media type set", mt); //$NON-NLS-1$
                     mediaTypes.add(mt);
                 }
@@ -487,7 +508,6 @@ public class ProvidersRegistry {
 
     public MediaType getMessageBodyWriterMediaTypeLimitByIsWritable(Class<?> type,
                                                                     RuntimeContext runtimeContext) {
-        List<MediaType> mediaTypes = new ArrayList<MediaType>();
         logger.trace("Searching MessageBodyWriters media types limited by class type {}", type); //$NON-NLS-1$
 
         List<MediaTypeMap<MessageBodyWriter<?>>.OFHolder<MessageBodyWriter<?>>> writerFactories =
@@ -495,7 +515,7 @@ public class ProvidersRegistry {
         logger.trace("Found all MessageBodyWriter ObjectFactories limited by class type {}", //$NON-NLS-1$
                      writerFactories);
         Annotation[] ann = new Annotation[0];
-        for (ObjectFactory<MessageBodyWriter<?>> factory : writerFactories) {
+        for (MediaTypeMap<MessageBodyWriter<?>>.OFHolder<MessageBodyWriter<?>> factory : writerFactories) {
             MessageBodyWriter<?> writer = factory.getInstance(runtimeContext);
             Produces produces = factory.getInstanceClass().getAnnotation(Produces.class);
             String[] values = null;
@@ -506,12 +526,7 @@ public class ProvidersRegistry {
             }
             for (String v : values) {
                 MediaType mt = MediaType.valueOf(v);
-                if (logger.isTraceEnabled()) {
-                    List<Annotation> anns = (ann == null) ? null : Arrays.asList(ann);
-                    logger.trace("Calling {}.isWritable( {}, {}, {}, {} )", new Object[] {writer, //$NON-NLS-1$
-                        type, type, anns, mt});
-                }
-                if (writer.isWriteable(type, type, ann, mt)) {
+                if (isWriteable(writer, type, type, ann, mt, runtimeContext, factory.isSystemProvider)) {
                     logger.trace("Returning media type {}", mt); //$NON-NLS-1$
                     return mt;
                 }
@@ -520,6 +535,59 @@ public class ProvidersRegistry {
         return null;
     }
 
+    /**
+     * @param factory
+     * @param type
+     * @param ann
+     * @param reader
+     * @param mt
+     * @param runtimeContext
+     * @return
+     */
+    private boolean isReadable(
+            MessageBodyReader<?> reader,
+            Class<?> type, Type genericType, Annotation[] ann,
+            MediaType mt, RuntimeContext runtimeContext, boolean isSystemProvider) {
+        if (logger.isTraceEnabled()) {
+            List<Annotation> anns = (ann == null) ? null : Arrays.asList(ann);
+            logger.trace("Calling {}.isReadable( {}, {}, {}, {} )", new Object[] {reader, //$NON-NLS-1$
+                type, genericType, anns, mt});
+        }
+        try {
+            return reader.isReadable(type, genericType, ann, mt);
+        } catch (RuntimeException ex) {
+            ProviderUtils.logUserProviderException(ex, reader, ProviderUtils.PROVIDER_EXCEPTION_ORIGINATOR.isReadable, new Object[]{type, genericType, ann, mt}, runtimeContext);
+            throw ex;
+        }
+    }
+
+
+    /**
+     * @param factory
+     * @param type
+     * @param genericType
+     * @param ann
+     * @param mt
+     * @param runtimeContext
+     * @return
+     */
+    private boolean isWriteable(
+            MessageBodyWriter<?> writer,
+            Class<?> type, Type genericType, Annotation[] ann, 
+            MediaType mt, RuntimeContext runtimeContext, boolean isSystemProvider) {
+        if (logger.isTraceEnabled()) {
+            List<Annotation> anns = (ann == null) ? null : Arrays.asList(ann);
+            logger.trace("Calling {}.isWritable( {}, {}, {}, {} )", new Object[] {writer, //$NON-NLS-1$
+                type, genericType, anns, mt});
+        }
+        try {
+            return writer.isWriteable(type, genericType, ann, mt);
+        } catch (RuntimeException ex) {
+            ProviderUtils.logUserProviderException(ex, writer, ProviderUtils.PROVIDER_EXCEPTION_ORIGINATOR.isWriteable, new Object[]{type, genericType, ann, mt}, runtimeContext);
+            throw ex;
+        }
+    }
+
     public Set<MediaType> getMessageBodyWriterMediaTypes(Class<?> type) {
         if (type == null) {
             throw new NullPointerException(Messages.getMessage("variableIsNull", "type")); //$NON-NLS-1$ //$NON-NLS-2$
@@ -646,6 +714,23 @@ public class ProvidersRegistry {
             return list;
         }
 
+        public Collection<ProviderRecord<T>> getProviderRecords() {
+            List<ProviderRecord<T>> compatible = new ArrayList<ProviderRecord<T>>();
+
+            Entry<MediaType, HashSet<PriorityObjectFactory<T>>>[] registryEntrySet = entrySet;
+            for (Entry<MediaType, HashSet<PriorityObjectFactory<T>>> entry : registryEntrySet) {
+                TreeSet<PriorityObjectFactory<T>> entries =
+                    new TreeSet<PriorityObjectFactory<T>>(Collections.reverseOrder());
+                entries.addAll(entry.getValue());
+
+                for (PriorityObjectFactory<T> of : entries) {
+                    compatible.add(new ProviderRecord<T>(of.getInstanceClass(), entry.getKey(),
+                                                         rawType, of.isSystemProvider));
+                }
+            }
+            return compatible;
+        }
+
         private List<OFHolder<T>> internalGetProvidersByMediaType(MediaType mediaType, Class<?> cls) {
             Set<OFHolder<T>> compatible = new TreeSet<OFHolder<T>>(Collections.reverseOrder());
             for (Entry<MediaType, HashSet<PriorityObjectFactory<T>>> entry : entrySet) {
@@ -707,8 +792,8 @@ public class ProvidersRegistry {
             }
             copyOfMap.put(key, set);
             if (!set.add(objectFactory)) {
-                if (logger.isWarnEnabled()) {
-                    logger.warn(Messages.getMessage("mediaTypeSetAlreadyContains", objectFactory)); //$NON-NLS-1$
+                if (logger.isTraceEnabled()) {
+                    logger.trace(Messages.getMessage("mediaTypeSetAlreadyContains", objectFactory)); //$NON-NLS-1$
                 }
             } else {
 
@@ -747,11 +832,12 @@ public class ProvidersRegistry {
         public String toString() {
             return toString("  ", false, true); //$NON-NLS-1$
         }
-        
+
         /**
-         * 
          * @param userOnly only print user-defined entities
-         * @param trace if calling toString as part of debugging, use trace=false, if as part of trace or any other reason, use trace=true
+         * @param trace if calling toString as part of debugging, use
+         *            trace=false, if as part of trace or any other reason, use
+         *            trace=true
          * @return
          */
         public String toString(boolean userOnly, boolean trace) {
@@ -759,10 +845,11 @@ public class ProvidersRegistry {
         }
 
         /**
-         * 
          * @param indent how far to indent output
          * @param userOnly only log user-defined entities
-         * @param trace if calling toString as part of debugging, use trace=false, if as part of trace or any other reason, use trace=true (debug prints slightly less verbose)
+         * @param trace if calling toString as part of debugging, use
+         *            trace=false, if as part of trace or any other reason, use
+         *            trace=true (debug prints slightly less verbose)
          * @return
          */
         protected String toString(String indent, boolean userOnly, boolean trace) {
@@ -787,12 +874,16 @@ public class ProvidersRegistry {
                     // Separate each ObjectFactory entry in the Set
                     // into its own line
                     for (ObjectFactory<T> of : data.get(k)) {
-                        // assuming everything in the org.apache.wink.* package space with "internal" in package name is system, not user
+                        // assuming everything in the org.apache.wink.* package
+                        // space with "internal" in package name is system, not
+                        // user
                         String instanceClassName = of.getInstanceClass().getName();
-                        if ((userOnly && !(instanceClassName.startsWith("org.apache.wink.common.internal.") || instanceClassName.startsWith("org.apache.wink.server.internal."))) || !userOnly) { //$NON-NLS-1$ $NON-NLS-2$
+                        if ((userOnly && !(instanceClassName
+                            .startsWith("org.apache.wink.common.internal.") || instanceClassName.startsWith("org.apache.wink.server.internal."))) || !userOnly) { //$NON-NLS-1$ $NON-NLS-2$
                             userItemFound = true;
                             sb_map.append(indent);
-                            if (trace) { // trace, print full ObjectFactory.toString()
+                            if (trace) { // trace, print full
+                                // ObjectFactory.toString()
                                 sb_map.append(of);
                             } else { // debug, print slightly less information
                                 sb_map.append(of.getInstanceClass());
@@ -811,6 +902,7 @@ public class ProvidersRegistry {
             return sb.toString();
         }
 
+        @SuppressWarnings("hiding")
         class OFHolder<T> implements ObjectFactory<T>, Comparable<OFHolder<T>> {
 
             private final PriorityObjectFactory<T> of;
@@ -963,24 +1055,64 @@ public class ProvidersRegistry {
 
         @Override
         public String toString() {
-            return String.format("Priority: %f, ObjectFactory: %s", priority, of.toString().replace("class ", "")); //$NON-NLS-1$
+            return String
+                .format("Priority: %f, ObjectFactory: %s", priority, of.toString().replace("class ", "")); //$NON-NLS-1$
         }
     }
-    
+
+    public static class ProviderRecord<T> {
+
+        private final MediaType mediaType;
+        private final Class<?>  genericType;
+        private final boolean   isSystemProvider;
+        private final Class<T>  providerClass;
+
+        public ProviderRecord(Class<T> providerClass,
+                              MediaType mediaType,
+                              Class<?> rawType,
+                              boolean isSystemProvider) {
+            super();
+            this.mediaType = mediaType;
+            this.isSystemProvider = isSystemProvider;
+            this.providerClass = providerClass;
+            Type t = GenericsUtils.getGenericInterfaceParamType(providerClass, rawType);
+            if (t == null) {
+                this.genericType = Object.class;
+            } else {
+                this.genericType = GenericsUtils.getClassType(t);
+            }
+        }
+
+        public MediaType getMediaType() {
+            return mediaType;
+        }
+
+        public Class<?> getGenericType() {
+            return genericType;
+        }
+
+        public boolean isSystemProvider() {
+            return isSystemProvider;
+        }
+
+        public Class<T> getProviderClass() {
+            return providerClass;
+        }
+    }
+
     /**
-     * 
      * @param userOnly true = log user providers only, false = log all providers
      */
     public String getLogFormattedProvidersList(boolean userOnly) {
         StringBuffer sb = new StringBuffer();
-        sb.append(this.contextResolvers.toString(userOnly, false));
         sb.append(this.messageBodyReaders.toString(userOnly, false));
         sb.append(this.messageBodyWriters.toString(userOnly, false));
+        sb.append(this.contextResolvers.toString(userOnly, false));
         if (userOnly) {
             return Messages.getMessage("followingProvidersUserDefined", sb.toString());
         } else {
             return Messages.getMessage("followingProviders", sb.toString());
         }
     }
-
+    
 }

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/utils/ProviderUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/utils/ProviderUtils.java?rev=1027154&r1=1027153&r2=1027154&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/utils/ProviderUtils.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/utils/ProviderUtils.java Mon Oct 25 14:54:08 2010
@@ -34,6 +34,7 @@ import java.lang.reflect.Type;
 import java.nio.charset.Charset;
 import java.nio.charset.IllegalCharsetNameException;
 import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
 import java.util.List;
 
 import javax.ws.rs.core.HttpHeaders;
@@ -43,8 +44,11 @@ import javax.ws.rs.ext.MessageBodyReader
 import javax.ws.rs.ext.MessageBodyWriter;
 import javax.ws.rs.ext.Providers;
 
+import org.apache.wink.common.RuntimeContext;
 import org.apache.wink.common.internal.MultivaluedMapImpl;
+import org.apache.wink.common.internal.application.ApplicationExceptionAttribute;
 import org.apache.wink.common.internal.http.AcceptCharset;
+import org.apache.wink.common.internal.log.LogUtils;
 import org.apache.wink.common.internal.utils.SoftConcurrentMap;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,6 +64,15 @@ public class ProviderUtils {
                                                                             new SoftConcurrentMap<String, Boolean>();
     private static SoftConcurrentMap<String, String>  preferredCharsets =
                                                                             new SoftConcurrentMap<String, String>();
+    
+    public static enum PROVIDER_EXCEPTION_ORIGINATOR {
+        isReadable,
+        readFrom,
+        getSize,
+        isWriteable,
+        writeTo,
+        getContext
+    }
 
     public static String getCharsetOrNull(MediaType m) {
         String name = (m == null) ? null : m.getParameters().get("charset"); //$NON-NLS-1$
@@ -281,4 +294,47 @@ public class ProviderUtils {
         }
         return reader.readFrom(type, genericType, new Annotation[0], mediaType, httpHeaders, is);
     }
+    
+    public static void logUserProviderException(RuntimeException e,
+            Object obj, // MessageBodyReader or MessageBodyWriter
+            PROVIDER_EXCEPTION_ORIGINATOR originator,
+            Object[] methodParams,
+            RuntimeContext context) {
+        
+        try {
+        
+            if (context.getAttribute(ApplicationExceptionAttribute.class) != null) {
+                // exception from application code has already been recorded to the RuntimeContext, don't record it again.
+                return;
+            }
+
+            List<Object> dataToFormattedString = new ArrayList<Object>();
+            dataToFormattedString.add(e.getClass().getName());
+            dataToFormattedString.add(e.getMessage());
+            dataToFormattedString.add(obj.getClass().getName());
+            dataToFormattedString.add(originator);
+            for (int i = 0; i < methodParams.length; i++) {
+                dataToFormattedString.add(methodParams[i]);
+            }
+            // send exception through stackToString because it may have been intentionally thrown
+            // from provider method; we don't want to scare the log readers, so it's recorded as DEBUG
+            dataToFormattedString.add(LogUtils.stackToDebugString(e));
+
+            String debugMsgFormat = "%s with message \"%s\" was encountered during invocation of method %s.%s( ";
+            for (int i = 0; i < methodParams.length; i++) {
+                debugMsgFormat += "%s";
+                if (i < methodParams.length) {
+                    debugMsgFormat += ", ";
+                }
+            }
+            String newLine = System.getProperty("line.separator"); //$NON-NLS-1$
+            debugMsgFormat += " )" + newLine + "%s";
+
+            String debugMsg = String.format(debugMsgFormat, dataToFormattedString.toArray(new Object[]{}));
+            context.setAttribute(ApplicationExceptionAttribute.class, new ApplicationExceptionAttribute(debugMsg));
+        } catch (Throwable t) {
+            // just to be extra super duper cautious.  It'll still be logged, just not via the format above.
+            logger.trace("Could not format log output for exception originating in provider.", t);
+        }
+    }
 }

Added: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/log/LogUtilsTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/log/LogUtilsTest.java?rev=1027154&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/log/LogUtilsTest.java (added)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/log/LogUtilsTest.java Mon Oct 25 14:54:08 2010
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.wink.common.internal.log;
+
+import javax.ws.rs.WebApplicationException;
+
+import junit.framework.TestCase;
+
+
+public class LogUtilsTest extends TestCase {
+
+    public void testExceptionToDebugString() {
+        Exception e = new WebApplicationException(new NullPointerException("hi"));
+        String estack = LogUtils.exceptionToDebugString(e);
+        System.out.println(estack);
+        // should print first line in stack:
+        assertTrue(estack.contains(WebApplicationException.class.getName()));
+        // make sure "hi" is printed on the first line:
+        assertEquals(69, estack.indexOf("hi"));
+    }
+    
+    public void testStackToDebugString() {
+        Exception e = new WebApplicationException(new NullPointerException("hi"));
+        String estack = LogUtils.stackToDebugString(e);
+        System.out.println(estack);
+        // should not print first line in stack:
+        assertTrue(!estack.contains(WebApplicationException.class.getName()));
+    }
+    
+}

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/InvokeMethodHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/InvokeMethodHandler.java?rev=1027154&r1=1027153&r2=1027154&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/InvokeMethodHandler.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/InvokeMethodHandler.java Mon Oct 25 14:54:08 2010
@@ -23,8 +23,11 @@ import java.lang.reflect.InvocationTarge
 import java.lang.reflect.Method;
 import java.util.Arrays;
 
+import org.apache.wink.common.internal.application.ApplicationExceptionAttribute;
+import org.apache.wink.common.internal.log.LogUtils;
 import org.apache.wink.server.handlers.AbstractHandler;
 import org.apache.wink.server.handlers.MessageContext;
+//import org.apache.wink.server.internal.log.ResourceInvocation.ResourceInvocationData;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -34,11 +37,15 @@ public class InvokeMethodHandler extends
 
     @Override
     public void handleRequest(MessageContext context) throws Throwable {
+        // vars declared outside of try block so we can log them in case of exception
+        Method javaMethod = null;
+        Object instance = null;
+        Object[] parameters = null;
         try {
             SearchResult searchResult = context.getAttribute(SearchResult.class);
-            Method javaMethod = searchResult.getMethod().getMetadata().getReflectionMethod();
-            Object[] parameters = searchResult.getInvocationParameters();
-            Object instance = searchResult.getResource().getInstance(context);
+            javaMethod = searchResult.getMethod().getMetadata().getReflectionMethod();
+            parameters = searchResult.getInvocationParameters();
+            instance = searchResult.getResource().getInstance(context);
             if (logger.isTraceEnabled()) {
                 logger
                     .trace("Invoking method {} of declaring class {} on the instance of a class {}@{} with parameters {}", //$NON-NLS-1$
@@ -48,12 +55,38 @@ public class InvokeMethodHandler extends
                                Integer.toHexString(System.identityHashCode(instance)),
                                Arrays.toString(parameters)});
             }
+//            ResourceInvocationData resInvocationData =
+//                context.getAttribute(ResourceInvocationData.class);
+//            if (resInvocationData != null) {
+//                resInvocationData.addInvocation(context);
+//            }
             Object result = javaMethod.invoke(instance, parameters);
             context.setResponseEntity(result);
         } catch (InvocationTargetException ite) {
-            logger.trace("Exception encountered during invocation:", ite.getTargetException()); //$NON-NLS-1$
+            try {
+                String newLine = System.getProperty("line.separator"); //$NON-NLS-1$
+                String debugMsg = String.format("%s with message \"%s\" was encountered during invocation of method %s of declaring class %s on the instance of a class %s@%s with parameters %s" + newLine + "%s", //$NON-NLS-1$ $NON-NLS-2$
+                        new Object[] {
+                        ite.getTargetException().getClass().getName(),
+                        ite.getTargetException().getMessage(),
+                        javaMethod == null ? "UNKNOWN" : javaMethod.getName(), //$NON-NLS-1$
+                        javaMethod == null ? "UNKNOWN" : javaMethod.getDeclaringClass().getName(), //$NON-NLS-1$
+                        instance == null ? "UNKNOWN" : instance.getClass().getName(), //$NON-NLS-1$
+                        instance == null ? "UNKNOWN" : Integer.toHexString(System.identityHashCode(instance)), //$NON-NLS-1$
+                        parameters == null ? "UNKNOWN" : Arrays.toString(parameters), //$NON-NLS-1$
+                        // send exception through stackToString because it may have been intentionally thrown
+                        // from resource method; we don't want to scare the log readers, so it's recorded as DEBUG
+                        LogUtils.stackToDebugString(ite.getTargetException())
+                        }
+                );
+                context.setAttribute(ApplicationExceptionAttribute.class, new ApplicationExceptionAttribute(debugMsg));
+            } catch (Throwable t) {
+                // just to be extra super duper cautious.  It'll still be logged, just not via the format above.
+                logger.trace("Could not format log output for exception originating in provider.", t);
+            }
+                
             throw ite.getTargetException(); // unpack the original exception
         }
     }
-
+    
 }

Modified: incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/serviceability/ServiceabilityTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/serviceability/ServiceabilityTest.java?rev=1027154&r1=1027153&r2=1027154&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/serviceability/ServiceabilityTest.java (original)
+++ incubator/wink/trunk/wink-server/src/test/java/org/apache/wink/server/serviceability/ServiceabilityTest.java Mon Oct 25 14:54:08 2010
@@ -157,11 +157,11 @@ public class ServiceabilityTest extends 
         assertEquals("Registered resources: \n" +
                 "  Path: myapp; ClassMetadata: Class: org.apache.wink.server.serviceability.ServiceabilityTest$MyApp$MyAppResource", records.get(1).getMessage());
         assertEquals("The following user-defined JAX-RS providers are registered: \n" +
-                "RawType: interface javax.ws.rs.ext.ContextResolver\n" +
-                "Data Map: {empty}\n" +
                 "RawType: interface javax.ws.rs.ext.MessageBodyReader\n" +
                 "Data Map: {empty}\n" +
                 "RawType: interface javax.ws.rs.ext.MessageBodyWriter\n" +
+                "Data Map: {empty}\n" +
+                "RawType: interface javax.ws.rs.ext.ContextResolver\n" +
                 "Data Map: {empty}", records.get(2).getMessage());
     }
     
@@ -177,7 +177,7 @@ public class ServiceabilityTest extends 
         WinkLogHandler.turnLoggingCaptureOff();
         ArrayList<LogRecord> records = WinkLogHandler.getRecords();
         
-        assertEquals(1, records.size());
+        assertEquals(2, records.size());
         assertEquals("Processing GET request to http://localhost:80/root, source content type is null, acceptable media types include text/plain", records.get(0).getMessage());
     }
     
@@ -193,7 +193,7 @@ public class ServiceabilityTest extends 
         WinkLogHandler.turnLoggingCaptureOff();
         ArrayList<LogRecord> records = WinkLogHandler.getRecords();
         
-        assertEquals(1, records.size());
+        assertEquals(2, records.size());
         assertEquals("Processing GET request to http://localhost:80/root, source content type is null, acceptable media types include text/html", records.get(0).getMessage());
     }
     
@@ -210,7 +210,7 @@ public class ServiceabilityTest extends 
         WinkLogHandler.turnLoggingCaptureOff();
         ArrayList<LogRecord> records = WinkLogHandler.getRecords();
         
-        assertEquals(1, records.size());
+        assertEquals(2, records.size());
         assertEquals("Processing GET request to http://localhost:80/root?param1=value1, source content type is null, acceptable media types include text/plain", records.get(0).getMessage());
     }
     
@@ -226,7 +226,7 @@ public class ServiceabilityTest extends 
         WinkLogHandler.turnLoggingCaptureOff();
         ArrayList<LogRecord> records = WinkLogHandler.getRecords();
         
-        assertEquals(1, records.size());
+        assertEquals(2, records.size());
         assertEquals("Processing GET request to http://localhost:80/root/2, source content type is null, acceptable media types include text/plain", records.get(0).getMessage());
     }
     
@@ -265,13 +265,13 @@ public class ServiceabilityTest extends 
                 "  Path: root; ClassMetadata: Class: org.apache.wink.server.serviceability.ServiceabilityTest$MyResource\n" +
                 "  Path: ; ClassMetadata: Class: org.apache.wink.server.internal.resources.HtmlServiceDocumentResource", records.get(2).getMessage());
         assertEquals("The following user-defined JAX-RS providers are registered: \n" +
-                "RawType: interface javax.ws.rs.ext.ContextResolver\nData Map: \n" +
+                "RawType: interface javax.ws.rs.ext.MessageBodyReader\nData Map: {empty}" +
+                "\nRawType: interface javax.ws.rs.ext.MessageBodyWriter\nData Map: {empty}" +
+                "\nRawType: interface javax.ws.rs.ext.ContextResolver\nData Map: \n" +
                 "MediaType key = */*\n" +
                 "ObjectFactory Set value = {\n" +
                 "  class org.apache.wink.server.serviceability.ServiceabilityTest$MyContextResolver1\n" +
-                "}\n" +
-                "\nRawType: interface javax.ws.rs.ext.MessageBodyReader\nData Map: {empty}" +
-                "\nRawType: interface javax.ws.rs.ext.MessageBodyWriter\nData Map: {empty}", records.get(3).getMessage());
+                "}\n", records.get(3).getMessage());
     }
 
 }



Mime
View raw message